The linear LR stack's shift/reduce mechanics -- shared by the
interpreted Grammar.LR and Grammar.Native.LR's per-state
generated code, since a stack push/pop is exactly the same operation
regardless of whether the state driving it came from a Map.get or a
compiled case.
A stack entry is {state, start_pos, end_pos, value}: state is
needed after a reduce to know which GOTO to consult -- the state a
pop exposes isn't knowable until then, even when which production
reduced is already compile-time-known (the same production can be
reduced from more than one calling context, exposing a different
state each time). start_pos/end_pos are token-stream indices,
needed for a :text-kind capture's span regardless of which RHS
position it sits at (Grammar.LRTable.Captures). value is the
shifted %Grammar.VM.Token{} itself, or a reduced nonterminal's own
already-built captures map.
Summary
Functions
Pushes a reduced nonterminal's captures onto rest_stack (as returned by reduce/4), landing in target_state.
Pushes a freshly-shifted token onto stack, landing in state.
Pops production's own RHS length off stack, builds its captures
via Grammar.LRTable.Captures.build/3, and returns {exposed_state, rest_stack, start_pos, end_pos, captures} -- exposed_state is
whatever's now on top (the caller's own job to look up GOTO for),
start_pos/end_pos the span the whole reduced production covers
(both pos, for a zero-width/epsilon production).
Types
@type entry() :: {state :: term(), non_neg_integer(), non_neg_integer(), term()}
Functions
@spec push_reduced([entry()], term(), non_neg_integer(), non_neg_integer(), map()) :: [entry()]
Pushes a reduced nonterminal's captures onto rest_stack (as returned by reduce/4), landing in target_state.
@spec push_token( [entry()], term(), Grammar.VM.Token.t(), non_neg_integer(), non_neg_integer() ) :: [ entry() ]
Pushes a freshly-shifted token onto stack, landing in state.
@spec reduce([entry()], Grammar.LRTable.Production.t(), tuple(), non_neg_integer()) :: {term(), [entry()], non_neg_integer(), non_neg_integer(), map()}
Pops production's own RHS length off stack, builds its captures
via Grammar.LRTable.Captures.build/3, and returns {exposed_state, rest_stack, start_pos, end_pos, captures} -- exposed_state is
whatever's now on top (the caller's own job to look up GOTO for),
start_pos/end_pos the span the whole reduced production covers
(both pos, for a zero-width/epsilon production).