资源描述
实习一 词法分析
一、实验目的:
通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。
编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。(遇到错误时可显示“Error”,然后跳过错误部分继续显示)。
二、核心代码清单:
1)定义类别编码
public static final int KEY_WORD = 1;
public static final int IDENTIFIER = 2;
public static final int NUMBER = 3;
public static final int OPERATOR = 4;
public static final int DELIMITER = 5;
2) 构造保留字,运算符,分隔符表
// 保留字、运算符、分隔符
private String[] keyword = new String[] { "if", "int", "for", "while",
"do", "return", "break", "continue" };//保留字
private String[] operator = new String[] { "+", "-", "*", "=", ">", ">=",
"==" };//运算符
private String[] delimiter = new String[] { ",", "{", "}", "(", ")", ";" };//分隔符
3) 判断是否为数字,字母函数
① // 判断是否是数字
private boolean isNumber(char c) {
if (c > '9' || c < '0')
return false;
else
return true;
}
②// 判断是否是字母(包括下划线)
// 判断是否是字母
private boolean isChar(char c) {
if ((c <= 'z' && c >= 'A') || c == '_')
return true;
else
return false;
}
4) 字母处理函数
// 处理第一个字符是字母的情况
private char dealWithChar(char c) throws IOException {
boolean flag = true;//是否出现重命名错误
if (Character.isSpace(c)) {
c = (char) fis.read();
return c;
}
String str = new String();
while (isNumber(c) || isChar(c)) // 是数字或字母,则加到str中;不是数字和字母,则str就是识别出的标识符(或保留字)
{
str = str + c;
c = (char) fis.read();
}
if (compare(str, 1)) // 判断是否是保留字
tokens.add(new Token(KEY_WORD, str));
else {
//遍历单词表,查看是否有重命名错误
for (int i = 0; i < tokens.size(); i++) {
Token tk = tokens.get(i);
String tmp = tk.str;//得到字符串
int type = tk.type;//得到类型
//如果新得到的字符串与字符表中的相同且类型为2,则重命名错误
if (str.equals(tmp)&&type==2) {
System.out.println(tmp + " " + "变量重定义错误!");
flag = false;
break;
}
}
if(flag){
flag = true;
tokens.add(new Token(IDENTIFIER, str));
}
}
return c;
}
5) 数字处理函数
// 处理第一个字符是数字的情况.
private char dealWithNumber(char c) throws IOException {
if (Character.isSpace(c)) {
c = (char) fis.read();
return c;
}
String str = new String();
while (isNumber(c)) // 是数字,则加到str中;不是数字,则str就是识别出的数,将str加入到tokens中
{
str = str + c;
c = (char) fis.read();
}
Token token = new Token(NUMBER, str);
tokens.add(token);
return c;
}
6) 其他字符处理函数
// 其它字符的情况
private char dealWithOther(char c) throws IOException {
String str = new String();
if (Character.isSpace(c)) {
c = (char) fis.read();
return c;
}
if (compare(new String() + c, DELIMITER)) {
str = str + c;
tokens.add(new Token(DELIMITER, str));
c = (char) fis.read();
return c;
}
while (compare(new String() + c, OPERATOR)) {
str = str + c;
c = (char) fis.read();
}
if (compare(str, OPERATOR))
tokens.add(new Token(OPERATOR, str));
return c;
}
8) 比较函数
// 将字符串与保留字、运算符、分隔符比较
private boolean compare(String str1, int i) {
switch (i) {
case KEY_WORD:
for (int j = 0; j < keyword.length; j++) {
if (str1.equals(keyword[j])) {
return true;
}
}
break;
case OPERATOR:
for (int j = 0; j < operator.length; j++) {
if (str1.equals(operator[j])) {
return true;
}
}
break;
case DELIMITER:
for (int j = 0; j < delimiter.length; j++) {
if (str1.equals(delimiter[j])) {
return true;
}
}
break;
}
return false;
}
9)进行循环分析
// 执行方法
public void doAnalysis() throws IOException {
char c = (char) fis.read();
while ((int) c != END_OF_FILE) {
if (isChar(c))// 如果开始字符是字母,转入字母处理函数,可能结果为保留字或标识符
c = dealWithChar(c);
else if (isNumber(c))
c = dealWithNumber(c);// 如果开始字符是数字,转入数字处理函数,可能结果为整数
else
c = dealWithOther(c);// 开始字符不是字母数字,则可能为运算符、分隔符
}
}
10) 输出单词符号
// 输出tokens中的内容
public void printTokens() {
for (int i = 0; i < tokens.size(); i++) {
int type = tokens.elementAt(i).type;
String str = tokens.elementAt(i).str;
System.out.println((i + 1) + ": " + "( " + type + ", \"" + str
+ "\")");
}
}
三、程序流程图:
图1 词法分析程序流程图
其他字符
数字字
字母
是
否
否
是
否
是
是
否
此字符串为运算符
此字符串为分隔符
得到字符串
保留字
此字符串为标识符
数字
运算符
字母处理程序
数字处理程序
其他字符处理程序
读入一个字符
字符
开始
读入源程序
定义类别编码
构造保留字、运算符、分隔符表
结束
输出单词符号
写入单词符号表
分析完成
此字符串为保留字
出错处理
分隔符
此字符串为数字
四、 测试:
C语言源程序:
main()
{
int i = 1;
int m = 0;
int i = 0;
for ( i = 1;i < 10; i++)
{
m = m + i;
}
}
输出结果如下图所示::
图1 词法分析器实验结果
五、实验总结:
通过这次实验,我对词法分析器的工作过程有了进一步的理解。词法分析器通过扫描C语言源程序,调用词法分析程序将其分解为各类单词。在实验的过程中,虽然这个程序要求的功能比较简单,但是因为这个程序设计的表比较多,要考虑的东西也比较多,所以在调试的过程中,还是遇到了不少的错误。通过不断地Debug一步一步的执行,找出程序中的bug;经过不断地调试最终成功的完成了此程序。令我印象最深刻的问题是:因为刚开始在定义运算符表和分隔符表的时候,没有将运算符表定义完全,所以在运行程序的时候,程序总是把运算符当作错误来处理,经过不断的调试,终于找到了这样bug。通过此次实验,让我了解到如何设计、编制并调试词法分析程序,加深对词法分析原理的理解;熟悉了构造词法分析程序的手工方式的相关原理,根据识别语言单词的状态转换图;另外,也让我重新熟悉了JAVA的相关内容。总之,通过这次实验,我收获很大。
展开阅读全文