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

The deterministic bottom-up backend: builds an SLR(1) table via
`Grammar.LRTable` and requires it be conflict-free -- a real conflict
is a compile-time error here (`compile/1`), never something forked
through (that's what `Grammar.GLR` is for). No graph-structured-stack
bookkeeping at all: an ordinary shift-reduce loop over a single stack.

Only ever runs `@engine lr` grammars -- same reasoning `Grammar.VM`/
`Grammar.Native` reject anything but `@engine peg`: the tag is a
grammar author's own declared choice of backend, and running a
grammar through the wrong one is a bug worth catching immediately
rather than silently doing something unintended.

Builds the exact same raw-capture shape `Ichor.Actions` expects
(`{:token,...}`/`{:rule,...}`/`{:text,...}`) at every reduce, using
`Grammar.LRTable.Production.t()`'s own `captures` plan -- see its
moduledoc for what each capture kind means. Reuses
`Grammar.VM.RuleCompiler.capture_shapes/1` unchanged (a pure static
pass over `grammar.rules`' IR, unaffected by how a table-driven engine
parses it) so `Ichor.Actions.evaluate/5` needs no changes at all to
work with this backend.

# `t`

```elixir
@type t() :: %Grammar.LR{
  capture_shapes: Ichor.Actions.capture_shapes(),
  table: Grammar.LRTable.t()
}
```

# `compile`

```elixir
@spec compile(Aether.Grammar.t()) :: {:ok, t()} | {:error, [Ichor.Error.t()]}
```

Builds `grammar`'s SLR(1) table and requires it be conflict-free, or reports every conflict found.

# `parse`

```elixir
@spec parse(Aether.Grammar.t(), String.t(), term()) ::
  {:ok, non_neg_integer()} | {:error, Ichor.Error.t() | [Ichor.Error.t()]}
```

Matches `input` against `grammar`'s root, requiring the entire (tokenized) input to be consumed. A bare recognizer -- no `Ichor.Actions` involved.

# `run`

```elixir
@spec run(Aether.Grammar.t(), String.t(), module(), Ichor.Actions.context()) ::
  {:ok, term()} | {:error, Ichor.Error.t() | [Ichor.Error.t()]}
```

Like `parse/3`, but runs the match through `actions_module` starting from `initial_context`, returning the grammar's actual evaluated result.

---

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