Compiles every rule in a grammar into quoted Elixir function
definitions run against the lexer's token stream (never raw
characters -- Aether's own two-stage split), mirroring
Grammar.VM.RuleCompiler's own semantics exactly (bare-reference
implicit self-capture, Indent/@samecol, capture-shape rules) but
producing direct function calls instead of bytecode.
Every generated function has the shape (stream :: tuple(), pos :: non_neg_integer(), ref_stack :: [integer()], context :: term()) -> {:ok, new_pos, new_ref_stack, raw_captures} | :fail, where
raw_captures is exactly the ordered-list shape Ichor.Actions
expects ({:token, name, text} / {:rule, name, sub_captures} /
{:text, text} values, keyed by name, in first-occurrence RHS
order -- see Ichor.Capture.raw_captures/0), each value recording
the tokens [pos, new_pos) it matched (Ichor.Capture.at/3), so an
action's error can say where. context is read-only,
threaded through purely so a
Grammar.IR.Custom @native(...) leaf can hand it to
Ichor.CustomRule.match/4 -- nothing else in this module ever reads
it, only passes it along. A RuleRef compiles to a call into that
other rule/token's own compiled function; the grammar's own token/rule
namespaces (passed in as token_names) are what tell the two apart,
exactly as in the VM.
Summary
Functions
Compiles every rule into a list of quoted defp definitions, one named
rule_fn_name/1 per rule plus one per anonymous sub-expression.
The lossless set's function for a rule (compile/2 with lossless: true).
The generated function name for a given rule name -- exposed so Grammar.Native can reference the root rule's own matcher.
Functions
@spec compile(Aether.Grammar.t(), keyword()) :: [Macro.t()]
Compiles every rule into a list of quoted defp definitions, one named
rule_fn_name/1 per rule plus one per anonymous sub-expression.
With lossless: true, the second set a lossless parser runs instead
(lossless_rule_fn_name/1, design/lossless-mode.md): the same
functions under their own names, but every rule call also records
itself for Ichor.Syntax, under Ichor.Syntax.Record.key/0. A set
of its own rather than a flag in the one set, so the ordinary
parser's functions are exactly what they were, and nothing on its path
checks which mode it is in.
The lossless set's function for a rule (compile/2 with lossless: true).
The generated function name for a given rule name -- exposed so Grammar.Native can reference the root rule's own matcher.