Previous: How Precedence Works, Up: Operator Precedence [Contents][Index]
Using properly precedence and associativity directives can help fixing
shift/reduce conflicts that do not involve arithmetic-like operators. For
instance, the “dangling else
” problem (see Shift/Reduce Conflicts) can be
solved elegantly in two different ways.
In the present case, the conflict is between the token "else"
willing
to be shifted, and the rule ‘if_stmt: "if" expr "then" stmt’, asking
for reduction. By default, the precedence of a rule is that of its last
token, here "then"
, so the conflict will be solved appropriately
by giving "else"
a precedence higher than that of "then"
, for
instance as follows:
%precedence "then" %precedence "else"
Alternatively, you may give both tokens the same precedence, in which case associativity is used to solve the conflict. To preserve the shift action, use right associativity:
%right "then" "else"
Neither solution is perfect however. Since Bison does not provide, so far, “scoped” precedence, both force you to declare the precedence of these keywords with respect to the other operators your grammar. Therefore, instead of being warned about new conflicts you would be unaware of (e.g., a shift/reduce conflict due to ‘if test then 1 else 2 + 3’ being ambiguous: ‘if test then 1 else (2 + 3)’ or ‘(if test then 1 else 2) + 3’?), the conflict will be already “fixed”.