Parser reads subsequent input tokens and at the same time walks states of automaton. Each visited state is supposed to provide information on what to do next depending on input token read. A conflict occurs when it is not possible to build an automaton where in each state for each possible next token there would be just a single action. In other words a conflict is a situation, where in some state there are two or more candidate actions for a single symbol.
Parser can perform two types of actions: reduce, which reduces top of stack elements according to some production, and shift, which pushes next token to stack hoping to match some longer production. Given these two types of actions possible conflicts are:
Note that there are no shift-shift conflicts.
The most typical example of shift-reduce conflict is known as 'dangling else'. In many programming languages syntax of IF instruction allows optional else block. Corresponding grammar is:
Providing that input is:
it is not possible to tell if it should be interpreted as:
or
That is whether the terminal ELSE code belongs to the outer or inner IF_INSTR.
When parser is processing input from left to right it must make final decision when in the following situation:
Possible options are:
decision to reduce top of stack according to production @2:
alternative decision is to shift ELSE:
Dangling else is an example of grammar ambiguity. User must explicitly specify which interpretation of above situation should be assumed when building parser. To resolve the conflict user must manually resolve the conflict by telling Alpag whether to shift or reduce in given situation.
A reduce-reduce conflict is almost always caused by serious grammar error. Conflicts of this type cannot be resolved by pointing to one of possible solutions, though some global options for handling them exist. Usually grammar must be rewritten to avoid such conflicts.
In most cases it is possible to rework the grammar so that general idea behind it is preserved and conflict disappears.
Usually reduce-reduce conflicts arise when certain construction (sequence of symbols) can be achieved or build from grammar rules in more than one way, as in the example:
The idea behind above erroneous the grammar is to allow three alternative syntaxes of a COMMAND:
However when a standalone CMD token (not followed by INT or STR) appears, two alternative interpretations of this CMD token exist:
It is not possible to tell between these two interpretations of CMD token.
Note that introducing such ambiguity was not probably the intent of the author.
Parser must provide unambiguous decisions in all states. After CMD was read possible decisions (given next token is known) looks as follows:
In above state parser is unable to tell by which production to reduce. Construction of parser fails and grammar must be rewritten.
Note that above grammar can be easily rewritten to avoid the conflict while preserving the original idea:
Trivial example of reduce-reduce conflict used in this chapter is not representative for entire class of r-r conflicts that can arise in production grammars. No simple rule or advice can be given on how to avoid such conflicts. However usually r-r conflicts are consequence of decomposing grammar into very deep trees of overly nested productions.