Yacc失败了一个声明,但成功减少了两个声明

时间:2014-06-21 00:09:51

标签: 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"); } 
                       | 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扩展到任意数量的声明,但我不能这样做,除非我先了解为什么至少两个声明不能正常工作。

1 个答案:

答案 0 :(得分:1)

问题几乎可以肯定是您正在取消EOF yylex的回复。 yylex 必须在EOF上返回0;否则,bison解析器无法可靠地识别开始生产。

与大多数解析器生成器一样 - 并且如大多数解析教科书中所述 - bison和yacc创建了一个"增强的"开始生产,其右侧由声明的(或隐式的)起始非终端组成,后跟一个EOF伪令牌。只有在减少生产时,解析才会成功,如果没有EOF,则无法减少生产。

由于bison对于不需要前瞻的状态会毫不前瞻地减少,因此,bison可以使用您的语法将declaration declaration缩减为program而不用前瞻。但如果没有declaration前瞻,它就无法将program缩减为EOF,因此它不会。对于有两个declarations的情况,尽管program已经减少,但解析实际上并没有成功,yyparse也不会返回。