The deterministic bottom-up backend: builds an SLR(1) table via
Grammar.LRTable and requires it be conflict-free -- a real conflict
is a compile-time error here (compile/1), never something forked
through (that's what Grammar.GLR is for). No graph-structured-stack
bookkeeping at all: an ordinary shift-reduce loop over a single stack.
Only ever runs @engine lr grammars -- same reasoning Grammar.VM/
Grammar.Native reject anything but @engine peg: the tag is a
grammar author's own declared choice of backend, and running a
grammar through the wrong one is a bug worth catching immediately
rather than silently doing something unintended.
Builds the exact same raw-capture shape Ichor.Actions expects
({:token,...}/{:rule,...}/{:text,...}) at every reduce, using
Grammar.LRTable.Production.t()'s own captures plan -- see its
moduledoc for what each capture kind means. Reuses
Grammar.VM.RuleCompiler.capture_shapes/1 unchanged (a pure static
pass over grammar.rules' IR, unaffected by how a table-driven engine
parses it) so Ichor.Actions.evaluate/5 needs no changes at all to
work with this backend.
Summary
Functions
Builds grammar's SLR(1) table and requires it be conflict-free, or reports every conflict found.
Matches input against grammar's root, requiring the entire (tokenized) input to be consumed. A bare recognizer -- no Ichor.Actions involved.
Like parse/3, but runs the match through actions_module starting from initial_context, returning the grammar's actual evaluated result.
Types
@type t() :: %Grammar.LR{ capture_shapes: Ichor.Actions.capture_shapes(), table: Grammar.LRTable.t() }
Functions
@spec compile(Aether.Grammar.t()) :: {:ok, t()} | {:error, [Ichor.Error.t()]}
Builds grammar's SLR(1) table and requires it be conflict-free, or reports every conflict found.
@spec parse(Aether.Grammar.t(), String.t(), term()) :: {:ok, non_neg_integer()} | {:error, Ichor.Error.t() | [Ichor.Error.t()]}
Matches input against grammar's root, requiring the entire (tokenized) input to be consumed. A bare recognizer -- no Ichor.Actions involved.
@spec run(Aether.Grammar.t(), String.t(), module(), Ichor.Actions.context()) :: {:ok, term()} | {:error, Ichor.Error.t() | [Ichor.Error.t()]}
Like parse/3, but runs the match through actions_module starting from initial_context, returning the grammar's actual evaluated result.