1、delim tnws delim+letter A-Za-zdigit 0-9%ws if printf(IF );return(IF);elseELSE return(ELSE);intINT return(BASIC);floatFLOAT breakBREAKreturn(BREAK);doDO return(DO);whileWHILE return(WHILE);trueTRUE return(TRUE);indexINDEX return(INDEX);boolBOOL charCHAR realreturn(REAL);falseFLASE return(FALSE);a-zA-
2、Z_a-zA-Z0-9_* printf(IDreturn(ID);+-?0-9+ printf(NUMreturn(NUM);0-9*.0-9+ printf(GT GE return(GE);+ +- - ();,&return(AND);|return(OR);%token NUM%token ID %token IF WHILE DO BREAK REAL TRUE FALSE BASIC ELSE INDEX GE LE NE EQ AND ORprogram : block printf(program-blockn ;block : decls stmts printf(bloc
3、k-decls stmtsndecls : | decls decl printf(decls-decls declndecl : type ID decl-type id;ntype : type NUM type-typenumn | BASIC printf(basicnstmts : | stmts stmt printf(stmts-stmts stmtnstmt : matched_stmt printf(stmt-matched_stmtn | open_stmt printf(open_stmtnopen_stmt: IF booL stmt printf(open_stmt-
4、if(bool)stmtn | IF matched_stmt ELSE open_stmt printf(if(bool) matched_stmt else open_stmtnmatched_stmt: matched_stmt ELSE matched_stmt printf(matched_stmt-if(bool) matched_stmt else matched_stmtn | other printf(othernother: loc loc=bool; | WHILE while(bool)stmtn | DO stmt WHILE do stmt while(bool);
5、 | BREAK break; | block printf(loc :loc-locbooln | ID printf(idnbooL : booL OR join printf(bool-bool|joinn | join printf(joinnjoin : join AND equality printf(join-join&equalityn | equality printf(equality : equality EQ rel printf(equality-equality=reln | equality NE rel printf(equality!=reln | rel p
6、rintf(relnrel : expr expr printf(rel-expr | expr | expr printf(expr : term printf(expr-expr+termnexpr-termn | term printf(termnterm : term * unary printf(term-term*unaryn | term /term/unaryn | unary printf(unarynunary :unary- | -unaryn | factor printf(factornfactor :factor-(bool)n | loc printf(locn
7、| NUM printf(numn | REAL printf(realn | TRUE printf(truen | FALSE printf(falsen#includelex.yy.cmain(int argc,char *argv) yyparse();yyerror(char *s) fprintf(stderr,error:%sn,s);六、实验结果Lex.l词法分析结果:Yacc.y语法分析结果:.七、实验总结遇到的问题1):刚开始在window环境下使用lex和yacc工具,编写lex.l文件的时候,在识别到if时,return(IF),提示IF没有定义,定义#define I
8、F 265后,在yacc.y文件中,再定义%token IF,发生重定义错误。解决办法:在lex.l文件中,无须定义#define IF 265,只在yacc.y文件中定义%token IF即可,不过在yacc.y中要加入#include”,使两个文件关联起来。遇到的问题2):在使用yacc工具编译yacc.y文件时,提示缺少bison.simple。上网下载一个bison.simple,放到yacc工具主目录下。遇到的问题3):在lex.l和yacc.y文件的第三部分同时写了main函数,导致错误。Lex.l文件中第三部分为空,不需要任何函数。因为关联lex.l和yacc.y后,yypars
9、e()会自动调用yylex()。遇到的问题4):生成yacc.tab.c文件后,放入VC+编译器中编译,提示错误如下:error LNK2001: unresolved external symbol _yyerrorDebug/main.exe : fatal error LNK1120: 1 unresolved externals未找到解决办法,无奈只能放弃window环境,改用linux环境编写。遇到的问题5):IF bool stmt-if(bool)stmtn stmt ELSE stmt printf(if(bool)stmt else stmtn存在冲突。改为:遇到的问题6):
10、这是一个致命性的问题,由于使用的linux下的lex版本太低,导致照抄课本上的ID和NUM正则表达式无法识别,困扰了我很久很久。多亏了朋友的帮助,终于发现错误,把letter(letter|digit)*改为a-zA-Z_a-zA-Z0-9_*;把digit+(.digit+)?(E+-?digit+)?改为+-?0-9+和+-?0-9*.0-9+,分别用于识别整数和浮点数。遇到的问题7):一些小错误,比如词法分析中,漏识别while等,还有把=误当做了EQ。仔细检查lex.l,对错漏的部分进行改补。遇到的问题8):对IF 和IF ELSE消除二义性后,依然存在冲突如下:尚未找到解决办法。本次
11、实验主要是学习结合lex和yacc工具进行语法分析,通过工具文档,了解lex和yacc的编写规则,然后使用教程后的源语言定义规则,即语法分析的各个文法即可编写出正确的yacc.y。在linux下使用lex和yacc比较容易,而在window下使用,就相对麻烦,会遇到的各种问题,所以该实验选用linux环境是不二选择。其次,linux环境可能存在lex和yacc的版本比较低,导致一些教程上的一些正则表达式无法识别,这个错误比较难发现。总之,通过本次实验,用了近一天的时间调试程序,对词法分析和语法分析有了进一步的认识,同时对程序纠错有了进一步的体会,再者更加熟悉了linux环境操作,更加体会到了linux功能的强大。但本实验还有一些令人不太满意的地方,比如*.y文件中依然存在冲突没有解决彻底,而且*.l文件中对于浮点数的识别还是具有一定的局限性,不能识别所有可能出现的浮点数。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1