pest::process!
[−]
[src]
macro_rules! process { ( @pattern $slf:ident $index:ident ($block:expr) _ : $typ:ident ) => { ... }; ( @pattern $slf:ident $index:ident ($block:expr) _ : $typ:ident, $( $tail:tt )* ) => { ... }; ( @pattern $slf:ident $index:ident ($block:expr) _ ) => { ... }; ( @pattern $slf:ident $index:ident ($block:expr) _, $( $tail:tt )* ) => { ... }; ( @pattern $slf:ident $index:ident ($block:expr) &$head:ident : $typ:ident ) => { ... }; ( @pattern $slf:ident $index:ident ($block:expr) &$head:ident : $typ:ident, $( $tail:tt )* ) => { ... }; ( @pattern $slf:ident $index:ident ($block:expr) &$head:ident ) => { ... }; ( @pattern $slf:ident $index:ident ($block:expr) &$head:ident, $( $tail:tt )* ) => { ... }; ( @pattern $slf:ident $index:ident ($block:expr) @$head:ident ) => { ... }; ( @pattern $slf:ident $index:ident ($block:expr) @$head:ident, $( $tail:tt )* ) => { ... }; ( @pattern $slf:ident $index:ident ($block:expr) $head:ident : $typ:ident ) => { ... }; ( @pattern $slf:ident $index:ident ($block:expr) $head:ident : $typ:ident, $( $tail:tt )* ) => { ... }; ( @pattern $slf:ident $index:ident ($block:expr) $head:ident ) => { ... }; ( @pattern $slf:ident $index:ident ($block:expr) $head:ident, $( $tail:tt )* ) => { ... }; ( @branches $slf:ident $index:ident ( $( $pattern:tt )* ) => $block:expr) => { ... }; ( @branches $slf:ident $index:ident ( $( $pattern:tt )* ) => $block:expr,) => { ... }; ( @branches $slf:ident $index:ident ( $( $pattern:tt )* ) => $block:expr, $( $tail:tt )* ) => { ... }; ( (&$slf:ident) -> $typ:ty { $( $ts:tt )* } ) => { ... }; }
A macro
for pattern-matching queued Token
s generated by a Parser
. It generates a method
process
on &self
that processes the whole queue of Token
s, reducing it to one single
result. The type of this result is specified at the beginning of the definition.
The process
is populated with patterns and the way a pattern shall be dealt with. A pattern
is constructed from the following comma-separated items:
Item | What it does |
---|---|
item |
matches any Token |
item: R |
matches a Token of rule R |
&item |
captures a Token |
&item: R |
captures a Token of rule R |
_ |
skips a Token |
_: R |
skips a Token of rule R |
@item |
recursively process child |
Panics
In case all the patterns inside of process!
won't match, the process
method will panic!
.
impl_rdp! { grammar! { a = { ["a"] } b = { ["b"] } } process! { (&self) -> () { (_: a) => {} } } } let mut parser = Rdp::new(StringInput::new("b")); parser.b(); parser.process();
Examples
Nested letter
Let's consider the following grammar of nested letters:
expression = _{ paren | letter } // we don't need the expression Token paren = { ["("] ~ expression ~ [")"] } letter = { ['a'..'z'] }
Defining the grammar paves way to a simple data-structre (an enum
) that can be either a
Paren
or a Letter
.
#[derive(Debug, PartialEq)] pub enum Expression { Paren(Box<Expression>), Letter(char) }
The processing phase needs to handle two cases: parens and letters. Letters are straightforward captures:
(&letter: letter)
Parens need to recursively process the next item in order to be stored inside of the Paren
.
But before that, it needs to match a paren
Token
that gets ignored.
(_: paren, @expression)
All together now:
#[derive(Debug, PartialEq)] pub enum Expression { Paren(Box<Expression>), Letter(char) } impl_rdp! { grammar! { expression = _{ paren | letter } paren = { ["("] ~ expression ~ [")"] } letter = { ['a'..'z'] } } process! { (&self) -> Expression { (&letter: letter) => { Expression::Letter(letter.chars().next().unwrap()) }, (_: paren, @expression) => { Expression::Paren(Box::new(expression)) } } } } let mut parser = Rdp::new(StringInput::new("((z))")); assert!(parser.expression()); assert_eq!(parser.process(), Expression::Paren(Box::new(Expression::Paren(Box::new(Expression::Letter('z'))))));