Grammar.VM.Compiler (Ichor v0.2.1)

Copy Markdown View Source

The combinator half of Grammar.VM's bytecode compilation, shared between the character-level compiler (token bodies, run by the lexer) and the token-stream-level compiler (rule bodies, run by the parser). Seq/Choice/Star/Plus/Opt/Rep/AndPred/NotPred compile identically either way -- only the leaf nodes differ (Literal/CharClass/Any/RuleRef for tokens; RuleRef/Indent/ Capture for rules -- tokens can never contain a Capture), so each caller supplies its own leaf_fun for those.

Every compile/3 clause returns {ops, next_counter}, where ops is a flat list of instructions possibly containing {:label, n} markers (resolved later by Grammar.VM.Linker) and counter is the next unused label number -- threaded through so nested compilation never reuses a label.

The instruction set is the standard PEG/LPeg one (Ierusalimschy's "A Text Pattern-Matching Tool based on Parsing Expression Grammars"): choice/commit for ordered choice and *, back_commit/fail_twice for the two lookahead predicates. Grammar.Analysis already guarantees no Star/Plus here wraps an unconditionally-empty match at the point a grammar author wrote it directly, but test_progress below is still a hard runtime guarantee rather than relying on that alone -- see the comment on the Star clause.

Summary

Types

leaf_fun()

@type leaf_fun() :: (Grammar.IR.expr(), non_neg_integer() ->
                 {ops(), non_neg_integer()})

ops()

@type ops() :: [term()]

Functions

compile(other, counter, leaf_fun)

@spec compile(Grammar.IR.expr(), non_neg_integer(), leaf_fun()) ::
  {ops(), non_neg_integer()}

fresh(counter)