对于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_declaration然后list_declaration减少到程序?我计划稍后将list_declaration扩展到任意数量的声明,但我不能这样做,除非我先了解为什么至少两个声明不能正常工作。
答案 0 :(得分:1)
问题几乎可以肯定是您正在取消EOF
yylex
的回复。 yylex
必须在EOF上返回0;否则,bison
解析器无法可靠地识别开始生产。
与大多数解析器生成器一样 - 并且如大多数解析教科书中所述 - bison和yacc创建了一个"增强的"开始生产,其右侧由声明的(或隐式的)起始非终端组成,后跟一个EOF
伪令牌。只有在减少生产时,解析才会成功,如果没有EOF
,则无法减少生产。
由于bison
对于不需要前瞻的状态会毫不前瞻地减少,因此,bison
可以使用您的语法将declaration declaration
缩减为program
而不用前瞻。但如果没有declaration
前瞻,它就无法将program
缩减为EOF
,因此它不会。对于有两个declarations
的情况,尽管program
已经减少,但解析实际上并没有成功,yyparse
也不会返回。