sipha
A PEG (Parsing Expression Grammar) parser with a stack-based VM, green/red syntax trees, and optional packrat memoisation.
Features
- Grammar builder — Compose rules with combinators:
byte,class,literal,choice,optional,zero_or_more,node,token, etc. - Green/red trees — Immutable green tree plus position-aware red layer; trivia-aware iterators.
- Structured errors —
ParseError::NoMatchcarries aDiagnosticwith furthest position and expected tokens. - Packrat memoisation —
Engine::with_memo()for guaranteed O(n) on grammars with backtracking. - SIMD literals — Fast literal matching for long tokens (SSE2/AVX2 on x86_64).
- Byte dispatch — O(1) first-byte dispatch for rules like JSON
value.
Quick example
use *;
Parsing with a syntax tree
Use node and token in the builder to emit green/red tree events, then build the tree from the parse output:
use *;
let mut g = new;
g.begin_rule;
g.node;
g.end_of_input;
g.accept;
let built = g.finish.unwrap;
let graph = built.as_graph;
let mut engine = new;
let out = engine.parse.unwrap;
let root = out.syntax_root.unwrap;
assert_eq!;
Error handling
On parse failure, ParseError::NoMatch(diagnostic) contains the furthest byte reached and the set of expected tokens:
if let Err = engine.parse
Grammar macro (sipha-macros)
The sipha-macros crate provides a sipha_grammar! macro so you can write rules in a PEG-style DSL:
use *;
use sipha_grammar;
let built = sipha_grammar! ;
let graph = built.as_graph;
See the sipha-macros README for full syntax. Run: cargo run --example macro_grammar
Examples
examples/macro_grammar.rs— Grammar defined withsipha_grammar!.examples/json_grammar.rs— Full JSON with SIMD literals, diagnostics, memo, and byte dispatch.examples/green_red_tree.rs— Green/red tree and trivia.examples/context_flags.rs— Parse context flags.examples/unicode_and_repeat.rs— Unicode terminals and repetition.
Run with: cargo run --example json_grammar
Safety note
BuiltGraph::as_graph() returns a ParseGraph that borrows from the BuiltGraph via a 'static cast. Keep the BuiltGraph alive and do not mutate it while any ParseGraph (or references derived from it) is in use.