Algorithms
CLOSURE(I) {
repeat {
for each item [A → αBβ, a] in I do {
for each production B → γ in G' do {
for each terminal b in first(βa) do {
add [B → ●γ, b] to set I;
}
}
}
} until no more items are add ti I;
return I;
}
GOTO(I, X) {
initialize J to empty set;
for each item [A → α●Xβ, a] in I do {
add item [A → αX●β, a] to set J;
}
return CLOSURE(J);
}
items(G') {
initialize C to {CLOSURE( { [S' → ●S,$] } );
repeat {
for each set of items I in C do {
for each grammar symbol X do {
if (GOTO(I,X) is not empty and not in C then
add GOTO(I,X) to C;
}
}
} until no new sets of items are added to C;
}
Algorithm
1. Construct the collection C' = { I0, ..., In } of LR(1) items for G'.
2. Parser states are constructed from Ii as follows.
(a) If [A → α●aβ, b] is in Ii and GOTO(Ii, a) = Ij, then set
ACTION[i, a] to "shift j" for all terminal a.
(b) If [A → α●, a] is in Ii and A ≠ S', then set ACTION[i, a]
to "reduce A → α".
(c) If [S' → S, $] is in Ii, then set ACTION[i, $] to "accept".
3. The goto transitions for state i are constructed for all
nonterminals A using the rule: If GOTO(Ii, A) = Ij, then
GOTO[i, A] = j.
4. All entries not defined by rules (2) and (3) are made "error".
5. The initial state of the parser is the one constructed from
the set of items containing [S' → ●S, $].
Starting from this augmented grammar
0) S' → S
1) S → XX
2) X → aX
3) X → b
we arrive at this LR(1) sets of items
I0: S' → ●S, $ I4: X → b●, a/b
S → ●XX, $
X → ●aX, a/b I5: S → XX●, $
X → ●b, a/b
I6: X → a●X, $
I1: S' → S●, $ X → ●aX, $
X → ●b, $
I2: S → X●X, $
X → ●aX, $ I7: X → b●, $
X → ●b, $
I8: X → aX●, a/b
I3: X → a●X, a/b
X → ●aX, a/b I9: X → aX●, $
X → ●b, a/b
From the above sets of LR(1) items, we obtain this LR(1) parsing tables
==================================
STATE | ACTION | GOTO
+---------------+----------
| a b $ | S X
-------+---------------+----------
0 | s3 s4 | 1 2
1 | acc |
2 | s6 s7 | 5
3 | s3 s4 | 8
4 | r3 r3 |
5 | r1 |
6 | s6 s7 | 9
7 | r3 |
8 | r2 r2 |
9 | r2 |
-------+---------------+----------
Consider the example LR(1) parser table we derived earlier.
I0: S' → ●S, $ I4: X → b●, a/b
S → ●XX, $
X → ●aX, a/b I5: S → XX●, $
X → ●b, a/b
I6: X → a●X, $
I1: S' → S●, $ X → ●aX, $
X → ●b, $
I2: S → X●X, $
X → ●aX, $ I7: X → b●, $
X → ●b, $
I8: X → aX●, a/b
I3: X → a●X, a/b
X → ●aX, a/b I9: X → aX●, $
X → ●b, a/b
What the LALR parser does is to merge these 3 pairs of states to just 3 states like this:
I36: X → a●X, a/b/$
X → ●aX, a/b/$
X → ●b, a/b/$
I47: X → b●, a/b/$
I89: X → aX●, a/b/$
We describe the LALR parse table construction as a post-processing of the LR parse table. However, there are techniques to construct the LALR table without fully constructing the LR table first.