Grammar.LRTable.Captures (IchorRuntime v0.5.0)

Copy Markdown View Source

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.

Every value it builds records the token range it matched (Ichor.Capture.at/3), for Ichor.Actions to turn into its span. A helper's captures, spliced in, were recorded when the helper was reduced and keep their ranges.

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).

Summary

Types

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).

Functions

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

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.

Types

entry()

@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).

Functions

build(production, entries, stream)

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

merge(captures, name, value)

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.