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

Builds the raw-capture list `Ichor.Actions` expects (`{:token,...}`/
`{:rule,...}`/`{:text,...}`, see `Ichor.Capture.raw_captures/0`) from
one reduced production's own RHS entries -- shared by `Grammar.LR` (a
single linear stack) and `Grammar.GLR` (a graph-structured one): both
reduce the same kind of production, against the same kind of token
stream, needing the exact same per-position classification (see
`Grammar.LRTable.Production`'s own moduledoc for what each capture
kind means), so this logic has exactly one place to live rather than
two copies drifting apart.

Built as a list, in `production.captures`' own RHS-position order,
rather than a map -- a name's position (first occurrence, for one
captured more than once) is real information `Ichor.Actions` relies
on (`Ichor.Capture.position/0`) to evaluate sibling captures in true
source order, which a plain map's own iteration order can't be
trusted to reconstruct (it isn't guaranteed to match insertion order,
and has been observed to differ across Erlang/OTP versions).

# `entry`

```elixir
@type entry() ::
  {value :: Grammar.VM.Token.t() | Ichor.Capture.raw_captures(),
   start_pos :: non_neg_integer(), end_pos :: non_neg_integer()}
```

One popped RHS position: `value` is the shifted `%Token{}` (a
terminal position) or the already-built raw-captures list of a
reduced nonterminal; `start_pos`/`end_pos` are the token-stream span
it covers, needed for a `:text`-kind capture regardless of which RHS
position it sits at (not just the whole production's own span).

# `build`

```elixir
@spec build(Grammar.LRTable.Production.t(), [entry()], tuple()) ::
  Ichor.Capture.raw_captures()
```

Builds the raw-captures list for `production`, given its popped RHS `entries` in order.

# `merge`

```elixir
@spec merge(Ichor.Capture.raw_captures(), atom(), term()) ::
  Ichor.Capture.raw_captures()
```

The first/second/third+ list-promotion rule every raw-capture builder
in Ichor uses (`Grammar.Native.Runtime.Parser.merge_captures/2`,
mirrored here for the LR/GLR side): a name captured more than once
naturally becomes a list without knowing the eventual count in
advance. A new name is appended at the end, landing at its
first-occurrence RHS position relative to whatever's already there
(`build/3` calls this in RHS order); a repeat name updates its
existing entry in place, not moving it.

---

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