Using properly precedence and associativity directives can help fixing
shift/reduce conflicts that do not involve arithmetics-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
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
"then", so the conflict will be solved appropriately
"else" a precedence higher than that of
instance as follows:
%nonassoc "then" %nonassoc "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, support for “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”.