词法分析程序Word文件下载.docx
- 文档编号:17334357
- 上传时间:2022-12-01
- 格式:DOCX
- 页数:12
- 大小:120.97KB
词法分析程序Word文件下载.docx
《词法分析程序Word文件下载.docx》由会员分享,可在线阅读,更多相关《词法分析程序Word文件下载.docx(12页珍藏版)》请在冰豆网上搜索。
(2)确定今后其他实验中要设计编译器的语言,如:
C-语言,其定义在《编译原理及实践》附录A中。
也可选择其它语言,不过要有该语言的详细定义(可仿照C-语言)。
一旦选定,不能更改,因为要在以后继续实现编译器的其它部分。
鼓励自己定义一门语言。
(3)根据该语言的关键词和识别的词法单元以及注释等,确定关键字表,画出所有词法单元和注释对应的DFA图。
(4)仿照前面学习的词法分析器,编写选定语言的词法分析器。
(5)准备2~3个测试用例,要求包含正例和反例,测试编译结果。
四、系统设计
(一)阅读已有编译器的经典词法分析源程序。
a)实验分析:
词法分析器,有的教材又称扫描器,我倒是觉得扫描器更加符合其本意,因为词法分析器的主要作用是将文本代码流解析成一个个记号,供语法分析使用。
由于上一次实验,TINY编译器已经相对比较熟悉,这一次主要关注词法分析器的部分,即SCAN.C。
就词法分析器本身的写法而言,并没有所谓的标准代码,不过经典代码还是很有参考价值的,而修改经典的过程也是体会经典的最佳形式。
b)实验过程:
此时实验我选择的仍然是TINY编译器,它的词法分析部分是SCAN.C文件。
A.调用词法分析器的形式:
在主函数中有如上语句是调用SCAN.C中的getToken()函数。
getToken()即词法分析器进行状态转换的核心部分,它其实就是一个自动机。
B.词法分析器中的常量:
状态枚举:
枚举的最大好处在于能够用字符(状态)代替数字,而且将这些封装在一个结构中。
/*statesinscannerDFA*/
Typedefenum
{START,INASSIGN,INCOMMENT,INNUM,INID,DONE,INLESS,INMORE,INEQ,INNEQ,INCOM,INNCOM}StateType;
保留字的标识符
/*lexemeofidentifierorreservedword*/
chartokenString[MAXTOKENLEN+1];
处理输入缓存以及当前指针位置的相关存储
#defineBUFLEN256
staticcharlineBuf[BUFLEN];
/*holdsthecurrentline*/
staticintlinepos=0;
/*currentpositioninLineBuf*/
staticintbufsize=0;
/*currentsizeofbufferstring*/
staticintEOF_flag=FALSE;
/*correctsungetNextCharbehavioronEOF*/
保留字的结构体,这一部分可以清晰的看到所有保留字
/*lookuptableofreservedwords*/
staticstruct
{char*str;
TokenTypetok;
}reservedWords[MAXRESERVED]
={{"
if"
IF},{"
int"
INT},{"
else"
ELSE},{"
return"
RETURN},
{"
VOID"
VOID},{"
while"
WHILE}
};
C.词法分析器的相关函数
处理文件输入相关:
这两个函数是一对,前者是从缓存中读取下一个字符,后者则将当前读取的字符重新放回缓存。
后者存在的最大的价值在于,当用下一字符的情况判断将跳转到什么状态时,如果该字符不属于当前标示符,则放回缓存,以保证下一标示符的获取不受影响。
staticintgetNextChar(void)
staticvoidungetNextChar(void)
staticTokenTypereservedLookup(char*s)
{inti;
for(i=0;
i<
MAXRESERVED;
i++)
if(!
strcmp(s,reservedWords[i].str))
returnreservedWords[i].tok;
returnID;
}
判断字符是否为保留字:
对于读入的单词,我们需要知道其到底是一个变量名还是一个保留字,这个时候就需要调用该函数。
利用for循环在所有保留字中搜寻,有匹配的就说明是一个保留字,否则就是变量名。
DFA实现算法:
其逻辑很清楚:
从START状态开始,每获取一个字符,就根据字符情况跳转到相应的下一状态,如果跳转到接受态DONE,则输出。
输出是调用UTIL.C文件完成的。
(二)用C或JAVA语言编写一门语言的词法分析器。
通过上面的实验我们已经了解了简单的词法分析器。
而编写一个语言的词法分析器,我们首先要知道它含有什么关键字,有哪些专用符号,什么是特殊标记,以及其他符号或者注释情况。
A.语言确定:
我选择C-语言,因为要在以后的实验中继续完善其他部分,所以我希望按照一个完整的工程制作。
因此仿照TINY编译器的形式,将每一部分的功能集中在一个文件中,有globals文件对全局变量进行定义,有util专职输出,有main文件作为主函数,调用其他的函数。
然后定义SCAN函数进行词法分析。
B.定义关键字
关键字是保留字:
IF,ELSE,INT,RETURN,VOID,WHILE
在globals.h里面写入保留字信息
/*reservedwords关键字-保留字*/
IF,ELSE,INT,RETURN,VOID,WHILE,
在scan里面选择关键字信息更改
}reservedWords[MAXRESERVED]//保留字个数
INT},
RETURN},{"
void"
C.符号
/*specialsymbols*/
PLUS,MINUS,TIMES,OVER,//加减乘除
LT,LE,MT,ME,EE,NE,ASSIGN,SEMI,COMMA,LPAREN,RPAREN,LFPAREN,RFPAREN,LDPAREN,RDPAREN
专用符号:
+-*/<
<
=>
>
===!
==;
()[]{}/**/
/*multicharactertokens*/
ID,NUM,
其他标记是ID和NUM,通过下列正则表达式定义:
空格由空白、换行符和制表符组成。
当然这些是要被忽略的。
注释用符号/*...*/围起来。
D.状态转移分析:
由于C-的词法更加复杂,所以状态也比TINY多很多,我定义了10个状态。
主要因为以下标示符是由多字符组成,所以不得不为每一种生成状态记录:
字母,数字,<
=,>
=,==,!
=,/*,*/
在SCAN.C中的状态定义如下:
typedefenum
{START,INNUM,INID,INLE,INME,INEE,INNE,INCOMMENT,OUTCOMMENT,DONE}
StateType;
状态图如下:
E.DFA实现代码:
while(state!
=DONE)
{intc=getNextChar();
save=TRUE;
//
switch(state)
{caseSTART:
if(isdigit(c))
state=INNUM;
elseif(isalpha(c))
state=INID;
elseif(c=='
<
'
)
state=INLE;
>
state=INME;
='
state=INEE;
elseif(c=='
!
state=INNE;
/'
){
ints=getNextChar();
if(s=='
*'
//ungetNextChar();
save=FALSE;
state=INCOMMENT;
}
else{
state=DONE;
ungetNextChar();
currentToken=OVER;
}
elseif((c=='
'
)||(c=='
\t'
\n'
))
save=FALSE;
else
{state=DONE;
switch(c)
{caseEOF:
currentToken=ENDFILE;
break;
case'
+'
:
currentToken=PLUS;
-'
currentToken=MINUS;
currentToken=TIMES;
这一次采用TINY的switch-case格式,因为这种形式更加方便。
部分代码如上。
由于无论是字符还是状态都增加了很多,代码量也稍有增加。
F.修改输出函数:
UTIL.C文件中的关键语句关系到词法分析的输出,因此需要重新写。
以便能够在CMD中看到词法分析的结果。
casePLUS:
fprintf(listing,"
+\n"
);
caseMINUS:
-\n"
caseTIMES:
*\n"
caseOVER:
/\n"
caseLT:
\n"
caseLE:
=\n"
caseMT:
caseME:
caseEE:
==\n"
caseNE:
caseASSIGN:
caseSEMI:
;
caseCOMMA:
\n"
caseLPAREN:
(\n"
caseRPAREN:
)\n"
caseLFPAREN:
[\n"
五、实验测试
(一)测试结果
(二)测试结果
C-语言的源程序:
{SampleprograminTINY}
readx;
{inputaninteger}
if0<
xthen
fact:
=0;
else
=1;
writefact
end
六、实验心得
a)实验问题:
1)程序进入死循环,或者一直报错:
程序不能正确执行,肯定出在细节处,我开始以为是逻辑处出错,一直在检查语句,结果很长时间都没有发现问题。
后来排除了所有可能,我检查了一下最开始制作的状态转移表,果然就发现了问题的所在:
状态转换中本应跳转到DONE,因为失误写成了START,结果跳转到了START。
2)就词法分析器本身而言,并不一定要按照TINY的形式写,其实可以自己创造数据存储格式,自己逐单词判断,比如用hash表来实现存储,以此实现DFA。
只不过不好继续扩展。
我本想自己重新用一种方法,后来发现时间有限,就放弃了。
b)实验心得:
由于有了第一次的实验的基础,转化成一个DFA的思想是非常清晰而简单的,然而实现的过程不是一帆风顺的,中间任何一个环节都可能会出现很多小问题,一个小细节没有处理好,可能会导致整个程序的崩溃,所以需要耐心和细心。
我在做的过程中,曾经因为一个状态打错,导致跳转时有误,开始一直怀疑是逻辑问题,不曾检查状态表的错误,导致延误了很久。
我觉得纠错的过程就像是推理和演绎,虽然有DEBUG,不过我使用的比较少,单纯通过输出推测出错的地方会是哪里,我喜欢这个过程。
当一个完整的词法分析结果出现在CMD中时,突然觉得这是最美的文字。
七、附录(源代码及注释)
代码附在文件夹里面
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 词法 分析 程序