如何在yacc文件中找到shift / reduce冲突

问题描述 投票:0回答:1

在编译我的yacc文件时,我得到了shift / reduce冲突。我似乎无法解决,所以我怎么能找到它?该错误指向第73行,这是auxVartSpec生产定义的行,特别是它的第二个生产auxVarSpec COMMA ID,但我已经为这些令牌设置了de优先级。

%

%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                
%%
c yacc lex
1个回答
2
投票

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

在这些冲突中,有72个是一个简单的拼写错误的结果。你的语法在NE的制作中使用了令牌名称GELEExpr,但你的优先声明是针对令牌NEQGEQLEQ。这会产生关于未使用令牌的警告。 (也没用过的是STARRESERVED。我想你不小心遗漏了Expr规则进行乘法。)

剩下的冲突发生在45国,其项目是(来自报告文件):

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

COMMA     shift, and go to state 68
COMMA     [reduce using rule 9 (auxVarSpec)]

所以在这种状态下,逗号可以被移动,继续生产43.或者它可以使用规则9(auxVarSpec: %empty)触发减少。这种减少是可能的,因为有一个项目使用auxVarSpec作为其下一个非终端,并且auxVarSpec以逗号开头,如果它不是空的。

为了更清楚,问题是在列表VarsAndStatements中,可能有一个VarDeclaration(这是一个声明),但也可能有一个ParseArgs(这是一个声明)。所以ParseArgsVarDeclaration都是可能的,他们两个都可以从ID COMMA开始,但其中一个需要减少IDCOMMA之间空的右侧。

如果没有额外的前瞻标记就无法解决这个冲突:如果逗号后跟另一个ID,则解析器正在查看VarDeclaration,而如果逗号后跟BLANKID(无论是什么),那么它必须是ParseArgs

尽管冲突无法按照书面形式解决,但可以通过延迟转换/减少决策的常用技术来避免冲突。特别是,有必要区分三种情况:

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

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

VarDeclaration: VAR VarSpec
              | ID Type
              | ID COMMA ID auxVarSpec Type
© www.soinside.com 2019 - 2024. All rights reserved.