The GSS-driving shift-reduce/fork loop itself, shared by the
interpreted Grammar.GLR (which wraps a Grammar.LRTable's plain
action/goto maps into closures) and Grammar.Native.GLR (which
passes compiled per-state functions instead) -- extracted so both
reuse the exact same, already-proven algorithm. The graph-structured
stack itself (node merging, multi-path reduce enumeration --
Grammar.GLR.GSS) is inherently a runtime, input-driven data
structure that can't compile away no matter which engine calls into
it; only how a caller looks up actions/goto for a state varies.
Summary
Types
Builds one reduction's captures: Grammar.LRTable.Captures.build/3, or Ichor.Syntax.Record.reduced/3 for a lossless parse.
Functions
Runs the GSS shift-reduce/fork loop over stream, starting from
start_state, dispatching every lookup through action_fn/goto_fn.
Types
@type action_fn() :: (Grammar.LRTable.state_id(), atom() -> [Grammar.LRTable.action()])
@type build_fn() :: (Grammar.LRTable.Production.t(), [Grammar.LRTable.Captures.entry()], tuple() -> Ichor.Capture.raw_captures())
Builds one reduction's captures: Grammar.LRTable.Captures.build/3, or Ichor.Syntax.Record.reduced/3 for a lossless parse.
@type goto_fn() :: (Grammar.LRTable.state_id(), atom() -> Grammar.LRTable.state_id() | nil)
Functions
@spec run( action_fn(), goto_fn(), %{required(non_neg_integer()) => Grammar.LRTable.Production.t()}, Grammar.LRTable.state_id(), atom(), tuple(), build_fn() ) :: {:ok, non_neg_integer(), Ichor.Capture.raw_captures()} | {:error, Ichor.Error.t()}
Runs the GSS shift-reduce/fork loop over stream, starting from
start_state, dispatching every lookup through action_fn/goto_fn.
build builds each reduction's captures. A lossless parse passes
Ichor.Syntax.Record.reduced/3, so the rules' records travel with
them, and the run picks the same derivation either way: a surviving
ambiguity is broken by provenance, which build never touches.