Parser Internals

Shift/Reduce & Reduce/Reduce Conflicts Explained

Make parsing conflicts visible instead of theoretical. Understand why LR parsing tables fail and how parser generators resolve them.

What is a Conflict?

A parsing conflict occurs when the parser generator cannot decide between two valid actions at a given state and input symbol.

  • Shift/Reduce: Shift is possible OR Reduce is possible.
  • Reduce/Reduce: Two different reductions are possible.

This ambiguity inside the parser table is a conflict.

1. Shift/Reduce Conflict

The Scenario

Consider this ambiguous grammar:

E → E + E
E → id

For the input:

id + id

At some state, the parser sees E + E and the next token is +. It must decide:

  • Shift the + onto the stack?
  • Reduce E + E to E?

Why it happens

Because the grammar does not define precedence.

  • Should id + id be grouped immediately? (Reduce)
  • Or wait for more input? (Shift)
This is missing precedence information. The parser is stuck because both actions are mathematically valid under the given grammar rules.

2. Reduce/Reduce Conflict

The Scenario

Consider this grammar where two non-terminals derive the same string:

S → A | B
A → id
B → id

For the input:

id

The parser reaches a state with id • and must reduce. But which rule produced it?

Why it happens

Because the grammar allows structural ambiguity.

Same string → Multiple non-terminal derivations.

The parser cannot decide whether to reduce using A → id or B → id because both perfectly match the stack.

3. Interactive Visual System

Step through how conflicts arise in a state and how different parsers (LR0, SLR, CLR) handle them.

Step 1: Current State
[ Waiting to start... ]
Step 2: Next Input Symbol
_
Step 3: Action Set
⚠ SHIFT / REDUCE CONFLICT

4. How Parsers Fix Conflicts

LR(0)

Has no lookahead. It blindly allows shifts and reduces simultaneously, causing many conflicts.

SLR

Adds FOLLOW sets to restrict reductions. Only reduce A → id if lookahead ∈ FOLLOW(A). Fixes many conflicts.

CLR

Uses full LR(1) lookahead per item (e.g., [A → id •, '+']). Each reduction is context-aware. Almost no conflicts.

LALR

Merges CLR states with the same LR(0) core. Keeps combined lookaheads. A practical compromise with very few conflicts.

The Ultimate Key Insight

A conflict is not randomness. It is two mathematically valid derivations competing for control.

Parsing is not guessing. It is rule enforcement under constraints.
The entire LR family exists to reduce that uncertainty step by step.