Grammar.VM.TokenInterpreter (Ichor v0.2.1)

Copy Markdown View Source

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

raw_capture()

@type raw_capture() ::
  {:token, atom(), String.t()} | {:rule, atom(), map()} | {:text, String.t()}

rule_matcher()

@type rule_matcher() :: (tuple(), non_neg_integer() ->
                     {:ok, non_neg_integer(), raw_capture()} | :fail)

Functions

run(instructions, entry, stream, context \\ nil)

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

run_from(instructions, entry, stream, start_pos, context \\ nil)

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