LL vs LR Parsing
That LR is "more powerful" in a way that makes LL obsolete. The power difference is real — every LL(k) grammar is LR(k) and not conversely — but most production compilers with hand-written frontends use recursive descent anyway, because error recovery and diagnostics are far easier when the code follows the grammar.
LL — top-down, predictive
When you want a parser you can read and debug by hand, and you control the grammar so you can factor it.
LR — bottom-up, shift-reduce
When the grammar is given and you need the largest class of grammars a deterministic parser can handle.
| Aspect | LL — top-down, predictive | LR — bottom-up, shift-reduce |
|---|---|---|
| Direction | Starts at the start symbol and predicts a production from lookahead. | Starts at the tokens and reduces handles as it recognises them. |
| Left recursion | Loops forever. Must be rewritten out of the grammar. | Handled directly, which is why it fits arithmetic grammars naturally. |
| How you write one | One function per nonterminal. Readable, debuggable, steppable. | A generated table plus a driver loop. Tables are not readable. |
| Error messages | The call stack names the construct being parsed, so a message can say what was expected. | A conflict in a table says which states disagreed, which is harder to phrase for a user. |
| Grammar conflicts | Show up as ambiguity you resolve by factoring. | Show up as shift/reduce and reduce/reduce conflicts in the generator. |
| Typical home | Hand-written frontends, Pratt-style expression parsers. | Parser generators — yacc, bison, LALRPOP, tree-sitter’s GLR variant. |