0

I've got a shift/reduce conflict that I can't figure out why it's occurring, and how to resolve it.

Given this grammar:

%token IDENTIFIER
%start Expression

%%

CallExpression
  : Expression "(" ")"
  ;

Lambda
  : "(" ")" "=>" Expression
  ;

Expression
  : IDENTIFIER
  | CallExpression
  | Lambda
  ;

I want to be able to parse expressions like this (not exhaustive):

foo
foo()
() => foo
() => () => foo
() => foo()

But I receive a shift/reduce conflict here:

State 11

    1 CallExpression: Expression . "(" ")"
    2 Lambda: "(" ")" "=>" Expression .  [$end, "("]

    "("  shift, and go to state 8

    "("       [reduce using rule 2 (Lambda)]
    $default  reduce using rule 2 (Lambda)

I thought I understood when shift/reduces occur, but this one is escaping me so I need to get schooled.

I tried learning more about the precedence directives available, left, right, precedence, nonassoc but any use of them I try does not resolve the ambiguity and they also give me warning: useless precedence and associativity so I'm doing something wrong. Hoping the answer is obvious to others.

I initially thought this was related to the fact that Lambdas start with () and CallExpressions end with it, but changing these tokens to not conflict makes no difference.

/facepalm

John Doe
  • 3
  • 2
  • Is `() => foo()` a Lambda containing a CallExpression, or a CallExpression containing a Lambda? I *think* that's what's confusing it here. – aschepler Nov 14 '16 at 01:13
  • @aschepler a ha! that makes total sense! It's supposed to be the former, but I hadn't even realized the later is grammatically possible. Great catch. Presumably the precedence directives could solve this, but I'm inexperienced with them. Any thoughts? – John Doe Nov 14 '16 at 01:17
  • @aschepler I forgot to say thank you! Thank you! This was the issue, and I found the correct precedence to resolve. If you want to add this as an answer, I'd accept it. – John Doe May 05 '17 at 22:38

0 Answers0