代码之家  ›  专栏  ›  技术社区  ›  neomang

解决yacc冲突-由于冲突,解析器中的规则无效

  •  0
  • neomang  · 技术社区  · 9 年前

    我正在使用一个yacc文件来解析给定的文件并将其转换为等效的c++文件。我根据提供的语法图创建了以下语法:

    program:    PROGRAMnumber id 'is' comp_stmt
                ;
    
    comp_stmt:    BEGINnumber statement symbol ENDnumber
                  ;
    
    statement:    statement SEMInumber statement 
                  | id EQnumber expression
                  | PRINTnumber expression
                  | declaration
                  ;
    
    declaration:    VARnumber id
                    ;
    
    expression:    term
                   ;
    
    term:    term as_op term
             | MINUSnumber term
             | factor
             ;
    
    factor:    factor md_op factor
               | ICONSTnumber
               | id
               | RPARENnumber expression LPARENnumber
               ;
    
    as_op:    PLUSnumber
              | MINUSnumber
              ;
    
    md_op:    TIMESnumber
              | DIVnumber
              ;
    
    symbol:    SEMInumber
               | COMMAnumber
               ;
    
    id:    IDnumber
           | id symbol id
           ;
    

    我剩下的唯一问题是,我在尝试用yacc编译时收到了这个错误。

    conflicts: 14 shift/reduce
    calc.y:103.17-111.41: warning: rule useless in parser due to conflicts: declaration: VARnumber id
    

    我已经解决了我遇到的唯一一个其他冲突,但我不确定这个冲突的解决方法是什么

    var a, b, c, d;
    

    var a;
    
    1 回复  |  直到 9 年前
        1
  •  4
  •   rici    9 年前

    所有用于派生列表的生成都是不明确的,因此会产生reduce/reduce冲突。例如:

     id: id symbol id
    

    当有三个标识符时,会很明显地模棱两可:是先减少前两个,还是减少后两个?通常的列表习惯用法是左递归:

    id_list: id | id_list `,` id
    

    对于大多数语言,这对于语句是不正确的 结束 带分号,不是 分离的 但该模型适用于逗号分隔的标识符列表,或加法运算符的左关联序列。

    对于语句,您可能需要更类似的内容:

    statement_list: | statement_list statement ';' 
    

    说到 symbol ,你真的相信吗 , ; 有相同的句法功能吗?这似乎不太可能,因为你写 var a, b, c, d; 而不是例如, var a; b, c; d, .

    野牛发出的“无用规则”警告正是因为你的语法允许 id s用分号分隔。当解析器看到 "var" ID 具有 ; 作为前瞻,它首先减少 ID 身份证件 然后需要决定是否减少 var id declaration 或将 ; 以便以后将其减少到 象征 然后继续减少 id symbol id 。在没有优先规则的情况下,野牛总是通过转移来解决转移/减少冲突,因此在这种情况下它就是这样做的。但结果是永远不可能减少 "var" id 公告 ,使生产因转变而变得无用,减少了冲突解决,这或多或少是警告所说的。