#[macro_export]
macro_rules! grammar {
( @conv $slf:ident [ ( $( $head:tt )* ) $( $tail:tt )* ] [ $( $optail:tt )* ]
[ $( $output:tt )* ] ) => {
grammar!(@conv $slf [ $( $head )* _rp $( $tail )* ] [ _lp $( $optail )* ]
[ $( $output )* ])
};
( @conv $slf:ident [ _rp $( $tail:tt )* ] [ _lp $( $optail:tt )* ] [ $( $output:tt )* ] ) => {
grammar!(@conv $slf [ $( $tail )* ] [ $( $optail )* ] [ $( $output )* ])
};
( @conv $slf:ident [ _rp $( $tail:tt )* ] [ $op:tt $( $optail:tt )* ]
[ $( $output:tt )* ] ) => {
grammar!(@conv $slf [ _rp $( $tail )* ] [ $( $optail )* ] [ $( $output )* $op ])
};
( @conv $slf:ident [ & $head:tt $( $tail:tt )* ] [ $( $optail:tt )* ] $output:tt ) => {
grammar!(@conv $slf [ $head _pres $( $tail )* ] [ $( $optail )* ] $output)
};
( @conv $slf:ident [ ! $head:tt $( $tail:tt )* ] [ $( $optail:tt )* ] $output:tt ) => {
grammar!(@conv $slf [ $head _abs $( $tail )* ] [ $( $optail )* ] $output)
};
( @conv $slf:ident [ ~ $( $tail:tt )* ] [ ~ $( $optail:tt )* ] [ $( $output:tt )* ] ) => {
grammar!(@conv $slf [ ~ $( $tail )* ] [ $( $optail )* ] [ $( $output )* ~ ])
};
( @conv $slf:ident [ ~ $( $tail:tt )* ] [ $( $optail:tt )* ] $output:tt) => {
grammar!(@conv $slf [ $( $tail )* ] [ ~ $( $optail )* ] $output)
};
( @conv $slf:ident [ | $( $tail:tt )* ] [ ~ $( $optail:tt )* ] [ $( $output:tt )* ] ) => {
grammar!(@conv $slf [ | $( $tail )* ] [ $( $optail )* ] [ $( $output )* ~ ])
};
( @conv $slf:ident [ | $( $tail:tt )* ] [ | $( $optail:tt )* ] [ $( $output:tt )* ] ) => {
grammar!(@conv $slf [ | $( $tail )* ] [ $( $optail )* ] [ $( $output )* | ])
};
( @conv $slf:ident [ | $( $tail:tt )* ] [ $( $optail:tt )* ] $output:tt) => {
grammar!(@conv $slf [ $( $tail )* ] [ | $( $optail )* ] $output)
};
( @conv $slf:ident [ $head:tt $( $tail:tt )* ] $ops:tt [ $( $output:tt )* ] ) => {
grammar!(@conv $slf [ $( $tail )* ] $ops [ $( $output )* $head ])
};
( @conv $slf:ident [] [] [ $( $output:tt )* ] ) => {
grammar!(@process $slf [] [ $( $output )* ])
};
( @conv $slf:ident [] [ $op:tt $( $optail:tt )* ] [ $( $output:tt )* ] ) => {
grammar!(@conv $slf [] [ $( $optail )* ] [ $( $output )* $op ])
};
( @mtc $slf:ident (( $exp:expr )) ) => (($exp));
( @mtc $slf:ident [ $left:tt .. $right:tt ]) => (grammar!(@mtc $slf [$left, $right]));
( @mtc $slf:ident [ $left:expr, $right:expr ]) => ($slf.between($left, $right));
( @mtc $slf:ident [ $str:expr ]) => ($slf.matches($str));
( @mtc $slf:ident $rule:ident) => ($slf.$rule());
( @process $_slf:ident [( $result:expr )] [] ) => ($result);
( @process $slf:ident [ $b:tt $a:tt $( $tail:tt )* ] [ ~ $( $optail:tt )* ] ) => {
{
grammar!(@process $slf [(( $slf.try(false, |$slf| {
if grammar!(@mtc $slf $a) {
$slf.skip_ws();
grammar!(@mtc $slf $b)
} else {
false
}
}) )) $( $tail )* ] [ $( $optail )* ])
}
};
( @process $slf:ident [ $b:tt $a:tt $( $tail:tt )* ] [ | $( $optail:tt )* ] ) => {
{
grammar!(@process $slf [((
grammar!(@mtc $slf $a) || grammar!(@mtc $slf $b)
)) $( $tail )* ] [ $( $optail )* ])
}
};
( @process $slf:ident [ $a:tt $( $tail:tt )* ] [ * $( $optail:tt )* ] ) => {
{
grammar!(@process $slf [(( {
let mut pos = $slf.pos();
loop {
if !grammar!(@mtc $slf $a) {
$slf.set_pos(pos);
break
}
pos = $slf.pos();
$slf.skip_ws();
}
true
} )) $( $tail )* ] [ $( $optail )* ])
}
};
( @process $slf:ident [ $a:tt $( $tail:tt )* ] [ + $( $optail:tt )* ] ) => {
{
grammar!(@process $slf [(( if grammar!(@mtc $slf $a) {
loop {
let pos = $slf.pos();
$slf.skip_ws();
if !grammar!(@mtc $slf $a) {
$slf.set_pos(pos);
break
}
}
true
} else {
false
} )) $( $tail )* ] [ $( $optail )* ])
}
};
( @process $slf:ident [ $a:tt $( $tail:tt )* ] [ ? $( $optail:tt )* ] ) => {
{
grammar!(@process $slf [(( {
grammar!(@mtc $slf $a);
true
} )) $( $tail )* ] [ $( $optail )* ])
}
};
( @process $slf:ident [ $a:tt $( $tail:tt )* ] [ _pres $( $optail:tt )* ] ) => {
{
grammar!(@process $slf [(( $slf.try(true, |$slf| {
grammar!(@mtc $slf $a)
}) )) $( $tail )* ] [ $( $optail )* ])
}
};
( @process $slf:ident [ $a:tt $( $tail:tt )* ] [ _abs $( $optail:tt )* ] ) => {
{
grammar!(@process $slf [(( $slf.try(true, |$slf| {
!grammar!(@mtc $slf $a)
}) )) $( $tail )* ] [ $( $optail )* ])
}
};
( @process $slf:ident [] [ $single:tt ] ) => {
grammar!(@mtc $slf $single)
};
( @process $slf:ident [ $( $optail:tt )* ] [ $head:tt $( $tail:tt )* ] ) => {
grammar!(@process $slf [ $head $( $optail )* ] [ $( $tail )* ])
};
( @skip ws $_slf:ident ) => ();
( @skip $_name:ident $slf:ident ) => ($slf.skip_ws());
() => {
#[allow(dead_code)]
pub fn any(&mut self) -> bool {
if self.end() {
false
} else {
let next = self.pos() + 1;
self.set_pos(next);
true
}
}
#[allow(dead_code)]
pub fn eoi(&mut self) -> bool {
self.end()
}
};
( $name:ident = { $( $ts:tt )* } $( $tail:tt )* ) => {
#[allow(unused_parens)]
#[allow(unused_variables)]
pub fn $name(&mut self) -> bool {
let slf = self;
grammar!(@skip $name slf);
let pos = slf.pos();
let queue_pos = slf.queue().len();
let result = grammar!(@conv slf [ $( $ts )* ] [] []);
if result {
let new_pos = slf.pos();
slf.queue().insert(queue_pos, Rules::$name(pos, new_pos - pos));
}
result
}
grammar!($( $tail )*);
};
( $name:ident = _{ $( $ts:tt )* } $( $tail:tt )* ) => {
#[allow(unused_parens)]
#[allow(unused_variables)]
pub fn $name(&mut self) -> bool {
let slf = self;
grammar!(@skip $name slf);
let pos = slf.pos();
let result = grammar!(@conv slf [ $( $ts )* ] [] []);
result
}
grammar!($( $tail )*);
};
}