我正在开发一个简单的解释器,我正在使用 bison 和 flex 作为我的词法分析器和解析器。当涉及到解析器时我遇到了问题:
progr :decl_classes decl_gvars decl_functions block {printf("The programme is correct!\n");}
;/*1. classes 2.global vars 3.functii 4.enetry point*/
decl_classes :decl_class ';' decl_classes
|{cout<<"No more classes\n";}
;
decl_class :CLASS ID '{' decl_gvars decl_functions '}' {cout<<"We have a class :"<<$2<<"\n";}
;
decl_functions :{cout<<"No more functions\n";}
|decl_function ';' decl_functions
;
decl_function :TYPE ID '('list_param')' '{'list'}'
;
decl_gvars :decl_gvar ';' decl_gvars
|{cout<<"No more gvars\n";}
;
decl_gvar :typedecl list_ID {cout<<"We have vars "<<endl;}
;
typedecl : TYPE {cout<<"Try to make a var\n";}
;
list_ID : ID '[' expr ']'
| ID
| ID ',' list_ID
;
list_param :param ',' list_param
|/*none*/
;
param :typedecl ID
|typedecl ID '['expr']'
;
block : BGIN list END
;
list : statement ';'
| list statement ';'
|/*none*/
;
解析器总是选择使用 decl_gvar 而不是 decl_function。任何帮助将不胜感激。
我测试了解析器是否会生成我的 decl_function(如果它是隔离的)并且确实如此。
基本问题是,在看到
TYPE
后,当下一个标记是 ID
时,它还不知道它是在查看 decl_function 还是 decl_gvar,但你的语法强制它将 typedecl
减少到识别 decl_gvar 或不简化它以识别 decl_function。由于默认情况下会优先于归约进行移位,因此解析器将始终尝试将其解析为 decl_function,即使它实际上是 decl_gvar (并且在这种情况下会出现语法错误。
最简单的解决方法是摆脱
typedecl : TYPE
规则(并在 decl_gvar 规则中将 typedecl
替换为 TYPE
。这样,您就不需要减少,事情将被推迟到 ID
之后)
标记,因此它将能够看到 (
来识别函数,或者看到 ,
或 ;
来识别 gvar。