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 Tokens generated by a Parser. It generates a method process on &self that processes the whole queue of Tokens, 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'))))));