优先级与后缀/中缀运算符冲突

时间:2013-01-20 08:27:35

标签: parsing shift-reduce-conflict lemon

这是为柠檬解析器生成器编写的语法:

%left  PostDecrementation.
%right PreDecrementation.

program ::= expression.
expression ::= Terminal.
expression ::= unaryoperation.
unaryoperation ::= Decrementation expression. [PreDecrementation]
unaryoperation ::= expression Decrementation. [PostDecrementation]

尝试编译时,生成器会产生以下冲突:

State 0:
      program ::= * expression
      expression ::= * Null
      expression ::= * unaryoperation
      unaryoperation ::= * Decrementation expression
      unaryoperation ::= * expression Decrementation

                      Null shift  5
            Decrementation shift  1
                   program accept
                expression shift  2
            unaryoperation shift  4

State 1:
      expression ::= * Null
      expression ::= * unaryoperation
      unaryoperation ::= * Decrementation expression
      unaryoperation ::= Decrementation * expression
      unaryoperation ::= * expression Decrementation

                      Null shift  5
            Decrementation shift  1
                expression shift  3
            unaryoperation shift  4

State 2:
  (0) program ::= expression *
      unaryoperation ::= expression * Decrementation

                         $ reduce 0
            Decrementation shift  6

State 3:
  (3) unaryoperation ::= Decrementation expression *
      unaryoperation ::= expression * Decrementation

            Decrementation shift  6
            Decrementation reduce 3   ** Parsing conflict **
                 {default} reduce 3

State 4:
  (2) expression ::= unaryoperation *

                         {default} reduce 2

State 5:
  (1) expression ::= Null *

                 {default} reduce 1

State 6:
  (4) unaryoperation ::= expression Decrementation *

                 {default} reduce 4

为什么会出现冲突,因为在语法中明确指定了PreIncrementation和PostDecrementation的优先级和关联性?

1 个答案:

答案 0 :(得分:0)

您只定义伪终端的优先规则(PostDecrementation和PreDecrementation)。你没有定义实际终端Decrementation的优先级。

总是在生产(可以减少)和终端(可以转移)之间比较优先级。因此,您需要指定Decrementation的优先级来解决冲突。

就个人而言,我不会在这种情况下使用优先声明。但是如果你真的想要,你应该只使用一个伪终端,并让Decrementation成为使用它的两个产品之一的优先级。