Reputation: 67900
Let's imagine I want to be able to parse values like this (each line is a separate example):
x
(x)
((((x))))
x = x
(((x))) = x
(x) = ((x))
I've written this YACC grammar:
%%
Line: Binding | Expr
Binding: Pattern '=' Expr
Expr: Id | '(' Expr ')'
Pattern: Id | '(' Pattern ')'
Id: 'x'
But I get a reduce/reduce conflict:
$ bison example.y
example.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
Any hint as to how to solve it? I am using GNU bison 3.0.2
Upvotes: 1
Views: 2648
Reputation: 241911
Your grammar is not LR(k)
for any k
. So you either need to fix the grammar or use a GLR
parser.
Suppose the input starts with:
(((((((((((((x
Up to here, there is no problem, because every character has been shifted onto the parser stack.
But now what? At the next step, x
must be reduced and the lookahead is )
. If there is an =
somewhere in the future, x
is a Pattern
. Otherwise, it is an Expr
.
You can fix the grammar by:
getting rid of Pattern
and changing Binding
to Expr | Expr '=' Expr;
getting rid of all the definitions of Expr
and replacing them with Expr: Pattern
The second alternative is probably better in the long run, because it is likely that in the full grammar which you are imagining (or developing), Pattern
is a subset of Expr
, rather than being identical to Expr
. Factoring Expr
into a unit production for Pattern
and the non-Pattern alternatives will allow you to parse the grammar with an LALR(1)
parser (if the rest of the grammar conforms).
Or you can use a GLR grammar, as noted above.
Upvotes: 1
Reputation: 754820
Reduce/reduce conflicts often mean there is a fundamental problem in the grammar.
The first step in resolving is to get the output file (bison -v example.y
produces example.output
). Bison 2.3 says (in part):
state 7
4 Expr: Id .
6 Pattern: Id .
'=' reduce using rule 6 (Pattern)
')' reduce using rule 4 (Expr)
')' [reduce using rule 6 (Pattern)]
$default reduce using rule 4 (Expr)
The conflict is clear; after the grammar reads an x
(and reduces that to an Id
) and a )
, it doesn't know whether to reduce the expression as an Expr
or as a Pattern
. That presents a problem.
I think you should rewrite the grammar without one of Expr
and Pattern
:
%%
Line: Binding | Expr
Binding: Expr '=' Expr
Expr: Id | '(' Expr ')'
Id: 'x'
Upvotes: 2