Parsing Yacc一次声明失败,但成功减少了两次声明
对于int或float变量声明,我有以下yacc解析器(没有任何冲突):Parsing Yacc一次声明失败,但成功减少了两次声明,parsing,bison,yacc,Parsing,Bison,Yacc,对于int或float变量声明,我有以下yacc解析器(没有任何冲突): %token ID INT FLOAT %token SEMICOLON %% program : list_declaration { printf("program\n"); } ; list_declaration : declaration { printf("list_declaration\n"); }
%token ID INT FLOAT
%token SEMICOLON
%%
program : list_declaration { printf("program\n"); }
;
list_declaration : declaration { printf("list_declaration\n"); }
| declaration declaration { printf("list_declaration\n"); }
;
declaration : var_declaration { printf("declaration\n"); }
;
var_declaration : type ID SEMICOLON { printf("var_declaration\n"); }
;
type : INT { printf("type\n"); }
| FLOAT { printf("type\n"); }
;
%%
我一直在绞尽脑汁试图解决这个问题,但没有找到任何解决办法。
如果有两个变量声明作为输入,如:
int test;
float test2;
其解析正常,以下是输出:
type
var_declaration
declaration
type
var_declaration
declaration
list_declaration
program
但如果只有一个声明,解析器就不会将其简化为程序,例如:
int test;
给出:
type
var_declaration
declaration
难道不应该将声明简化为list_声明,然后将list_声明简化为程序吗?我计划稍后将list_声明扩展到任意数量的声明,但是我不能这样做,除非我首先理解为什么它不能对至少两个声明正常工作。问题几乎肯定是您正在抑制
yylex
返回的EOF
yylex
必须在EOF时返回0;否则,bison
解析器无法可靠地识别开始生产
与大多数解析器生成器一样,正如大多数解析教科书中所描述的那样,bison和yacc创建了一个“增强”的开始生成,其右侧由声明的(或隐式的)开始非终结符,后跟一个EOF
伪标记。只有当生产量减少时,解析才会成功,并且如果没有EOF
,生产量就不能减少
由于
bison
将在没有前瞻的情况下减少不需要前瞻的状态,因此bison
可以使用语法将声明
减少为程序
,而无需前瞻。但是如果没有EOF
lookahead,它不能将declaration
简化为program
,因此它不能。在有两个声明的情况下
,尽管减少了程序
,但解析实际上没有成功,yyparse
将不会返回。扫描仪是否尝试拦截EOF
?还是让flex自由地做正确的事情?@rici我的扫描器捕获eof,因为我使用指向文件的指针作为yyin,所以我有“do{yyparse();}而(!feof(yyin));”不,你没有。如果你这样做了,在扫描仪中捕获EOF将是错误的;为此,您应该使用yywrap
。您的list\u声明
产品只允许一个或两个声明。应该是list_declaration:declaration{…}list_declaration{…}
谢谢@rici,正是使用yywrap()解决了这个问题。