LR(0) Parsing and Canonical Item Sets
LR parsers read input left-to-right and build a rightmost derivation in reverse — a bottom-up parsing strategy used by many real compiler-generator tools (like yacc/bison), in contrast to the top-down approach LL parsers use. Building an LR(0) parser starts with augmenting the grammar with a new start symbol, then computing the canonical collection of item sets: each item set tracks which productions could be "in progress" at a given parsing state, marked with a dot showing how far into the production the parser has read.
The closure operation expands an item set by adding new items whenever the dot sits before a non-terminal — since that non-terminal's own productions could now also be starting. GOTO transitions connect item sets together based on which symbol is consumed, forming the parsing automaton's state graph, which ultimately becomes the parsing table an actual parser implementation would use to decide shift/reduce actions.
This is genuinely intricate to trace by hand for anything beyond a toy grammar, which is exactly why automating the construction — closure, GOTO, and the resulting state table — matters for verifying compiler-construction coursework.
LR(0) vs SLR(1)
Both tables are built from the same canonical collection of LR(0) item sets; they differ only in where reduce actions go. LR(0) puts a reduce in every column of a state that holds a completed item, while SLR(1) only puts the reduce for A → α under the terminals in FOLLOW(A). That one change resolves many conflicts.
Worked example
The expression grammar E → E + T | T, T → T * F | F, F → ( E ) | id has 12 LR(0) states. As an LR(0) table it has two shift/reduce conflicts on *, in the states holding E → T • and E → E + T •, which also hold T → T • * F. SLR(1) resolves both because * is not in FOLLOW(E) = { +, ), $ }, so the grammar is SLR(1) and id * id + id parses successfully.
The grammar S → L = R | R, L → * R | id, R → L is the textbook case that is not SLR(1): "=" is in FOLLOW(R), so one state gets a shift/reduce conflict on "=". It needs LALR(1) or canonical LR(1) lookaheads.