当然 是在做语法分析器的时候。
几个要点,也许对大家做prase的时候有帮助。
1)很多例子在lex中用宏定义#define定义了token的值这样无论是定义还是修改起来都很麻烦。
其实只需在lex中 加入这么一句:#include "y.tab.h"。然后在yacc XXX.y的时候加上参数-d(即yacc -d XXX.y) 编译器会自动生成y.tab.h,它会根据你在.y文件中%token定义的记号去自动生成定义了token的值宏定义#define的头文件。
2)也许每个人都会遇到悬空的else所带来的二义性。
if_stmt : IF '(' expression ')' statement
| IF '(' expression ')' statement ELSE statement
;
这个语句在yacc的时候会提示一个移动归约冲突。
但是,你们又会看见文献中说yacc规定移进优先。照理说这样就已经解决了悬空的else所带来的二义性(else移进优先)。但是很多文章都没有提到,要在.y文件中声明%expect 1 表示告诉编译器预见一次的移动归约冲突。这样就可以正常编译了。:-)
3)当然 还有许多的细节。比如在.y中存在的如运算符之类的token 都必须从lex中传来。即使是 '+ ' , '(' 这样的一元字符,都要再.lex中返回 —— "+" {return '+'} 返回其ASC2码。
4)如何让你的语法分析器找到错误呢?
这就是yyerror的功能了 这个龙书上有例子 我就不说了。你可以自己写yyerror函数,让它按照你的格式显示。但是如何知道错误在第几行?yylineno参数有时候不会自动支持,这个只要在.lex中对回车进行处理—— \n {yylineno++;}即可。