Grammar.Native.RuleCompiler (Ichor v0.7.3)

Copy Markdown View Source

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

compile(grammar, opts \\ [])

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

lossless_rule_fn_name(name)

@spec lossless_rule_fn_name(atom()) :: atom()

The lossless set's function for a rule (compile/2 with lossless: true).

rule_fn_name(name)

@spec rule_fn_name(atom()) :: atom()

The generated function name for a given rule name -- exposed so Grammar.Native can reference the root rule's own matcher.