0

Here is a grammar wrote for the lemon parser generator :

%left  PostDecrementation.
%right PreDecrementation.

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

When trying to compile it, the generator produces the following conflict :

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

Why is there a conflict, since the precedence and associativity of both PreIncrementation and PostDecrementation has been explicitely specified in the grammar ?

Maël Nison
  • 7,055
  • 7
  • 46
  • 77

1 Answers1

0

You are only defining precedence rules for pseudoterminals (PostDecrementation and PreDecrementation). Nowhere do you define the precedence of the actual terminal Decrementation.

Precedence is always compared between a production (which could be reduced) and a terminal (which could be shifted). So you need to specify the precedence of Decrementation to resolve the conflict.

Personally, I wouldn't use precedence declarations in this case. But if you really want to, you should probably just use one pseudoterminal, and let Decrementation be the precedence of one of the two productions which uses it.

rici
  • 234,347
  • 28
  • 237
  • 341
  • Putting a `%nonassoc Decrementation` rule with a lowest precedence than (Post/Pre)Decrementation seems to generate a valid AST (`(++(foo++))`), is it a right way to solve the issue ? I would like to avoid the waterfall grammar style – Maël Nison Jan 21 '13 at 02:08
  • if you're just going to add a precedence for Decrementation, then whether you define Decrementation as %left, %right, or %nonassoc makes no difference, because it will never be compared with itself. (And indeed, that is true of the pseudoterminals as well). The only thing that matters is the order. Let me repeat for emphasis: a precedence rule always compares a production with a token. – rici Jan 21 '13 at 02:33