5.3 SLR(1) Parsing: Follow Set Lookaheads & Conflict Resolution
π‘ Core Intuition: The 3-Second Mental Modelβ
π³ The Everyday Analogy: The Discerning Passport Inspectorβ
In pure LR(0) parsing, the parser operates with total blindness during reductions:
- Whenever a state contains a completed assembly (), it writes
Reduceacross every single terminal column in that table row. - This is like an immigration officer stamping every single traveler's passport with an entry visa without checking their boarding pass! If a traveler holds a ticket for another sovereign terminal, an unnecessary conflict or a false entry occurs.
Simple LR (SLR(1)) introduces a sharp, common-sense lookahead gate:
-
A reduction by should ONLY occur if the next incoming terminal token is a symbol that can legally appear immediately after in the language:
-
If , performing reduction is futile because non-terminal could never legally connect to in any valid derivation.
-
By placing reductions strictly under columns, SLR(1) eliminates the vast majority of false conflicts that paralyze LR(0).
π» Bridging to Computer Science: Restricting Reductions via FOLLOW Lookaheadsβ
In bottom-up syntax analysis:
- SLR(1) retains the exact same DFA state machine and identical canonical collection of LR(0) items as an LR(0) parser.
- However, during parsing table generation, each complete item consults the global context of the grammar: .
- Lookahead token acts as a gatekeeper: if , the reduction is scheduled; if , the cell remains blank.
πTable of Contents
ποΈ Architectural Foundations: The SLR(1) Reduction Filterβ
The SLR(1) Reduction Gating Mechanism
Filtering out illegal reduction conflicts using grammar FOLLOW sets as gatekeepers
Lookahead Token (a)
Next unconsumed terminal token from input buffer.
Complete Item A β Ξ± β’
State contains a handle ready for grammatical reduction.
a β FOLLOW(A)?
Can terminal 'a' legally appear immediately after non-terminal A?
ACTION[i, a] = rk
If YES: write reduce action. If NO: reject reduction and avoid conflict.
βοΈ LR(0) vs SLR(1): Side-by-Side Comparisonβ
LR(0) vs SLR(1): The Lookahead Filter
Contrasting blind row-wide reductions against targeted FOLLOW-set filtering
LR(0) Parser
- β’Places Reduce A -> Ξ± in ALL terminal columns in the state's row.
- β’Zero lookahead check; completely blind to incoming tokens.
- β’Generates spurious Shift/Reduce conflicts on almost all real grammars.
- β’State machine and table dimensions identical to SLR(1).
SLR(1) Parser
- β’Places Reduce A -> Ξ± ONLY under columns a β FOLLOW(A).
- β’Uses 1 token of lookahead to filter out illegal reductions.
- β’Resolves massive numbers of LR(0) Shift/Reduce conflicts.
- β’Same number of states as LR(0); significantly more expressive.
π Formal Mathematical Foundations: SLR(1) Table Constructionβ
SLR(1) uses the exact same canonical collection of LR(0) items and the exact same DFA states as LR(0). The difference lies entirely in step 2 of table construction:
Given canonical collection for augmented grammar :
-
Shift Actions: If where is a terminal, and :
-
SLR(1) Reduce Actions (The Targeted Filter): If where and is production rule :
(All terminal columns remain empty error cells!).
-
Accept Action: If :
-
GOTO Transitions: If for non-terminal :
π€Ό SLR(1) Conflict Conditionsβ
An SLR(1) parsing table exhibits a conflict if and only if one of the following conditions is satisfied:
βοΈ Shift/Reduce Conflict in SLR(1)β
A state contains a shift item for terminal () AND a completed reduce item () such that:
(If , the conflict is successfully eliminated by the SLR(1) lookahead filter!).
π₯ Reduce/Reduce Conflict in SLR(1)β
A state contains two distinct completed reduce items and such that their follow sets share at least one common terminal:
π Real-World Production Context: How Industry Builds Thisβ
While pure SLR(1) parsers are rarely used directly in modern production compilers (having been superseded by LALR(1) in tools like GNU Bison, Yacc, and Menhir):
Understanding why SLR(1) fails on unambiguous constructs (such as pointer dereference assignment statements) is the core intellectual foundation of bottom-up parsing theory:
- SLR(1) computes FOLLOW sets globally across the entire grammar.
- Global FOLLOW sets merge lookaheads from independent derivation branches, polluting the lookahead set with tokens that can never legally appear in the current derivation context.
- This limitation directly inspired Canonical LR(1) (context-specific lookaheads) and LALR(1) (merging LR(1) states with identical cores).
Because SLR(1) uses the exact same DFA states as LR(0):
- Memory footprint in the runtime executable is identical to LR(0).
- Parser performance is with zero backtracking.
π Numerical Applications & Worked Examplesβ
Example 1: Resolving an LR(0) Shift/Reduce Conflict via SLR(1)β
Recall the arithmetic expression grammar from Module 05 Topic 2 that suffered a Shift/Reduce conflict in LR(0):
- Augment the grammar and compute FOLLOW sets.
- Evaluate state and prove that SLR(1) completely eliminates the Shift/Reduce conflict.
Step-by-Step Analytical Solution:
Step 1: Augmented Grammar & Numbered Productions
- (0)
- (1)
- (2)
- (3)
- (4)
Step 2: Compute FOLLOW Sets
- For Start Symbol :
- For :
- In : is at the end:
- In : is followed by
+:
- For :
- In and : is at the end:
Step 3: Evaluate State From initial state , transitioning across non-terminal yields state :
In state :
- Item is a shift item on terminal
+. It requests a Shift on column+. - Item is a completed reduce item (production 1: ).
- In LR(0): was written into both columns
+and$, creating a fatal conflict on+! - In SLR(1): is written ONLY under columns in :
- In LR(0): was written into both columns
- Crucially, !
Table Population for Row 1:
- Column
+: Contains Shift to state . - Column
$: Contains Reduce 1 ().
The conflict has vanished! Every cell contains at most one action. The grammar is strictly SLR(1)!
Example 2: The Canonical Assignment Grammar That Fails SLR(1)β
Consider the unambiguous pointer-assignment grammar:
Prove analytically that this grammar is NOT SLR(1) by identifying the exact state where an unresolved Shift/Reduce conflict occurs.
Step-by-Step Analytical Proof:
Step 1: Compute FOLLOW Sets
- is start symbol:
- In : is followed by
=. - In : is at the end:
- In : is at the end .
- In : is at the end .
- Therefore, the follow sets of and merge:
Step 2: Construct State (Transition on symbol ) Starting from :
- Includes
- Includes and
- Includes and
- Includes
Compute :
- Advancing dot over in yields:
- Advancing dot over in yields:
Step 3: Analyze Conflict in State In state :
- Item is a shift item on terminal
=. It demands Shift on column=. - Item is a complete reduce item for production .
- In SLR(1), reduce is placed in all columns belonging to :
- Because
=belongs to , the reduction MUST be placed in column=!
Table Population for Cell :
An unresolved Shift/Reduce Conflict exists in cell !
Even though this grammar is completely unambiguous, it is NOT SLR(1).
Root Cause of SLR(1) Failure: contains
=because of the valid rightmost derivation . However, in state , the stack has observed prefix . In this specific context, an=can only be legally followed if remains on the left side of the assignment; an reduction at this position would create an invalid prefix . Because SLR(1) uses global follow sets rather than context-specific lookaheads, it cannot see this distinction.
π― Exam & Interview Pitfall Checkβ
Question 1: "Does SLR(1) have more states or a larger parsing table than LR(0)?"
Key Focus Points:
- Strict Rule: No. The number of states and the dimensions of the parsing table in SLR(1) are identically equal to those in LR(0).
- Reason: Both parsers use the exact same canonical collection of LR(0) items. SLR(1) differs solely in filtering out which cells receive reduction entries.
Question 2: "If a grammar has an -production, can it be SLR(1)?"
Key Focus Points:
- Yes. Grammars with -productions can certainly be SLR(1), provided that the empty reduction item does not conflict with shift items or other reduce items under lookaheads in .
Trap 1: Assuming that an unambiguous grammar is always SLR(1).
Answer: Classic trap. Unambiguity does not guarantee SLR(1) compatibility. The assignment grammar () is unambiguous and has a unique parse tree for every valid string, yet it fails SLR(1) because global FOLLOW sets are too coarse.
Trap 2: Claiming that SLR(1) eliminates all Shift/Reduce conflicts.
Answer: False. SLR(1) eliminates an S/R conflict if and only if the shift terminal does NOT belong to the FOLLOW set of the reducing non-terminal (). If , the S/R conflict survives.