Expand description
§tygr — TYpe into Grammar Routines
Define grammars as Rust types and derive the routine work of grammar handling: a parser, a printer, and a presentation (in EBNF).
§Design
Derive Grammar on a struct or enum to get a parser, a printer, and
a BNF presentation for free. Each supported Rust construct maps to an
EBNF concept.
| Rust construct | EBNF (Wirth 1977) |
|---|---|
struct | concatenation (A B C) |
enum | alternation (A B | C) |
(A, B, …) | inline concatenation |
Either<A, B> | inline alternation (A | B) |
Vec<T> | repetition ({ T }) |
Vec1<T> | one-or-more repetition (T { T }) |
Option<T> | optional ([ T ]) |
Box<T> | recursive indirection |
NotFollowedBy<G> | negative lookahead (!G), consumes nothing |
Hidden<T> | parsed/printed, omitted from BNF |
Raw<T> | parsed via T, kept as the raw matched text |
Range<T> | parsed via T, kept alongside its [start, end) span |
Wrap<L, T, R> / Prefix<P, T> / Suffix<T, S> | concatenation shorthands, Deref-ing to T |
VecSep<T, S> | one-or-more repetition with separators (T { S T }) |
For a type that isn’t itself a direct concatenation/alternation of other
grammars, but is instead built from one (e.g. parsing digits into a
u32), derive GrammarFromStr,
GrammarFromOther, or
GrammarTryFromOther instead — each builds
Self from a parsed GrammarFrom::Source via FromStr, From, or
TryFrom respectively.
#[grammar(...)] on a #[derive(Grammar)] type:
name = "..."— override the BNF rule name (defaults to the type name).hidden— same effect as wrapping inHidden<T>, but on a whole struct/enum.inline— splice this type’s own definition wherever it’s referenced, instead of a rule reference.validated— after a successful parse, runValidate::validateon the value; a rejection backtracks as if the grammar hadn’t matched.
§Feature Flags
The tygr crate enables the trace_one_node feature by default.
Available features are:
| Feature | Description |
|---|---|
default | Enables trace_one_node. |
trace | Enables all tracing features. |
trace_pos | Traces parser positions. |
trace_one_node | Traces only the nearest grammar node for each attempt. |
trace_all_nodes | Traces the complete grammar node chain for each attempt. |
lower_bnf_name | Converts generated BNF names to lowercase. |
upper_bnf_name | Converts generated BNF names to uppercase. |
§Quick Example
use tygr::*;
#[derive(Grammar)]
pub struct Expr(pub Expr1, pub Vec<(Wrap<Ws, Op1, Ws>, Expr1)>);
#[derive(Grammar)]
pub enum Op1 {
Add(StringEq!("+")),
Sub(StringEq!("-")),
}
#[derive(Grammar)]
pub struct Expr1(pub Expr2, pub Vec<(Wrap<Ws, Op2, Ws>, Expr2)>);
#[derive(Grammar)]
pub enum Op2 {
Mul(StringEq!("*")),
Div(StringEq!("/")),
}
#[derive(Grammar)]
pub enum Expr2 {
Paren(Wrap<(StringEq!("("), Ws), Box<Expr>, (Ws, StringEq!(")"))>),
Number(Int),
}
char_class!(pub IsDigit, "digit", |ch| ch.is_ascii_digit());
#[derive(Grammar)]
pub struct Int(pub StringOf1<IsDigit>);
char_class!(pub IsSpace, "space", |ch| ch.is_ascii_whitespace());
#[derive(Grammar)]
#[grammar(hidden)]
pub struct Ws(pub StringOf<IsSpace>);
let e = Expr::parse("1 + 2 * 3").unwrap();
assert_eq!(e.print(), "1 + 2 * 3");
assert_eq!(
bnf_rules![Expr, Op1, Expr1, Op2, Expr2, Int].to_string(),
"Expr = Expr1 { Op1 Expr1 } .\n\
Op1 = \"+\" | \"-\" .\n\
Expr1 = Expr2 { Op2 Expr2 } .\n\
Op2 = \"*\" | \"/\" .\n\
Expr2 = \"(\" Expr \")\" | Int .\n\
Int = 'digit' { 'digit' } ."
);Modules§
- bnf
- Intermediate representation for BNF/EBNF generation with optimization.
Macros§
- String
Eq - Expand a string literal into a literal-token type.
- String
EqCI - Expand a string literal into a case-insensitive literal-token type.
- bnf_
rules - Collect BNF rule definitions from one or more
GrammarRuletypes. - char_
class - Define a
CharClassin one line.
Structs§
- CharOf
- Matches exactly one character satisfying a character class.
- Error
- A parse failure. Carries no detail unless the relevant
trace_*feature is enabled (see the crate-level feature flag table); useError::posandError::tracesto inspect it rather than the fields directly, since those degrade gracefully across feature configurations. - Frame
- One named rule call in a
Trace’scontext. - Hidden
- Wrapper that hides a grammar element from BNF output.
- NotFollowed
By - Zero-width negative lookahead: matches the empty string, but only when the following input does not match the wrapped grammar. Consumes nothing and prints nothing.
- OLC
- Converts between byte offsets and
(line, character)positions in a fixed input string. - Prefix
- Sequence of two grammars,
Deref-ing to the second. - Range
- Wrapper that records the
[start, end)input span its ranged value was parsed from. - Raw
- Wrapper that parses using the wrapped grammar but keeps only the raw
matched text as a
String. - String
Of - Matches zero or more characters satisfying a character class, collected into a
String. - String
Of1 - Matches one or more characters satisfying a character class, collected into a
String. - Suffix
- Sequence of two grammars,
Deref-ing to the first. - Trace
- One recorded parse attempt at
Error::pos— a rule call chain and what it expected to find there. MultipleTraces at the same position are candidates: any one of them matching would have let the parse continue. - Vec1
- Like
Vec, but matches one or more items rather than zero or more. - VecSep
- One or more items, with a separator between each pair.
- Wrap
- Sequence of three grammars,
Deref-ing to the middle one.
Enums§
- Expectation
- One candidate for what would have matched at a
Trace’s recorded position.
Traits§
- Char
Class - Trait for character-class predicates.
- Grammar
- Parse, print, and describe (as BNF) a grammar element.
- Grammar
From - Bridges a mapped type to its source grammar.
- Grammar
Rule - A
Grammarwith a name and top-level BNF definition, so it can appear as its own rule (e.g. inbnf_rules!) rather than only inline in some other rule’s definition. - Into
Inner - Unwrap a grammar wrapper (e.g.
Wrap,Prefix,Suffix) to get at the value it wraps. - Validate
- Post-parse validation for
#[grammar(validated)]types. - Validation
- Return type of
Validate::validate— eitherbool(falserejects) orOption<&'static str>(Some(msg)rejects with a reason).
Derive Macros§
- Grammar
- Derive
Grammar(andGrammarRule) for astructorenum. - Grammar
From Other GrammarviaGrammarFrom+From<Source>.- Grammar
From Str GrammarviaGrammarFrom+FromStron the matched text.- Grammar
TryFrom Other GrammarviaGrammarFrom+TryFrom<Source>.