Runs a Grammar.VM.RuleCompiler-produced program against a lexed token
stream -- the machine Grammar.VM uses for the parser stage.
Alongside recognition, it builds the raw capture tree Ichor.Actions
needs: each rule invocation gets its own "frame" (a
%{pending: [...], captures: %{}} accumulator), pushed on :call and
popped on :return, populated by the :cap_start/:cap_end pairs
Grammar.VM.RuleCompiler brackets every capture (implicit or explicit)
with.
Structurally the same backtracking discipline as
Grammar.VM.CharInterpreter (including snapshotting the call stack in
every choice point, for the same reason -- see that module's docs),
plus two more things to snapshot/restore: the capture-in-progress
frame (a failed alternative's partial captures must never leak into
a sibling alternative that goes on to succeed) and the @indent/
@samecol reference-column stack.
Star's loop-back uses :test_progress, not plain :commit -- a
runtime guard against a body that matches without consuming anything
(see Grammar.VM.Compiler's docs on why this can't be left to
Grammar.Analysis's static empty-repetition check alone).
context is threaded through every instruction purely so {:custom, ...} (a Grammar.IR.Custom @native(...) node) can hand it to
Ichor.CustomRule.match/4 -- every other instruction ignores it. It's
read-only here: matching never produces a new context, only
Ichor.Actions.evaluate/5 does that, between top-level forms.
Summary
Functions
Attempts to match entry against stream (a tuple of Grammar.VM.Token,
for O(1) indexed access) starting at position 0. On success, returns the
first unconsumed stream index and the matched rule's own raw capture
map -- the caller decides whether the index means "matched everything".
Like run/4, but starts at start_pos instead of 0 -- for matching one of several top-level occurrences in the same stream (Grammar.VM.run_sequence/4).
Types
@type rule_matcher() :: (tuple(), non_neg_integer() -> {:ok, non_neg_integer(), raw_capture()} | :fail)
Functions
@spec run(tuple(), non_neg_integer(), tuple(), term()) :: {:ok, non_neg_integer(), %{optional(atom()) => raw_capture() | [raw_capture()]}} | :fail
Attempts to match entry against stream (a tuple of Grammar.VM.Token,
for O(1) indexed access) starting at position 0. On success, returns the
first unconsumed stream index and the matched rule's own raw capture
map -- the caller decides whether the index means "matched everything".
@spec run_from(tuple(), non_neg_integer(), tuple(), non_neg_integer(), term()) :: {:ok, non_neg_integer(), %{optional(atom()) => raw_capture() | [raw_capture()]}} | :fail
Like run/4, but starts at start_pos instead of 0 -- for matching one of several top-level occurrences in the same stream (Grammar.VM.run_sequence/4).