Parsing 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"); }

对于int或float变量声明,我有以下yacc解析器(没有任何冲突):

%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()解决了这个问题。