Skip to main content

5.2 LR(0) Parsing: Canonical Collection of Items, Closure, GOTO & Table Construction

πŸ“šModule 01LR(0) Parsing & Canonical Item Collections⏱️5 min read
🎯High-Yield For:Semester Exams β€’ GATE CSE β€’ Technical Interviews

πŸ’‘ Core Intuition: The 3-Second Mental Model​

🍳 The Everyday Analogy: The Assembly Progress Tracker​

Imagine building a complex piece of flat-pack furniture with an instruction manual:

  • The Production Blueprint: Chairβ†’LegsΒ SeatΒ Backrest\text{Chair} \to \text{Legs} \ \text{Seat} \ \text{Backrest}
  • The Progress Bookmark (The Dot β‹…\cdot):
    • Chairβ†’β‹…Β LegsΒ SeatΒ Backrest\text{Chair} \to \cdot \ \text{Legs} \ \text{Seat} \ \text{Backrest}: You have opened the box, but haven't assembled anything yet. You are actively searching for the Legs.
    • Chairβ†’Legsβ‹…SeatΒ Backrest\text{Chair} \to \text{Legs} \cdot \text{Seat} \ \text{Backrest}: The legs are fully attached! Your eyes now shift to the next instruction: grab the Seat.
    • Chairβ†’LegsΒ SeatΒ Backrestβ‹…\text{Chair} \to \text{Legs} \ \text{Seat} \ \text{Backrest} \cdot: The entire chair is completely assembled! You don't need any more parts; you proudly mark this unit finished (Reduce to Chair).

πŸ’» Bridging to Computer Science: Tracking Viable Prefixes via Dot Items​

In bottom-up LR parsing, the compiler does not guess which production to apply ahead of time. Instead, it tracks all partially matched productions simultaneously using LR(0) Items:

  • An LR(0) item is simply a grammar production with a marker dot (β‹…\cdot) placed at some position on the right-hand side.
  • The symbols to the left of the dot represent what has already been pushed and verified on the parser stack.
  • The symbols to the right of the dot represent what the parser expects to see next in the input stream.
  • When the dot reaches the extreme right end (Aβ†’Ξ±β‹…A \to \alpha \cdot), the entire handle has been matched, signaling an immediate Reduce action.

πŸ—οΈ Architectural Foundations: The LR(0) State Machine Pipeline​

Architecture Flow

The Canonical LR(0) Collection Pipeline

Generating the DFA of viable prefixes through augmented grammar, closure expansion, and GOTO transitions

βž•Step 1

Augment Grammar G'

Introduce unique start rule S' β†’ S to define an unambiguous accept state.

β†’
Seed Item
πŸ”’Step 2

CLOSURE Expansion

Inductively add B β†’ β€’Ξ³ whenever dot precedes non-terminal B.

β†’
State I0
πŸš€Step 3

GOTO(I, X) Transitions

Advance dot past symbol X and take CLOSURE of resulting items.

β†’
Fixed Point
⚑Step 4

Canonical DFA

Complete collection of item sets forming parser ACTION and GOTO tables.


πŸ“ Formal Mathematical Foundations: Items, Closure & GOTO​

βž• The Augmented Grammar​

Given a context-free grammar G=(V,Ξ£,R,S)G = (V, \Sigma, R, S), the Augmented Grammar Gβ€²G' is formed by introducing a fresh start symbol Sβ€²S' and a single auxiliary production:

Sβ€²β†’SS' \to S

Why augment? In the original grammar, the start symbol SS may appear on the right-hand side of some production rules (e.g. S→aSbS \to a S b). Without augmentation, the parser cannot distinguish between completing a nested sub-derivation of SS and completing the entire compilation. Reducing S′→SS' \to S signals an unambiguous termination condition: the parser halts and safely Accepts the program.

πŸ“Œ The LR(0) Item​

An LR(0) Item of a grammar GG is a production A→αβA \to \alpha \beta with a distinguished dot ‒ placed at some position in the right-hand side:

A→α⋅βA \to \alpha \cdot \beta
  • For a production with right-hand side of length n=∣αβ∣n = |\alpha \beta|, there are exactly n+1n + 1 distinct LR(0) items.

  • Special Case for Epsilon: For an empty production Aβ†’Ο΅A \to \epsilon, there is only one LR(0) item:

    A→⋅A \to \cdot

    (Which functions immediately as a completed reduce item!)

The 4 Canonical LR(0) Item Categories

How the position of the dot determines the parser's operational action

⏩

Shift Item

Action: Shift
  • Dot immediately precedes a terminal symbol: A β†’ Ξ± β€’ a Ξ².
  • Triggers a SHIFT action: pushes terminal 'a' and target state onto the stack.
  • Consumes exactly one terminal from the input lookahead stream.
πŸ”€

GOTO Item

Action: Non-Terminal Transition
  • Dot immediately precedes a non-terminal symbol: A β†’ Ξ± β€’ B Ξ².
  • Triggers CLOSURE expansion: pulls all initial items B β†’ β€’Ξ³ into current state.
  • Governs parser state transitions after a reduction: GOTO[state, B].
🎯

Reduce Item

Action: Reduction
  • Dot has reached the extreme right of the production: A β†’ Ξ³ β€’.
  • Entire production handle has been matched and verified on stack.
  • Pops |Ξ³| states and symbols from stack; exposes previous state.
πŸ†

Accept Item

Action: Parser Acceptance
  • Special item derived from the augmented start symbol: S' β†’ S β€’.
  • Occurs when entire input has been successfully reduced to start symbol S.
  • Parser terminates with success: program is grammatically valid.

βš™οΈ The Canonical Collection Engine: CLOSURE & GOTO​

The collection of all sets of LR(0) items forms the state space of the DFA of Viable Prefixes.

πŸ”’ The CLOSURE Algorithm​

If II is a set of items for grammar GG, CLOSURE(I)\text{CLOSURE}(I) is constructed inductively:

  1. Basis: Every item in II is added to CLOSURE(I)\text{CLOSURE}(I).

  2. Induction: If [Aβ†’Ξ±β‹…BΞ²]∈CLOSURE(I)[A \to \alpha \cdot B \beta] \in \text{CLOSURE}(I) and BB is a non-terminal, then for every production Bβ†’Ξ³B \to \gamma in GG, add the initial item:

    B→⋅γB \to \cdot \gamma

    to CLOSURE(I)\text{CLOSURE}(I), if it is not already present.

  3. Repeat step 2 until no new items can be added.

πŸš€ The GOTO Function​

Let II be a set of items, and let X∈(VβˆͺΞ£)X \in (V \cup \Sigma) be a grammar symbol. GOTO(I,X)\text{GOTO}(I, X) represents the state reached by transitioning across symbol XX:

πŸ“–Formal Definition: The LR(0) GOTO Transition Functiondefinition
GOTO(I,X)=CLOSURE({Aβ†’Ξ±Xβ‹…Ξ²βˆ£Aβ†’Ξ±β‹…Xβ∈I})\text{GOTO}(I, X) = \text{CLOSURE}\big( \{ A \to \alpha X \cdot \beta \mid A \to \alpha \cdot X \beta \in I \} \big)

Intuitively, GOTO(I,X)\text{GOTO}(I, X) advances the dot one position to the right across symbol XX for all items in II where the dot precedes XX, and then expands the closure of the resulting set.


πŸ—οΈ LR(0) Parsing Table Construction Algorithm​

An LR parsing table contains two distinct components:

  • ACTION[i,a]\text{ACTION}[i, a]: Indexed by parser state ii and terminal token aa (where a∈Σa \in \Sigma or a=a = $).
  • GOTO[i,A]\text{GOTO}[i, A]: Indexed by parser state ii and non-terminal symbol A∈VA \in V.

Deterministic Population Rules​

For each state IiI_i in the canonical collection:

  1. Shift Actions: If [Aβ†’Ξ±β‹…aΞ²]∈Ii[A \to \alpha \cdot a \beta] \in I_i where a∈Σa \in \Sigma is a terminal, and GOTO(Ii,a)=Ij\text{GOTO}(I_i, a) = I_j:

    ACTION[i,a]=ShiftΒ j(writtenΒ sj)\text{ACTION}[i, a] = \text{Shift } j \quad (\text{written } s_j)
  2. Reduce Actions (The Zero-Lookahead Invariant): If [Aβ†’Ξ±β‹…]∈Ii[A \to \alpha \cdot] \in I_i (where Aβ‰ Sβ€²A \neq S' and Aβ†’Ξ±A \to \alpha is production rule kk):

    ACTION[i,a]=ReduceΒ k(writtenΒ rk)forΒ ALLΒ terminalsΒ a∈Σβˆͺ{$}\text{ACTION}[i, a] = \text{Reduce } k \quad (\text{written } r_k) \quad \text{\bf for ALL terminals } a \in \Sigma \cup \{ \$ \}

    (In an LR(0) parser, reductions are placed blindly across every single terminal column in the row!)

  3. Accept Action: If [Sβ€²β†’Sβ‹…]∈Ii[S' \to S \cdot] \in I_i:

    ACTION[i,$]=Accept\text{ACTION}[i, \$] = \text{Accept}
  4. GOTO Entries: If GOTO(Ii,A)=Ij\text{GOTO}(I_i, A) = I_j for non-terminal A∈VA \in V:

    GOTO[i,A]=j\text{GOTO}[i, A] = j
  5. Blank Entries: All unpopulated cells in the table represent syntax error states.


🀼 Conflicts in LR(0) Grammars​

Because LR(0) places reductions unconditionally across all terminal columns without checking lookahead, very few practical grammars are strictly LR(0):

  • Shift/Reduce (S/R) Conflict: A state contains both a shift item (Aβ†’Ξ±β‹…aΞ²A \to \alpha \cdot a \beta) and a reduce item (Bβ†’Ξ³β‹…B \to \gamma \cdot). When terminal aa arrives, the table cannot decide whether to shift or reduce.
  • Reduce/Reduce (R/R) Conflict: A state contains two distinct completed reduce items (Aβ†’Ξ±β‹…A \to \alpha \cdot and Bβ†’Ξ²β‹…B \to \beta \cdot). The parser cannot decide which reduction to execute.

Definition: A grammar is LR(0) if and only if its LR(0) parsing table contains zero multiply-defined entries (no S/R or R/R conflicts).


🏭 Real-World Production Context: How Industry Builds This​

While pure LR(0) parsers are rarely used directly in production compilers because practical languages have operator precedence that causes LR(0) conflicts:

The LR(0) Canonical Collection of Items is the exact DFA backbone utilized by both SLR(1) and LALR(1) parser generators (such as GNU Bison, Yacc, and Menhir):

  • An LALR(1) generator constructs the exact same LR(0) state machine first.
  • Only after building the LR(0) state graph does the generator compute lookahead sets to restrict where reductions are placed, transforming row-wide reductions into targeted lookahead slots.

Because the LR(0) state machine merges all derivation contexts with identical cores, the number of states generated is compactβ€”typically on the order of several hundred to a few thousand states for an entire C or Rust grammar.


πŸ“ Numerical Applications & Worked Examples​

Example 1: Complete Canonical Collection & LR(0) Table Construction​

Construct the complete canonical collection of LR(0) items and the parsing table for the grammar:

Sβ†’AAAβ†’aA∣b\begin{aligned} S &\to A A \\ A &\to a A \mid b \end{aligned}

Step-by-Step Analytical Solution:

Step 1: Number the Productions in Augmented Grammar Gβ€²G'

  • Production (0): Sβ€²β†’SS' \to S
  • Production (1): Sβ†’AAS \to A A
  • Production (2): Aβ†’aAA \to a A
  • Production (3): Aβ†’bA \to b

Step 2: Construct the Canonical Collection of States

Initial State I0I_0:

  • Seed item: Sβ€²β†’β‹…SS' \to \cdot S
  • Dot precedes Sβ€…β€ŠβŸΉβ€…β€ŠS \implies add Sβ†’β‹…AAS \to \cdot A A
  • Dot precedes Aβ€…β€ŠβŸΉβ€…β€ŠA \implies add Aβ†’β‹…aAA \to \cdot a A and Aβ†’β‹…bA \to \cdot b
  • I0={Sβ€²β†’β‹…S,Β Sβ†’β‹…AA,Β Aβ†’β‹…aA,Β Aβ†’β‹…b}I_0 = \{ S' \to \cdot S, \ S \to \cdot A A, \ A \to \cdot a A, \ A \to \cdot b \}

Transitions from I0I_0:

  • GOTO(I0,S)=CLOSURE({Sβ€²β†’Sβ‹…})=I1={Sβ€²β†’Sβ‹…}\text{GOTO}(I_0, S) = \text{CLOSURE}(\{ S' \to S \cdot \}) = \mathbf{I_1} = \{ S' \to S \cdot \}
  • GOTO(I0,A)=CLOSURE({Sβ†’Aβ‹…A})\text{GOTO}(I_0, A) = \text{CLOSURE}(\{ S \to A \cdot A \}):
    • Dot precedes Aβ€…β€ŠβŸΉβ€…β€ŠA \implies add Aβ†’β‹…aAA \to \cdot a A and Aβ†’β‹…bA \to \cdot b
    • I2={Sβ†’Aβ‹…A,Β Aβ†’β‹…aA,Β Aβ†’β‹…b}\mathbf{I_2} = \{ S \to A \cdot A, \ A \to \cdot a A, \ A \to \cdot b \}
  • GOTO(I0,a)=CLOSURE({Aβ†’aβ‹…A})\text{GOTO}(I_0, a) = \text{CLOSURE}(\{ A \to a \cdot A \}):
    • Dot precedes Aβ€…β€ŠβŸΉβ€…β€ŠA \implies add Aβ†’β‹…aAA \to \cdot a A and Aβ†’β‹…bA \to \cdot b
    • I3={Aβ†’aβ‹…A,Β Aβ†’β‹…aA,Β Aβ†’β‹…b}\mathbf{I_3} = \{ A \to a \cdot A, \ A \to \cdot a A, \ A \to \cdot b \}
  • GOTO(I0,b)=CLOSURE({Aβ†’bβ‹…})=I4={Aβ†’bβ‹…}\text{GOTO}(I_0, b) = \text{CLOSURE}(\{ A \to b \cdot \}) = \mathbf{I_4} = \{ A \to b \cdot \}

Transitions from I2I_2:

  • GOTO(I2,A)=CLOSURE({Sβ†’AAβ‹…})=I5={Sβ†’AAβ‹…}\text{GOTO}(I_2, A) = \text{CLOSURE}(\{ S \to A A \cdot \}) = \mathbf{I_5} = \{ S \to A A \cdot \}
  • GOTO(I2,a)=I3\text{GOTO}(I_2, a) = I_3 (same items as I3I_3)
  • GOTO(I2,b)=I4\text{GOTO}(I_2, b) = I_4 (same items as I4I_4)

Transitions from I3I_3:

  • GOTO(I3,A)=CLOSURE({Aβ†’aAβ‹…})=I6={Aβ†’aAβ‹…}\text{GOTO}(I_3, A) = \text{CLOSURE}(\{ A \to a A \cdot \}) = \mathbf{I_6} = \{ A \to a A \cdot \}
  • GOTO(I3,a)=I3\text{GOTO}(I_3, a) = I_3 (self-loop)
  • GOTO(I3,b)=I4\text{GOTO}(I_3, b) = I_4

States I1,I4,I5,I6I_1, I_4, I_5, I_6 have dots at the end (completed items).
Total Canonical States = 7 states (I0I_0 through I6I_6).

Step 3: Construct the LR(0) Parsing Table

StateAction: aAction: bAction: $GOTO: SGOTO: A
0s3s_3s4s_412
1Accept
2s3s_3s4s_45
3s3s_3s4s_46
4r3r_3r3r_3r3r_3
5r1r_1r1r_1r1r_1
6r2r_2r2r_2r2r_2

Notice that in States 4, 5, and 6, reductions r3,r1,r2r_3, r_1, r_2 are placed unconditionally across all terminal columns (a, b, and $)!
Because every single cell contains at most one action, the grammar is strictly LR(0)!


Example 2: Proving an Arithmetic Expression Grammar is NOT LR(0)​

Consider the grammar:

Sβ†’EEβ†’E+T∣TTβ†’id\begin{aligned} S &\to E \\ E &\to E + T \mid T \\ T &\to \text{id} \end{aligned}

Prove analytically that this grammar is NOT LR(0) by constructing the conflicting state.

Step-by-Step Analytical Proof:

  1. Augment the grammar: Sβ€²β†’SS' \to S.

  2. Compute state I0=CLOSURE({Sβ€²β†’β‹…S})I_0 = \text{CLOSURE}(\{ S' \to \cdot S \}):

    • Includes Sβ€²β†’β‹…SS' \to \cdot S
    • Includes Sβ†’β‹…ES \to \cdot E
    • Includes Eβ†’β‹…E+TE \to \cdot E + T and Eβ†’β‹…TE \to \cdot T
    • Includes Tβ†’β‹…idT \to \cdot \text{id}
  3. Compute state I1=GOTO(I0,E)I_1 = \text{GOTO}(I_0, E):

    I1=CLOSURE({S→E⋅, E→E⋅+T})I_1 = \text{CLOSURE}(\{ S \to E \cdot, \ E \to E \cdot + T \})
  4. Inspect state I1I_1:

    • Item Sβ†’Eβ‹…S \to E \cdot is a completed reduce item. In LR(0), it requires Reduce Sβ†’ES \to E placed in ALL terminal columns, including + and $.
    • Item Eβ†’Eβ‹…+TE \to E \cdot + T is a shift item on terminal +. It requires Shift on column +.
  5. Evaluate table cell ACTION[1,+]\text{ACTION}[1, +]:

    ACTION[1,+]={Shift,Reduce S→E}\text{ACTION}[1, +] = \{ \text{Shift}, \quad \text{Reduce } S \to E \}
  6. A severe Shift/Reduce Conflict exists in state I1I_1. Therefore, the grammar is NOT LR(0).


🎯 Exam & Interview Pitfall Check​

Core Conceptual Questions

Question 1: "How many LR(0) items are generated by a production rule of length n, and what is the rule for epsilon productions?"
Key Focus Points:

  • A production Aβ†’X1X2…XnA \to X_1 X_2 \dots X_n has nn symbols on its right-hand side and generates exactly n+1n + 1 LR(0) items (the dot can occupy positions 0,1,…,n0, 1, \dots, n).
  • For an epsilon production Aβ†’Ο΅A \to \epsilon, length n=0n = 0. It generates exactly 1 item: Aβ†’β‹…A \to \cdot. This item is immediately a complete reduce item.

Question 2: "Why does LR(0) table construction place reductions in every terminal column, and why does this cause conflicts?"
Key Focus Points:

  • Zero Lookahead: The '0' in LR(0) denotes zero tokens of lookahead. The parser makes reduction decisions based solely on the stack contents without inspecting the next input symbol.
  • Resulting Fragility: Whenever a state contains both a shift item and a completed reduce item, placing the reduction across the entire row creates an unavoidable Shift/Reduce conflict under the shift terminal.
Common Interview Traps: Architectural Trade-Offs

Trap 1: Placing reductions only under FOLLOW symbols in an LR(0) table.
Answer: Fatal concept mix-up. Placing reductions only under FOLLOW(A)\text{FOLLOW}(A) is the definition of SLR(1), NOT LR(0). In LR(0), reductions MUST be placed in every terminal column plus $.

Trap 2: Believing left-recursive grammars cannot be parsed by LR(0).
Answer: Misconception carried over from LL(1). Bottom-up LR parsers naturally handle left-recursive grammars without infinite loops or stack overflow. In fact, left recursion is preferred in bottom-up parsing because it keeps the stack depth bounded during list processing!


πŸ’¬

Discussion & Doubts