# `Grammar.LRTable`
[🔗](https://github.com/joetjen/ichor_runtime/blob/v0.2.0/lib/grammar/lr_table.ex#L1)

The SLR(1) action/goto table shape itself, plus the two lookups every
LR-family engine needs at match time -- interpreted (`Grammar.LR`,
`Grammar.GLR.Runtime`) or compiled (generated `Grammar.Native.LR`/
`.GLR` code) alike.

Building a table from a grammar (`Grammar.LRTable.Builder.build/1`,
which needs `Desugar`/`Sets`/`Automaton`) is a dev-time-only concern
that stays in `ichor` proper -- this module holds only what a
generated parser (or the interpreted engines) still calls once a
table already exists.

# `action`

```elixir
@type action() ::
  {:shift, state_id()} | {:reduce, production_id :: non_neg_integer()} | :accept
```

# `state_id`

```elixir
@type state_id() :: non_neg_integer()
```

# `t`

```elixir
@type t() :: %Grammar.LRTable{
  action: %{required(state_id()) =&gt; %{required(atom()) =&gt; [action()]}},
  end_symbol: atom(),
  goto: %{required(state_id()) =&gt; %{required(atom()) =&gt; state_id()}},
  productions: %{required(non_neg_integer()) =&gt; Grammar.LRTable.Production.t()},
  root: atom(),
  start_state: state_id(),
  start_symbol: atom()
}
```

# `current_terminal`

```elixir
@spec current_terminal(tuple(), non_neg_integer(), atom()) :: atom()
```

The current lookahead terminal name at `pos` in `stream`, or
`end_symbol` once input is exhausted -- shared by every LR-family
engine (`Grammar.LR`, `Grammar.GLR.Runtime`, and generated
`Grammar.Native.LR`/`.GLR` code alike), interpreted or compiled.

# `unexpected_error`

```elixir
@spec unexpected_error(tuple(), non_neg_integer()) :: Ichor.Error.t()
```

The shared "no action applies here" parse error, naming the offending token (or end of input).

---

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