}
}
(4) 正规式的DFA
根据正规式和DFA的构造算法,可以得到最终的简化DFA如下图所示:
*letterletter|digitdigit.digit301digit24*/5/6-7-+ | , | ; | ( | ) (5) 词法分析器的执行流程
(6) 与语法分析器的接口
词法分析器提供记号给语法分析器,它们之间的关系如下图所示:
InitScanner调用返回一个记号语法分析器调用调用GetTokenCloseScanner 2. Java软件包的设计
3. 软件中关键的算法
为了能够在其他的函数中调用GetToken()函数,笔者将该函数定义为public。
这个函数中和C或者C++的不同之处主要在于C中unread函数的实现。为了实现字符的回退,笔者利用了java中的PushbackReader。原因笔者将在后面进行详细叙述。
public Token GetToken() throws Exception
// in order to make it visible,we define it public {
Token token; int Char; char ch; token = new Token(); // 初始化为SEMICO EmptyTokenString(); token.lexeme = TokenBuffer; for (;;) {
}
Char = GetChar(); if (Char == -1) { { }
if (!isspace((char) Char)) { }
break; LineNo++;
token.type = Token_Type.NONTOKEN; return token; ch = (char) Char;
} else if (Char == 13)
AddCharTokenString((char) Char); if (isLetter((char) Char))
// int char之间的转换需要测试…… {
for (;;) { }
BackChar((char) Char);
token = JudgeKeyToken(TokenBuffer.toString()); token.lexeme = TokenBuffer; return token;
Char = GetChar(); if (isalnum((char) Char)) }
AddCharTokenString((char) Char); break; else {
} else if (isDigit((char) Char)) {
for (;;) { }
if ((char) Char == '.') {
AddCharTokenString((char) Char); for (;;) {
Char = GetChar(); if (isDigit((char) Char)) else
break;
AddCharTokenString((char) Char);
}
Char = GetChar(); if (isDigit((char) Char)) else
break;
AddCharTokenString((char) Char);
}// end of if((char)Char == '.') BackChar((char) Char);
token.type = Token_Type.CONST_ID; token.lexeme = TokenBuffer;
token.value = Double.valueOf(TokenBuffer.toString()); // 如此实现atof的功能 return token; switch ((char) Char) { case ';':
token.type = Token_Type.SEMICO; break;
token.type = Token_Type.L_BRACKET; break;
token.type = Token_Type.R_BRACKET; break;
token.type = Token_Type.COMMA; break;
token.type = Token_Type.PLUS; break;
Char = GetChar(); if (Char == '-') { }
Char = GetChar();
while (Char != '\\n' && Char != -1)
Char = GetChar(); BackChar((char) Char); return GetToken(); BackChar((char) Char);
token.type = Token_Type.MINUS; break;
} else {
case '(':
case ')':
case ',':
case '+':
case '-':
} else {
case '/':
}
if (Char == '/') { }
Char = GetChar(); if ((char) Char == '*') { }
token.type = Token_Type.ERRTOKEN; break;
token.type = Token_Type.POWER; break;
BackChar((char) Char); token.type = Token_Type.MUL; break;
while (Char != '\\n' && Char != -1)
Char = GetChar(); BackChar((char) Char); return GetToken(); BackChar((char) Char); token.type = Token_Type.DIV; break;
} else {
case '*':
} else {
default:
}// end of switch((char)Char)
}// end of else return token;
三、测试例程设计与测试结果分析
1. 例程1
(1) 测试例程设计
为了测试词法分析器是否能够正确地分析输入序列和识别记号,而由于笔者刚刚着手Java且时间有限,故只能用Java的控制台进行输入输出。
笔者可以在Java中的Run -> Run Configurations -> Arguments -> Program arguments中给main主函数传递参数。 (2) 测试结果
test1.txt文件内容如下: origin is (100, pi+300); --here are notes.
for T from 0 to 120 step 1 draw (t, -t);
在这里,笔者特意加了—行表示注释,而且其中的还用的是小写的表示符,因为根据笔者程序的设计,不仅可以调过注释,而且还可以使得程序对大小写不敏感,这样无