解决yacc冲突 - 由于冲突,规则在解析器中无用

时间:2016-03-05 03:02:24

标签: c yacc

我正在处理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 个答案:

答案 0 :(得分:4)

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

 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用分号分隔。当解析器看到"var" ID ;作为预测时,它首先将ID缩减为id,然后需要决定是否将var id缩减为declaration或者转移;以便稍后将其缩减为symbol,然后继续缩减id symbol id。在没有优先规则的情况下,野牛总是解决转移/减少冲突而转向,这就是它在这种情况下的作用。但结果是永远不可能将"var" id减少到declaration,因为减少冲突的解决方案使得生产无用,这或多或少是警告所说的。