Macro pest::grammar
[−]
[src]
macro_rules! grammar { ( @assoc < $( $ts:tt )* ) => { ... }; ( @assoc $( $ts:tt )* ) => { ... }; ( @conv $atomic:tt $slf:ident [ < $( $ts:tt )* ] [] [] ) => { ... }; ( @conv_prec $pos:ident ($_prec:expr) $_atomic:tt $slf:ident [] [] [] ) => { ... }; ( @conv_prec $pos:ident ($prec:expr) $atomic:tt $slf:ident [ $name:ident = { $( $head:tt )* } $( $tail:tt )* ] [] [] ) => { ... }; ( @conv_prec $pos:ident ($prec:expr) $atomic:tt $slf:ident [ $name:ident = @{ $( $head:tt )* } $( $tail:tt )* ] [] [] ) => { ... }; ( @conv_prec $pos:ident ($prec:expr) $atomic:tt $slf:ident [ $name:ident = _{ $( $head:tt )* } $( $tail:tt )* ] [] [] ) => { ... }; ( @conv $atomic:tt $slf:ident [ { $( $primary:tt )* } $( $ts:tt )* ] [] [] ) => { ... }; ( @conv $atomic:tt $slf:ident [ ( $( $head:tt )* ) $( $tail:tt )* ] [ $( $optail:tt )* ] [ $( $output:tt )* ] ) => { ... }; ( @conv $atomic:tt $slf:ident [ _rp $( $tail:tt )* ] [ _lp $( $optail:tt )* ] [ $( $output:tt )* ] ) => { ... }; ( @conv $atomic:tt $slf:ident [ _rp $( $tail:tt )* ] [ $op:tt $( $optail:tt )* ] [ $( $output:tt )* ] ) => { ... }; ( @conv $atomic:tt $slf:ident [ & $head:tt $( $tail:tt )* ] [ $( $optail:tt )* ] $output:tt ) => { ... }; ( @conv $atomic:tt $slf:ident [ ! $head:tt $( $tail:tt )* ] [ $( $optail:tt )* ] $output:tt ) => { ... }; ( @conv $atomic:tt $slf:ident [ ~ $( $tail:tt )* ] [ ~ $( $optail:tt )* ] [ $( $output:tt )* ] ) => { ... }; ( @conv $atomic:tt $slf:ident [ ~ $( $tail:tt )* ] [ $( $optail:tt )* ] $output:tt) => { ... }; ( @conv $atomic:tt $slf:ident [ | $( $tail:tt )* ] [ ~ $( $optail:tt )* ] [ $( $output:tt )* ] ) => { ... }; ( @conv $atomic:tt $slf:ident [ | $( $tail:tt )* ] [ | $( $optail:tt )* ] [ $( $output:tt )* ] ) => { ... }; ( @conv $atomic:tt $slf:ident [ | $( $tail:tt )* ] [ $( $optail:tt )* ] $output:tt) => { ... }; ( @conv $atomic:tt $slf:ident [ $head:tt $( $tail:tt )* ] $ops:tt [ $( $output:tt )* ] ) => { ... }; ( @conv $atomic:tt $slf:ident [] [] [ $( $output:tt )* ] ) => { ... }; ( @conv $atomic:tt $slf:ident [] [ $op:tt $( $optail:tt )* ] [ $( $output:tt )* ] ) => { ... }; ( @mtc $slf:ident (( $exp:expr )) ) => { ... }; ( @mtc $slf:ident [ $left:tt .. $right:tt ]) => { ... }; ( @mtc $slf:ident [ $left:expr, $right:expr ]) => { ... }; ( @mtc $slf:ident [ $str:expr ]) => { ... }; ( @mtc $slf:ident $rule:ident) => { ... }; ( @process $_atomic:tt $_slf:ident [( $result:expr )] [] ) => { ... }; ( @process false $slf:ident [ $b:tt $a:tt $( $tail:tt )* ] [ ~ $( $optail:tt )* ] ) => { ... }; ( @process true $slf:ident [ $b:tt $a:tt $( $tail:tt )* ] [ ~ $( $optail:tt )* ] ) => { ... }; ( @process $atomic:tt $slf:ident [ $b:tt $a:tt $( $tail:tt )* ] [ | $( $optail:tt )* ] ) => { ... }; ( @process false $slf:ident [ $a:tt $( $tail:tt )* ] [ * $( $optail:tt )* ] ) => { ... }; ( @process true $slf:ident [ $a:tt $( $tail:tt )* ] [ * $( $optail:tt )* ] ) => { ... }; ( @process false $slf:ident [ $a:tt $( $tail:tt )* ] [ + $( $optail:tt )* ] ) => { ... }; ( @process true $slf:ident [ $a:tt $( $tail:tt )* ] [ + $( $optail:tt )* ] ) => { ... }; ( @process $atomic:tt $slf:ident [ $a:tt $( $tail:tt )* ] [ ? $( $optail:tt )* ] ) => { ... }; ( @process $atomic:tt $slf:ident [ $a:tt $( $tail:tt )* ] [ _pres $( $optail:tt )* ] ) => { ... }; ( @process $atomic:tt $slf:ident [ $a:tt $( $tail:tt )* ] [ _abs $( $optail:tt )* ] ) => { ... }; ( @process $_atomic:tt $slf:ident [] [ $single:tt ] ) => { ... }; ( @process $atomic:tt $slf:ident [ $( $optail:tt )* ] [ $head:tt $( $tail:tt )* ] ) => { ... }; ( @skip whitespace $_slf:ident ) => { ... }; ( @skip comment $slf:ident ) => { ... }; ( @skip $_name:ident $slf:ident ) => { ... }; ( @skip false $slf:ident ) => { ... }; ( @skip true $slf:ident ) => { ... }; ( @atomic whitespace $_atomic:tt $slf:ident $rules:tt ) => { ... }; ( @atomic comment $_atomic:tt $slf:ident $rules:tt ) => { ... }; ( @atomic $_name:ident $atomic:tt $slf:ident $rules:tt ) => { ... }; () => { ... }; ( $name:ident = { $( $ts:tt )* } $( $tail:tt )* ) => { ... }; ( $name:ident = @{ $( $ts:tt )* } $( $tail:tt )* ) => { ... }; ( $name:ident = _{ $( $ts:tt )* } $( $tail:tt )* ) => { ... }; }
A macro
that defines each rule as a method on a Parser
which parses from the current
position. Rules are always defined between braces, with an optional symbol marking the type of
rule defined.
Note: grammar!
may require you to increase the recursion limit of your create with
#![recursion_limit = "*"]
where * is the new limit.
pest has four special rules:
whitespace
- gets run between rules and sub-rulescomment
- gets run only between rulesany
- matches exactly onechar
eoi
- (end-of-input) matches only when aParser
has reached its end
whitespace
and comment
should be overridden and are void otherwise, while any
and eoi
are predefined rules.
Normal rules
A normal rule will always create a Token
and add it to the
Parser::queue
, along with any subsequent rules that its
subrules may create.
one = { two }
If the above rule matches and two
is a normal rule as well, the queue of Token
s will
contain Token { rule: Rule::one, ... }, Token { rule: Rule::two, ... }
.
Normal rules are also tracked for error reporting. Once a normal rule fails, its failure is
automatically recorded and available in Parser::expected
.
Atomic rules @
Atomic rules work as normal rules apart from the fact that they don't accept any whitespace
or comment
between rules and sub-rules, and any sub-rules of an atomic rule will not appear
in Parser::expected
.
ab = @{ a ~ b }
In the rule above, there cannot be anything between a
and b
for ab
to match. This rule
has a cascading effect, so any rules called from an atomic rule will also be atomic while
being matched in an atomic context. In other words, a
and b
will also be atomic when being
matched inside of ab
.
Silent rules _
Silent rules work like normal rules without appearing in
Parser::queue
or
Parser::expected
.
whitespace = _{ [" "] }
Unlike atomic rules, silent rules are not cascading. A rule inside a silent rule will not be silent unless it's explicitly stated.
Syntax
Rule | What it does |
---|---|
["a"] |
matches the exact string "a" |
['a'..'z'] |
matches one character between 'a' and 'z' |
a |
matches rule a |
a ~ b |
matches the sequence a b |
a | b |
matches either a or b |
a* |
matches a zero or more times |
a+ |
matches a one or more times |
a? |
optionally matches a |
&a |
matches a without making progress |
!a |
matches if a doesn't match without making progress |
Precedence climbing
pest supports a special type of rule that implements precedence climbing in the background.
expression = _{ { ["("] ~ expression ~ [")"] | number } addition = { plus | minus } multiplication = { times | slash } power = {< pow } // < for right-associativity }
The first part of the precedence climbing rule is the primary expression that comes between
braces. It's followed by any number of rules, each rule having a precedence higher than the
previous one. The <
denote right-associativity, the default being left-associativity.
Examples
impl_rdp! { grammar! { expression = _{ paren ~ expression? } paren = { ["("] ~ expression? ~ [")"] } } } let mut parser = Rdp::new(StringInput::new("(())((())())()")); assert!(parser.expression()); assert!(parser.end());