I’ve written following bison grammar file:
%left '+' '-'
%left '*' '/'
%token NUMBER
%%
expr
: NUMBER
| expr '+' expr
| expr '-' expr
| expr '*' expr
| expr '/' expr
| expr expr %prec '*' /* implicit multiplication */
;
Now bison reports shift/reduce conflict regarding expr : expr expr. I’ve extracted problem to following minimal set:
%left OP
%%
expr
: 'a'
| expr expr %prec OP
;
I can’t get why is bison still complains about shift/reduce conflict. I’ve found some old mail archive: Re: bison/yacc: shift/reduce conflict using %prec for composition, but I don’t understand author’s explanations either.
Could someone clarify why this grammar is ambiguous, and how to resolve conflict?
EDIT: by NUMBER NUMBER I mean NUMBER * NUMBER, i.e. product of this two numbers.
The problem here is that the token
NUMBERdoesn’t have a precedence. So when there’s a state that can either shift aNUMBERor reduce a rule (regardless of whether that rule has a precedence) it can’t decide which to do.Now you can fix it for this grammar by adding a precedence for
NUMBER(make it the same as*), but it will come back if you add any rules for expression that start with any token other thanNUMBER— for example if you addexpr: '(' expr ')', you’ll get shift/reduce conflicts on'('.An even bigger problem is if you add unary prefix operators, such as
expr: '-' expr. In this case, you won’t get a conflict as ‘-‘ already has a precedence, but an input likeNUMBER - NUMBERwill get parsed asNUMBER ( - NUMBER ), which is probably not at all what you want. There’s no good way of dealing with this issue with precedence rules.The underlying cause of this confusion is that bison’s precedence rules don’t resolve precedence by comparing two rules as you might naively expect based on using the word “precedence”. Instead they work by comparing the “precedence” of a rule to be reduced with that of a token to be shifted and base the decision to shift or reduce based on that. At the point in the parse where this happens, the second rule hasn’t yet been recognized; instead bison is just guessing what it might be based on the token.