Rules to help remove ambiguities

Precedence cannot resolve conflicts if one or both conflicting operations have no precedence. For example, consider the following:
statmt:  IF '(' cond ')' statmt
    |    IF '(' cond ')' statmt ELSE statmt ;
Given this rule, how should the parser interpret the following input?
IF ( cond1 ) IF ( cond2 ) statmt1 ELSE statmt2
There are two equally valid interpretations of this input:
IF ( cond1 ) {
     IF ( cond2 ) statmt1
     ELSE statmt2
}
and:
IF ( cond1 ) {
     IF ( cond2 ) statmt1
}
ELSE statmt2
In a typical grammar, the IF and IF-ELSE statements would not have a precedence, so precedence could not resolve the conflict. Thus consider what happens at the point when the parser has read:
IF ( cond1 ) IF ( cond2 ) statmt1
and has just picked up ELSE as the look-ahead symbol.
  1. It can immediately reduce the:
    IF ( cond2 ) statmt1
    using the first definition of statmt and obtain:
    IF ( cond1 ) statmt ELSE ...
    thereby associating the ELSE with the first IF.
  2. It can shift, which means ignoring the first part (the IF with cond1) and going on to handle the second part, thereby associating the ELSE with the second IF.

In this case, most programming languages choose to associate the ELSE with the second IF; that is, they want the parser to shift instead of reduce. Because of this (and other similar situations), yacc-produced parsers are designed to use the following rule to resolve shift-reduce conflicts.

Rule 1

If there is a shift-reduce conflict in situations where no precedence rules have been created to resolve the conflict, the default action is to shift.

The conflict is also reported in the yacc output so you can check that shifting is actually what you want. If it is not what you want, the grammar rules have to be rewritten.

The rule is used only in situations where precedence rules cannot resolve the conflict. If both the shift operation and the reduce operation have an assigned precedence, the parser can compare precedences and decide which operation to perform first. Even if the precedences are equal, the precedences must have originated from either %left, %right, or %nonassoc, so the parser knows how to handle the situation. The only time a rule is needed to remove ambiguity is when one or both of the shift or reduce operations does not have an assigned precedence.

In a similar vein, yacc-produced parsers use the following rule to resolve reduce-reduce conflicts.

Rule 2

If there is a reduce-reduce conflict, the parser always reduces by the rule that was given first in the rules section of the yacc input.

Again, the conflict is reported in the yacc output so that users can ensure that the choice is correct.

Precedence is not consulted in reduce-reduce conflicts. yacc always reduces by the earliest grammar rule, regardless of precedence.

The rules are simple to state, but they can have complex repercussions if the grammar is nontrivial. If the grammar is sufficiently complicated, these simple rules for resolving conflicts may not be capable of handling all the necessary intricacies in the way you want. Users should pay close attention to all conflicts noted in the parsing table report produced by yacc and should ensure that the default actions taken by the parser are the desired ones.