如何在yacc文件中查找移位/减少冲突

时间:2019-03-30 21:07:22

标签: c yacc lex

在编译yacc文件时,出现移位/减少冲突。我似乎无法解决,那么如何找到它?错误指向第73行,这是auxVartSpec生产定义的行,特别是第二生产auxVarSpec COMMA ID的行,但是我已经为这些令牌设置了优先级。

%

%token <value> SEMICOLON BLANKID PACKAGE RETURN AND ASSIGN STAR COMMA DIV EQ GE GT LBRACE LE LPAR LSQ LT MINUS MOD NE NOT OR PLUS RBRACE RPAR RSQ ELSE FOR IF VAR INT FLOAT32 BOOL STRING PRINT PARSEINT FUNC CMDARGS RESERVED ID INTLIT REALLIT STRLIT

%type <node> Program Declarations VarDeclaration VarSpec Type FuncDeclaration FuncHeader Parameters FuncBody VarsAndStatements Statement ParseArgs FuncInvocation Expr auxDeclarations auxVarSpec auxParameters auxStatement auxFuncInvocation opcType opcParameters opcExpr opcFuncInvocation 


%nonassoc   IFX
%nonassoc   ELSE

%left  COMMA
%right  ASSIGN
%left   OR
%left   AND
%left   EQ NEQ
%left   LT GT LEQ GEQ
%left   PLUS MINUS
%left   STAR DIV MOD
%right  NOT

%%

Program: PACKAGE ID SEMICOLON Declarations                  
       ;                                   

Declarations: auxDeclarations                       

auxDeclarations: %empty                             

           | auxDeclarations VarDeclaration SEMICOLON                
           | auxDeclarations FuncDeclaration SEMICOLON      
           ;

VarDeclaration: VAR VarSpec                     

          | ID auxVarSpec Type                  

        ;                                                               
VarSpec: ID auxVarSpec Type                                         
           ;
auxVarSpec: %empty                          
      | auxVarSpec COMMA ID                     
      ;

Type: INT                   

    | FLOAT32                   

    | BOOL                  

    | STRING                    

    ;

FuncDeclaration: FUNC FuncHeader FuncBody            
           ;
FuncHeader: ID LPAR opcParameters RPAR opcType            
       ;

opcType: %empty                 
    | Type                  
        ;

Parameters: ID Type auxParameters       

opcParameters: %empty               
         | Parameters           
         ;

auxParameters: %empty               

         | auxParameters COMMA ID Type  
         ;

FuncBody: LBRACE VarsAndStatements RBRACE             

VarsAndStatements: VarsAndStatements SEMICOLON            

         | VarsAndStatements VarDeclaration SEMICOLON 

         | VarsAndStatements Statement SEMICOLON      

         | %empty                         

         ;

Statement: ID ASSIGN Expr                   


     | LBRACE auxStatement RBRACE               

     | IF Expr LBRACE auxStatement RBRACE %prec IFX     

     | IF Expr LBRACE auxStatement RBRACE ELSE LBRACE auxStatement RBRACE       


         | FOR opcExpr LBRACE auxStatement RBRACE       


     | RETURN opcExpr                       

     | FuncInvocation                   

     | ParseArgs                        

     | PRINT LPAR Expr RPAR                 

     | PRINT LPAR STRLIT RPAR               

     ;

opcExpr: %empty                 
       | Expr                   
       ;

auxStatement: %empty                               
        | auxStatement Statement SEMICOLON                 
        ; 

ParseArgs: ID COMMA BLANKID ASSIGN PARSEINT LPAR CMDARGS LSQ Expr RSQ RPAR 


FuncInvocation: ID LPAR opcFuncInvocation RPAR  

auxFuncInvocation: %empty               
         | COMMA Expr           
         ;

opcFuncInvocation: %empty           
         | Expr auxFuncInvocation     
         ;

Expr: Expr OR Expr              

    | Expr AND Expr             


    | Expr LT  Expr             


    | Expr GT  Expr             


    | Expr EQ  Expr             


    | Expr NE  Expr             


    | Expr LE  Expr             


    | Expr GE  Expr             


    | Expr PLUS  Expr               

    | Expr MINUS  Expr              


    | Expr DIV  Expr                


    | Expr MOD  Expr                


    | NOT Expr                  


    | MINUS Expr                


    | PLUS Expr                 


    | INTLIT                    


    | REALLIT                   


    | ID                    

    | FuncInvocation                

    | LPAR Expr RPAR                
%%

1 个答案:

答案 0 :(得分:2)

您看到的错误消息表示文件中存在73个移位/减少冲突,而不是在第73行存在移位/减少冲突。(移位/减少冲突对应于解析器状态,而不是行号。您可以通过使用-v命令行选项生成报告文件来查看冲突的位置。)

在这些冲突中,有72个是简单拼写错误的结果。您的语法在NE的生产中使用标记名称GELEExpr,但是您的优先声明是针对标记NEQ,{{1}的}和GEQ。这将产生有关未使用令牌的警告。 (LEQSTAR也未使用。我想您不小心忽略了RESERVED乘法规则。)

剩余的冲突位于状态45中,其项目为(来自报告文件):

Expr

(每个产品所附的数字是产品编号,而不是生产线编号。产品编号位于报告文件的顶部,但是由于也列出了产品,因此它们在这里没有太大区别。每个作品中的State 45 7 VarDeclaration: ID . auxVarSpec Type 29 Statement: ID . ASSIGN Expr 43 ParseArgs: ID . COMMA BLANKID ASSIGN PARSEINT LPAR CMDARGS LSQ Expr RSQ RPAR 44 FuncInvocation: ID . LPAR opcFuncInvocation RPAR 表示前瞻点。除非您指定.

,否则不会显示开头为前瞻点的作品。

冲突与前瞻--report=itemset

COMMA

因此,在这种状态下,可以移动逗号以继续生产43。或者可以使用规则9(COMMA shift, and go to state 68 COMMA [reduce using rule 9 (auxVarSpec)] )触发减少。这种减少是可能的,因为存在一个以auxVarSpec: %empty作为下一个非终结符的项目,如果auxVarSpec不为空,则以逗号开头。

更明确地说,问题在于列表auxVarSpec中可能有一个VarsAndStatements(这是一个声明),但也可能有一个VarDeclaration(这是一个声明一份声明)。因此ParseArgsParseArgs都是可能的,并且它们都可以以VarDeclaration开头,但是其中之一需要减少ID COMMAID之间的空白右侧。 COMMA

没有额外的先行标记就无法解决该冲突:如果逗号后跟另一个ID,则解析器将查看VarDeclaration,而如果逗号后跟{ {1}}(无论是什么),那么它必须是BLANKID

尽管不能按书面方式解决冲突,但可以通过推迟移位/减少决策的常规技术来避免冲突。特别是,有必要区分三种情况:

ParseArgs

一种方法是添加一个明显多余的产品:

ID Type                /* VarDeclaration */
ID COMMA ID ...        /* VarDeclaration */
ID COMMA BLANKID ...   /* ParseArgs */