2

The following is my grammar:

arithmetic_expression : expression + expression
                      | expression - expression

expression            : constant
                      | ID
                      | arithmetic_expression
                      | ternary

ternary               : expression ? expression : expression

I receive a shift-reduce error in this state:

state 126

    (19) ternary -> expression QUESTION_MARK expression COLON expression .
    (27) arithmetic_exp -> expression . PLUS expression
    (28) arithmetic_exp -> expression . MINUS expression
    (19) ternary -> expression . QUESTION_MARK expression COLON expression

  ! shift/reduce conflict for PLUS resolved as shift
  ! shift/reduce conflict for MINUS resolved as shift
  ! shift/reduce conflict for QUESTION_MARK resolved as shift

    PLUS            shift and go to state 86
    MINUS           shift and go to state 88
    QUESTION_MARK   shift and go to state 85

  ! PLUS            [ reduce using rule 19 (ternary -> expression QUESTION_MARK expression COLON expression .) ]
  ! MINUS           [ reduce using rule 19 (ternary -> expression QUESTION_MARK expression COLON expression .) ]
  ! QUESTION_MARK   [ reduce using rule 19 (ternary -> expression QUESTION_MARK expression COLON expression .) ]

I believe the conflict is that

true ? 1 : false ? 3 : 2

can be interpreted as true ? 1 : (false ? 3 : 2) or (true ? 1 : false) ? 3 : 2.

I have set the precedence for +, and - as left associative and higher level than ? (which I set to right associativity).

What am I doing wrong?

sdasdadas
  • 23,917
  • 20
  • 63
  • 148

2 Answers2

5

If I understand you correctly, you did the following:

%left '+' '-'
%right '?'

%%

arithmetic_expression : expression + expression
                      | expression - expression
                      ;
ternary               : expression ? expression : expression
                      ;

That won't work, because you haven't told bison what the precedence of the ternary production is.

To resolve shift-reduce conflicts, bison compares the precedence of the production which might be reduced with the precedence of the terminal which might be shifted. You've declared the precedence of the terminals '+', '-' and '?', and the precedence of both productions in arithmetic_expression, but not the precedence of the production in ternary.

Quoting from the bison manual, emphasis added:

each rule gets its precedence from the last terminal symbol mentioned in the components.

That's very subtle and you won't be the first person who didn't notice.

Solutions: either declare the precedence of the terminal : or add %prec '?' to the production in ternary.

rici
  • 234,347
  • 28
  • 237
  • 341
  • Thanks that was it - I didn't realize that the last terminal affected precedence in that way. – sdasdadas Jul 28 '13 at 20:12
  • 1
    @sdasdadas: it is consistent with operator precedence parsing, which is based on the definition of a precedence relationship between "consecutive" terminals. (They're not really consecutive because they can be separated by exactly one non-terminal, but not by another terminal.) With LR(k) parsing, the stack state is used to represent the first terminal in the precedence relationship, which is the last terminal in the production included in the stack state. That's the best explanation I can give in a comment :) – rici Jul 28 '13 at 20:27
1

Exaclty - you didn't specify associativity.

In C, the grammar says:

conditional_expression = logical_or_expression [ '?' expression ':' conditional_expression ];

so I believe you want something like

conditional_expression = arithmetic_expression [ '?' expression ':' conditional_expression ];

if you want a C-like behavior (and thus right associativity, among other properties).

  • I don't quite understand - I specified the tokens +/- and ? as left and right associative, respectively. – sdasdadas Jul 28 '13 at 04:18
  • @sdasdadas And how about `:`? That's still missing. Did you try my suggestion? –  Jul 28 '13 at 04:27
  • No I hadn't, I was just trying to clarify where I was going wrong. I appreciate the suggestion but, as far as I understand it (and I might very well be incorrect), it looks like a change that I don't necessarily want in my grammar. You (and rici) were correct about the `:` though. – sdasdadas Jul 28 '13 at 20:11