Builds an SLR(1) action/goto table from an @engine lr/@engine glr
grammar -- shared by both Grammar.LR (which additionally requires the
result be conflict-free) and Grammar.GLR (which accepts conflicts and
forks over them at runtime).
Pipeline: Grammar.LRTable.Desugar flattens grammar.rules' PEG-shaped
IR into a flat CFG production list; Grammar.LRTable.Sets computes
nullable/FIRST/FOLLOW over that list; Grammar.LRTable.Automaton builds
the canonical LR(0) item-set collection and, on top of it, the SLR(1)
action/goto tables. build/1 never itself decides a conflict is
fatal -- a cell with more than one action is simply present in
action as a list of length > 1; it's each engine's own call whether
that's acceptable.
Summary
Functions
Builds the SLR(1) table for grammar, or every unsupported-construct error found.
Every {state, symbol, [actions]} cell with more than one action -- a shift/reduce or reduce/reduce conflict.
The current lookahead terminal name at pos in stream, or
end_symbol once input is exhausted -- shared by every LR-family
engine (Grammar.LR, Grammar.GLR.Runtime, and generated
Grammar.Native.LR/.GLR code alike), interpreted or compiled.
The shared "no action applies here" parse error, naming the offending token (or end of input).
Types
@type state_id() :: Grammar.LRTable.Automaton.state_id()
@type t() :: %Grammar.LRTable{ action: %{ required(state_id()) => %{ required(atom()) => [Grammar.LRTable.Automaton.action()] } }, end_symbol: atom(), goto: %{required(state_id()) => %{required(atom()) => state_id()}}, productions: %{required(non_neg_integer()) => Grammar.LRTable.Production.t()}, root: atom(), start_state: state_id(), start_symbol: atom() }
Functions
@spec build(Aether.Grammar.t()) :: {:ok, t()} | {:error, [Ichor.Error.t()]}
Builds the SLR(1) table for grammar, or every unsupported-construct error found.
@spec conflicts(t()) :: [{state_id(), atom(), [Grammar.LRTable.Automaton.action()]}]
Every {state, symbol, [actions]} cell with more than one action -- a shift/reduce or reduce/reduce conflict.
@spec current_terminal(tuple(), non_neg_integer(), atom()) :: atom()
The current lookahead terminal name at pos in stream, or
end_symbol once input is exhausted -- shared by every LR-family
engine (Grammar.LR, Grammar.GLR.Runtime, and generated
Grammar.Native.LR/.GLR code alike), interpreted or compiled.
@spec unexpected_error(tuple(), non_neg_integer()) :: Ichor.Error.t()
The shared "no action applies here" parse error, naming the offending token (or end of input).