# `Grammar.Native.LR`
[🔗](https://github.com/joetjen/ichor/blob/v0.3.0/lib/grammar/native/lr.ex#L1)

The compile-time codegen backend for `@engine lr` grammars: builds the
SLR(1) table via `Grammar.LRTable` once, at Elixir-compile-time (inside
`use Ichor`'s macro expansion), and requires it be conflict-free --
same requirement `Grammar.LR.compile/1` enforces at runtime, just
checked once here instead of on every call.

Since LR has no forking at all, everything compiles away into direct
calls: one generated function per automaton state
(`lr_state_<N>/4`), each a compiled `case` on the current lookahead
terminal (`Grammar.LRTable.current_terminal/3`) deciding shift, reduce,
or accept -- mirroring how `Grammar.Native.RuleCompiler` gives every
PEG IR node its own function calling other nodes' functions directly,
never an interpreted instruction loop.

A shift's target state is always compile-time-known (fixed by the
*current* state + the matched terminal), so it's a direct call to
that state's own function -- zero lookup, the actual hot path (this
runs once per input token). A reduce's `GOTO` target is *not*
compile-time-known -- it depends on whichever state popping the
production's RHS happens to expose, which varies with the parse's own
history -- so every reduce goes through `lr_dispatch/5`, one compiled
clause per state (a jump table, not a `Map.get`), and `lr_goto/2`, one
compiled clause per `{nonterminal, state}` pair. Capture-building
itself stays the shared, unchanged `Grammar.LRTable.Captures.build/3`
(via `Grammar.LR.Stack.reduce/4`, `Macro.escape`'d one production per
reduce clause) -- a small, data-driven fold over a handful of RHS
positions, not the hot per-token loop this module actually compiles
away.

# `generate`

```elixir
@spec generate(Aether.Grammar.t(), module()) :: Macro.t()
```

Generates the full quoted body (lexer + compiled LR parser + `parse/1,2` + `run/1,2`) for `grammar`, dispatching to `actions_module`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
