The graph-structured stack itself: nodes keyed by {state, stream_position} (deduplicated -- two derivations that reach the same
state at the same position share one node, the actual efficiency win
over independent parallel stacks), edges labeled with whatever that
edge's own transition produced (a shifted %Grammar.VM.Token{}, or a
reduced nonterminal's own already-built captures map) plus the
provenance accumulated along it so far.
A node can have more than one incoming edge exactly when two
previously-distinct derivations converge (a shift/reduce or
reduce/reduce conflict both survived, or two different reduce paths
happen to land on the same state and position) -- that's genuine local
ambiguity, not a bug, and paths/3's whole job is enumerating every
distinct way to walk backward through however many edges a reduce
needs to pop, independently for each of a node's incoming edges.
Positions live on the node identity itself ({state, position}), not
on the edge -- which is what makes a :text-kind capture's span
(Grammar.LRTable.Captures) derivable per RHS position directly from
the two nodes an edge connects, with no separate bookkeeping needed.
Summary
Functions
Adds an edge from -> to labeled value/provenance, unless an identical one already exists.
Every distinct length-k backward path from node: {origin_node, entries, combined_provenance}, entries in left-to-right (RHS)
order as Grammar.LRTable.Captures.entry() triples ({value, start_pos, end_pos}, the span read straight off the two nodes each
edge connects). More than one result means the popped span was
reached via more than one derivation -- local ambiguity, resolved
later by comparing accumulated provenance, not decided here.
Types
@type edge() :: {node_id(), term(), provenance()}
@type node_id() :: {Grammar.LRTable.state_id(), non_neg_integer()}
@type provenance() :: [non_neg_integer()]
Functions
Adds an edge from -> to labeled value/provenance, unless an identical one already exists.
@spec new() :: t()
@spec paths(t(), node_id(), non_neg_integer()) :: [ {node_id(), [Grammar.LRTable.Captures.entry()], provenance()} ]
Every distinct length-k backward path from node: {origin_node, entries, combined_provenance}, entries in left-to-right (RHS)
order as Grammar.LRTable.Captures.entry() triples ({value, start_pos, end_pos}, the span read straight off the two nodes each
edge connects). More than one result means the popped span was
reached via more than one derivation -- local ambiguity, resolved
later by comparing accumulated provenance, not decided here.