运行生成的YACC解析器产生意外的语法错误

时间:2016-09-18 16:24:10

标签: c bison yacc

例如我有代码

%nonassoc lower
%nonassoc ELSE

if_stmt: IF '(' expr ')' statement   %prec lower
         {
            /*some code*/
         }
       | IF '(' expr ')' statement ELSE statement
         {
            /*some code*/
         }
       ;

根据规则和代码(不做太多)我现在得到" elsesyntax 错误"当我测试IF-ELSE语句时。如果它只是一个IF语句,它可以正常工作。

我认为我应该在第二个动作中传递一些东西以使其起作用,但我不确定是什么。

如果可能的话,我不想将这两项行动分开。

编辑:所以这里是被问及的语法和优先级: EDIT2:实现了我的语法规则。复合_stmt和local_declarations是评论因为我还不知道如何处理它们。

%nonassoc islowerthanelse
%nonassoc ELSE

%%

%token <intVal> NUM WHILE PRINT IF ELSE INT 

program            :    declaration_list statement_list       
                         {
                         printf("/0\n");

                         }
                         ;                                    

declaration_list   :    declaration_list declaration          
                          {
                            printf("/1\n");
                            $$ = make_node(DeclSeq, NULL, $1, $2, NULL, NULL);
                          }
                         |declaration 
                         {
                            printf("/2\n");
                            $$ = $1;
                         }                        
                         ;

declaration        :    type_specifier ID ';'                  
                          {
                            printf("/3\n");
                            $$ = make_node(Decl, p3, $1, NULL, NULL, NULL);
                           }

type_specifier     :    INT                                   
                          {
                            printf("/5\n");
                            $$ = make_node(INT, NULL, NULL, NULL, NULL, NULL);

                          }
                         ;

statement_list     :    statement_list statement              
                         {
                           printf("/6\n");
                           $$ = make_node(StmtSeq, NULL, $1, $2, NULL, NULL);
                         }
                         |/* EMPTY */
                          {
                            printf("/7\n");
                            $$ = make_node(astEmptyStmtSeq, NULL, NULL, NULL, NULL, NULL);

                          }
                         ;

statement          :    expression_stmt                       
                          {
                            printf("/8\n");
                            $$ = $1;
                          }
                         /*|compound_stmt                       
                          {
                            $$ = $1;
                          }*/
                         |selection_stmt                      
                          {
                            $$ = $1;
                          }
                         |iteration_stmt                      
                          {
                            $$ = $1;
                          }
                         |print_stmt                          
                          {
                            printf("/12\n");
                            $$ = $1;
                          }
                         ;

/*compound_stmt      :    '{' local_declarations statement_list '}' 
                         ;

local_declarations :    local_declarations declaration
                         |/* EMPTY *\
                         ;*/

expression_stmt    :    expression ';'                       
                          {
                            printf("/15\n");
                            $$ = make_node(ExprStmt, NULL, $1, NULL, NULL, NULL);
                          }                 
                         |/* EMPTY */ ';'
                          {
                            printf("/16\n");
                            $$ = make_node(EmptyExprStmt, NULL, NULL, NULL, NULL, NULL);
                          }
                         ;

selection_stmt     :    IF '(' expression ')' statement      %prec islowerthanelse      
                          { printf("/256\n");
                            $$ = make_node(IfStmt, NULL, $3, $5, NULL, NULL);

                          }      
                         |IF '(' expression ')' statement ELSE statement 
                          {printf("/257\n");
                            $$ = make_node(IfElseStmt, NULL, $3, $5, $7, NULL);
                          }                    
                         ;

iteration_stmt     :    WHILE '(' expression ')' statement
                          {
                            $$ = make_node(astWhileStmt, NULL, $3, $5, NULL, NULL);
                          }
                          ;

2 个答案:

答案 0 :(得分:0)

行动是相互独立的;没有“堕落”。如果要在两个动作之间重构公共代码,请将其放入可以从动作中调用的函数中。

但是,这应该与您看到的语法错误无关。操作不会影响解析;如果解析器报告语法错误,它将执行此操作而不运行任何操作(因为错误反映了无法找到适当的生产)。

答案 1 :(得分:0)

来自片段节目的最佳猜测 - 您的%prec lower实际上具有比ELSE令牌更高的优先级,因此当看到ELSE时,它会减少第一个规则,然后获得语法错误,因为它无法在缩减后对ELSE执行任何操作。

然而,实际上回答这个问题需要看到完整的语法。

我在你的语法中添加了以下内容来制作一个MVCE:

%{
#include <stdio.h>
#define make_node(...)  0
%}

%nonassoc islowerthanelse
%nonassoc ELSE

%token NUM WHILE PRINT IF INT ID
%token expression print_stmt

%%

%%
#include "lex.yy.c"
int main() { return yyparse(); }
int yywrap() { return 1; }
void yyerror(const char *msg) { printf("%s\n", msg); }

除了一个微不足道的词法分子:

%%
"while" return WHILE;
"print" return PRINT;
"if" return IF;
"else" return ELSE;
"int" return INT;
"expression" return expression;
[A-Za-z][A-Za-z0-9]* return ID;
[0-9]* return NUM;
[ \t\n] ;
. return *yytext;

和输入文件如:

int A;
if (expression) expression; else expression;

它似乎工作得很好......

$ a.out <input.txt/5
/3
/2
/7
/15
/8
/15
/8
/257
/6
/0