Grammar.Native.LR (Ichor v0.2.0)

Copy Markdown View Source

The compile-time codegen backend for @engine lr grammars: builds the SLR(1) table via Grammar.LRTable once, at Elixir-compile-time (inside use Ichor's macro expansion), and requires it be conflict-free -- same requirement Grammar.LR.compile/1 enforces at runtime, just checked once here instead of on every call.

Since LR has no forking at all, everything compiles away into direct calls: one generated function per automaton state (lr_state_<N>/4), each a compiled case on the current lookahead terminal (Grammar.LRTable.current_terminal/3) deciding shift, reduce, or accept -- mirroring how Grammar.Native.RuleCompiler gives every PEG IR node its own function calling other nodes' functions directly, never an interpreted instruction loop.

A shift's target state is always compile-time-known (fixed by the current state + the matched terminal), so it's a direct call to that state's own function -- zero lookup, the actual hot path (this runs once per input token). A reduce's GOTO target is not compile-time-known -- it depends on whichever state popping the production's RHS happens to expose, which varies with the parse's own history -- so every reduce goes through lr_dispatch/5, one compiled clause per state (a jump table, not a Map.get), and lr_goto/2, one compiled clause per {nonterminal, state} pair. Capture-building itself stays the shared, unchanged Grammar.LRTable.Captures.build/3 (via Grammar.LR.Stack.reduce/4, Macro.escape'd one production per reduce clause) -- a small, data-driven fold over a handful of RHS positions, not the hot per-token loop this module actually compiles away.

Summary

Functions

Generates the full quoted body (lexer + compiled LR parser + parse/1,2 + run/1,2) for grammar, dispatching to actions_module.

Functions

generate(grammar, actions_module)

@spec generate(Aether.Grammar.t(), module()) :: Macro.t()

Generates the full quoted body (lexer + compiled LR parser + parse/1,2 + run/1,2) for grammar, dispatching to actions_module.