with
%nonassoc ELSE
%nonassoc THEN
I get
$ bison -dv tiger.yy
tiger.yy:74.5-28: warning: rule useless in parser due to conflicts [-Wother]
: IF exp THEN exp ELSE exp
^^^^^^^^^^^^^^^^^^^^^^^^
but with
%nonassoc THEN
%nonassoc ELSE
the rule works.
What's going on here? why is this the case?
As the warning says, the rule is useless because if THEN
has precedence over ELSE
, then the resolution of a shift/reduce conflict makes it impossible for the rule to be applied.
I presume that the grammar actually includes something like:
exp: IF exp THEN exp ELSE exp
| IF exp THEN exp
because if the ELSE
clause is mandatory, there wouldn't be a conflict. The rule above has a shift/reduce conflict because when the ELSE
is the lookahead token in the parsing of IF exp THEN IF exp THEN exp ELSE...
it would be possible to either shift the ELSE
or reduce the innerIF exp THEN exp
to exp
.
In order to correctly parse the expression, it is necessary to favour the shift action, so that the ELSE
will be associated with the innermost available IF
. Without precedence declarations, that would be the default resolution, since yacc/bison prefers shift over reduce. However, if bison uses a default resolution, it also produces a warning about the resolution. To avoid the warning, it is common to explicitly force the default resolution by giving ELSE
precedence over THEN
. That's what
%nonassoc THEN
%nonassoc ELSE
does. If you write the precedence declarations in the other order,
%nonassoc ELSE
%nonassoc THEN
then you are giving THEN
precedence over ELSE
, which means that you are instructing the parser generator to prefer reducing the production whose last nonterminal is THEN
over shifting ELSE
. Bison/yacc will obey that request, but if it does so it can never shift the ELSE
making the rule containing the ELSE
useless.