#[macro_export]
macro_rules! parse {
( $($t:tt)* ) => { __parse_internal!{ $($t)* } };
}
#[macro_export]
#[doc(hidden)]
macro_rules! __parse_internal_or {
($input:expr, $lhs:expr, $rhs:expr) => {
$crate::combinators::or($input, $lhs, $rhs)
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! __parse_internal {
( @BIND(($input:expr ; _) $($exp:tt)+) ) => { __parse_internal!{@EXPR($input;) $($exp)* } };
( @BIND(($input:expr ; _) $($exp:tt)+) $($tail:tt)+ ) => { (__parse_internal!{@EXPR($input;) $($exp)* }).bind(|i, _| __parse_internal!{i; $($tail)* }) };
( @BIND(($input:expr ; $name:pat) $($exp:tt)+) $($tail:tt)+ ) => { (__parse_internal!{@EXPR($input;) $($exp)* }).bind(|i, $name| __parse_internal!{i; $($tail)* }) };
( @BIND(($input:expr ; $name:ident : $name_ty:ty) $($exp:tt)+) $($tail:tt)+ ) => { (__parse_internal!{@EXPR($input;) $($exp)* }).bind(|i, $name : $name_ty| __parse_internal!{i; $($tail)* }) };
( @TERM($input:expr) ret @ $t_ty:ty , $e_ty:ty : $e:expr ) => { $input.ret::<$t_ty, $e_ty>($e) };
( @TERM($input:expr) ret $e:expr ) => { $input.ret($e) };
( @TERM($input:expr) err @ $t_ty:ty , $e_ty:ty : $e:expr ) => { $input.err::<$t_ty, $e_ty>($e) };
( @TERM($input:expr) err $e:expr ) => { $input.err($e) };
( @TERM($input:expr) ( $($inner:tt)* ) ) => { __parse_internal!{@EXPR($input;) $($inner)*} };
( @TERM($input:expr) $state:ident -> $e:expr ) => { { let $state = $input; $e } };
( @TERM($input:expr) $func:ident ( $($param:expr),* $(,)*) ) => { $func($input, $($param),*) };
( @EXPR($input:expr; $($lhs:tt)*) ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)*} };
( @EXPR($input:expr; $($lhs:tt)*) >> $($tail:tt)* ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)*}.bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) };
( @EXPR($input:expr; $($lhs:tt)*) $t1:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1} };
( @EXPR($input:expr; $($lhs:tt)*) $t1:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1}).bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) };
( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2} };
( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2}).bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) };
( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3} };
( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3}).bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) };
( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4} };
( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4}).bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) };
( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5} };
( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5}).bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) };
( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6} };
( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6}).bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) };
( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7} };
( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7}).bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) };
( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $($tail:tt)* ) => { __parse_internal!{@EXPR($input; $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8) $($tail)*} };
( @EXPR_ALT($input:expr; $($lhs:tt)*) ) => { __parse_internal!{@EXPR_SKIP($input;) $($lhs)*} };
( @EXPR_ALT($input:expr; $($lhs:tt)*) <|> $($tail:tt)* ) => { __parse_internal_or!{$input, |i| __parse_internal!{@EXPR_SKIP(i;) $($lhs)*}, |i| __parse_internal!{@EXPR_ALT(i;) $($tail)*}} };
( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt ) => { __parse_internal!{@EXPR_SKIP($input;) $($lhs)* $t1} };
( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt <|> $($tail:tt)* ) => { __parse_internal_or!{$input, |i| __parse_internal!{@EXPR_SKIP(i;) $($lhs)* $t1}, |i| __parse_internal!{@EXPR_ALT(i;) $($tail)*}} };
( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt ) => { __parse_internal!{@EXPR_SKIP($input;) $($lhs)* $t1 $t2} };
( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt <|> $($tail:tt)* ) => { __parse_internal_or!{$input, |i| __parse_internal!{@EXPR_SKIP(i;) $($lhs)* $t1 $t2}, |i| __parse_internal!{@EXPR_ALT(i;) $($tail)*}} };
( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt ) => { __parse_internal!{@EXPR_SKIP($input;) $($lhs)* $t1 $t2 $t3} };
( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt <|> $($tail:tt)* ) => { __parse_internal_or!{$input, |i| __parse_internal!{@EXPR_SKIP(i;) $($lhs)* $t1 $t2 $t3}, |i| __parse_internal!{@EXPR_ALT(i;) $($tail)*}} };
( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt ) => { __parse_internal!{@EXPR_SKIP($input;) $($lhs)* $t1 $t2 $t3 $t4} };
( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt <|> $($tail:tt)* ) => { __parse_internal_or!{$input, |i| __parse_internal!{@EXPR_SKIP(i;) $($lhs)* $t1 $t2 $t3 $t4}, |i| __parse_internal!{@EXPR_ALT(i;) $($tail)*}} };
( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt ) => { __parse_internal!{@EXPR_SKIP($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5} };
( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt <|> $($tail:tt)* ) => { __parse_internal_or!{$input, |i| __parse_internal!{@EXPR_SKIP(i;) $($lhs)* $t1 $t2 $t3 $t4 $t5}, |i| __parse_internal!{@EXPR_ALT(i;) $($tail)*}} };
( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt ) => { __parse_internal!{@EXPR_SKIP($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6} };
( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt <|> $($tail:tt)* ) => { __parse_internal_or!{$input, |i| __parse_internal!{@EXPR_SKIP(i;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6}, |i| __parse_internal!{@EXPR_ALT(i;) $($tail)*}} };
( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt ) => { __parse_internal!{@EXPR_SKIP($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7} };
( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt <|> $($tail:tt)* ) => { __parse_internal_or!{$input, |i| __parse_internal!{@EXPR_SKIP(i;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7}, |i| __parse_internal!{@EXPR_ALT(i;) $($tail)*}} };
( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $($tail:tt)* ) => { __parse_internal!{@EXPR_ALT($input; $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8) $($tail)*} };
( @EXPR_SKIP($input:expr; $($lhs:tt)*) ) => { __parse_internal!{@TERM($input) $($lhs)*} };
( @EXPR_SKIP($input:expr; $($lhs:tt)*) <* $($tail:tt)* ) => { __parse_internal!{@TERM($input) $($lhs)*}.bind(|i, l| __parse_internal!{@EXPR_SKIP(i;) $($tail)*}.map(|_| l)) };
( @EXPR_SKIP($input:expr; $($lhs:tt)*) $t1:tt ) => { __parse_internal!{@TERM($input) $($lhs)* $t1} };
( @EXPR_SKIP($input:expr; $($lhs:tt)*) $t1:tt <* $($tail:tt)* ) => { __parse_internal!{@TERM($input) $($lhs)* $t1}.bind(|i, l| __parse_internal!{@EXPR_SKIP(i;) $($tail)*}.map(|_| l)) };
( @EXPR_SKIP($input:expr; $($lhs:tt)*) $t1:tt $t2:tt ) => { __parse_internal!{@TERM($input) $($lhs)* $t1 $t2} };
( @EXPR_SKIP($input:expr; $($lhs:tt)*) $t1:tt $t2:tt <* $($tail:tt)* ) => { __parse_internal!{@TERM($input) $($lhs)* $t1 $t2}.bind(|i, l| __parse_internal!{@EXPR_SKIP(i;) $($tail)*}.map(|_| l)) };
( @EXPR_SKIP($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt ) => { __parse_internal!{@TERM($input) $($lhs)* $t1 $t2 $t3} };
( @EXPR_SKIP($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt <* $($tail:tt)* ) => { __parse_internal!{@TERM($input) $($lhs)* $t1 $t2 $t3}.bind(|i, l| __parse_internal!{@EXPR_SKIP(i;) $($tail)*}.map(|_| l)) };
( @EXPR_SKIP($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt ) => { __parse_internal!{@TERM($input) $($lhs)* $t1 $t2 $t3 $t4} };
( @EXPR_SKIP($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt <* $($tail:tt)* ) => { __parse_internal!{@TERM($input) $($lhs)* $t1 $t2 $t3 $t4}.bind(|i, l| __parse_internal!{@EXPR_SKIP(i;) $($tail)*}.map(|_| l)) };
( @EXPR_SKIP($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $($tail:tt)* ) => { __parse_internal!{@EXPR_SKIP($input; $($lhs)* $t1 $t2 $t3 $t4 $t5) $($tail)*} };
( @STATEMENT($args:tt $($data:tt)*) ) => { __parse_internal!{@BIND($args $($data)*)} };
( @STATEMENT($args:tt $($data:tt)*) ; $($tail:tt)*) => { __parse_internal!{@BIND($args $($data)*) $($tail)*} };
( @STATEMENT($args:tt $($data:tt)*) $t1:tt ) => { __parse_internal!{@BIND($args $($data)* $t1)} };
( @STATEMENT($args:tt $($data:tt)*) $t1:tt ; $($tail:tt)* ) => { __parse_internal!{@BIND($args $($data)* $t1) $($tail)*} };
( @STATEMENT($args:tt $($data:tt)*) $t1:tt $t2:tt ) => { __parse_internal!{@BIND($args $($data)* $t1 $t2)} };
( @STATEMENT($args:tt $($data:tt)*) $t1:tt $t2:tt ; $($tail:tt)* ) => { __parse_internal!{@BIND($args $($data)* $t1 $t2) $($tail)*} };
( @STATEMENT($args:tt $($data:tt)*) $t1:tt $t2:tt $t3:tt ) => { __parse_internal!{@BIND($args $($data)* $t1 $t2 $t3)} };
( @STATEMENT($args:tt $($data:tt)*) $t1:tt $t2:tt $t3:tt ; $($tail:tt)* ) => { __parse_internal!{@BIND($args $($data)* $t1 $t2 $t3) $($tail)*} };
( @STATEMENT($args:tt $($data:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt ) => { __parse_internal!{@BIND($args $($data)* $t1 $t2 $t3 $t4)} };
( @STATEMENT($args:tt $($data:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt ; $($tail:tt)* ) => { __parse_internal!{@BIND($args $($data)* $t1 $t2 $t3 $t4) $($tail)*} };
( @STATEMENT($args:tt $($data:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt ) => { __parse_internal!{@BIND($args $($data)* $t1 $t2 $t3 $t4 $t5)} };
( @STATEMENT($args:tt $($data:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt ; $($tail:tt)* ) => { __parse_internal!{@BIND($args $($data)* $t1 $t2 $t3 $t4 $t5) $($tail)*} };
( @STATEMENT($args:tt $($data:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt ) => { __parse_internal!{@BIND($args $($data)* $t1 $t2 $t3 $t4 $t5 $t6)} };
( @STATEMENT($args:tt $($data:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt ; $($tail:tt)* ) => { __parse_internal!{@BIND($args $($data)* $t1 $t2 $t3 $t4 $t5 $t6) $($tail)*} };
( @STATEMENT($args:tt $($data:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt ) => { __parse_internal!{@BIND($args $($data)* $t1 $t2 $t3 $t4 $t5 $t6 $t7)} };
( @STATEMENT($args:tt $($data:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt ; $($tail:tt)* ) => { __parse_internal!{@BIND($args $($data)* $t1 $t2 $t3 $t4 $t5 $t6 $t7) $($tail)*} };
( @STATEMENT($args:tt $($data:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt ) => { __parse_internal!{@BIND($args $($data)* $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8)} };
( @STATEMENT($args:tt $($data:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt ; $($tail:tt)* ) => { __parse_internal!{@BIND($args $($data)* $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8) $($tail)*} };
( @STATEMENT($args:tt $($data:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt ) => { __parse_internal!{@BIND($args $($data)* $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9)} };
( @STATEMENT($args:tt $($data:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt ; $($tail:tt)* ) => { __parse_internal!{@BIND($args $($data)* $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9) $($tail)*} };
( @STATEMENT($args:tt $($data:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt ) => { __parse_internal!{@BIND($args $($data)* $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10)} };
( @STATEMENT($args:tt $($data:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt ; $($tail:tt)* ) => { __parse_internal!{@BIND($args $($data)* $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10) $($tail)*} };
( @STATEMENT($args:tt $($data:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $($tail:tt)* ) => { __parse_internal!{@STATEMENT($args $($data)* $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11) $($tail)*} };
( $input:expr ; let $name:pat = $($tail:tt)+ ) => { __parse_internal!{@STATEMENT(($input; $name)) $($tail)+} };
( $input:expr ; let $name:ident : $name_ty:ty = $($tail:tt)+ ) => { __parse_internal!{@STATEMENT(($input; $name:$name_ty)) $($tail)+} };
( $input:expr ; $($tail:tt)+ ) => { __parse_internal!{@STATEMENT(($input; _)) $($tail)+} };
( $input:expr ) => { $input };
( $input:expr ; ) => { $input };
}
#[macro_export]
macro_rules! parser {
( $($t:tt)* ) => { |i| parse!{i; $($t)* } }
}
#[cfg(test)]
mod test {
macro_rules! __parse_internal_or {
($input:expr, $lhs:expr, $rhs:expr) => {{
let Input(i) = $input;
match ($lhs)(Input(i)) {
Data::Value(j, t) => Data::Value(j, t),
Data::Error(..) => ($rhs)(Input(i)),
}
}};
}
#[derive(Debug, Eq, PartialEq)]
struct Input(i64);
#[derive(Debug, Eq, PartialEq)]
enum Data<T, E> {
Value(i64, T),
Error(i64, E),
}
impl Input {
fn ret<T, E>(self, t: T) -> Data<T, E> {
Data::Value(self.0, t)
}
fn err<T, E>(self, e: E) -> Data<T, E> {
Data::Error(self.0, e)
}
}
impl<T, E> Data<T, E> {
fn bind<F, U, V>(self, f: F) -> Data<U, V>
where
F: FnOnce(Input, T) -> Data<U, V>,
V: From<E>,
{
match self {
Data::Value(i, t) => match f(Input(i), t) {
Data::Value(i, t) => Data::Value(i, t),
Data::Error(i, e) => Data::Error(i, e),
},
Data::Error(i, e) => Data::Error(i, From::from(e)),
}
}
fn map<F, U>(self, f: F) -> Data<U, E>
where
F: FnOnce(T) -> U,
{
match self {
Data::Value(i, t) => Data::Value(i, f(t)),
Data::Error(i, e) => Data::Error(i, e),
}
}
}
#[test]
fn empty() {
let i = 123;
let r = parse! {i};
assert_eq!(r, 123);
}
#[test]
fn empty_expr() {
let r = parse! {1 + 2};
assert_eq!(r, 3);
}
#[test]
fn ret() {
let i = Input(123);
let r: Data<_, ()> = parse! {i; ret "foo"};
assert_eq!(r, Data::Value(123, "foo"));
}
#[test]
fn ret_typed() {
let i = Input(123);
let r = parse! {i; ret @ _, (): "foo"};
assert_eq!(r, Data::Value(123, "foo"));
}
#[test]
fn ret_typed2() {
let i = Input(123);
let r = parse! {i; ret @ &str, (): "foo"};
assert_eq!(r, Data::Value(123, "foo"));
}
#[test]
fn err() {
let i = Input(123);
let r: Data<(), _> = parse! {i; err "foo"};
assert_eq!(r, Data::Error(123, "foo"));
}
#[test]
fn err_typed() {
let i = Input(123);
let r = parse! {i; err @(), _: "foo"};
assert_eq!(r, Data::Error(123, "foo"));
}
#[test]
fn err_typed2() {
let i = Input(123);
let r = parse! {i; err @(), &str: "foo"};
assert_eq!(r, Data::Error(123, "foo"));
}
#[test]
fn action() {
fn doit(i: Input) -> Data<&'static str, ()> {
Data::Value(i.0, "doit")
}
let i = Input(123);
let r = parse!(i; doit());
assert_eq!(r, Data::Value(123, "doit"));
}
#[test]
fn action2() {
fn doit(i: Input, p: &str) -> Data<&str, ()> {
Data::Value(i.0, p)
}
let i = Input(123);
let r = parse!(i; doit("doit"));
assert_eq!(r, Data::Value(123, "doit"));
}
#[test]
fn action3() {
fn doit(i: Input, p: &str, u: u32) -> Data<(&str, u32), ()> {
Data::Value(i.0, (p, u))
}
let i = Input(123);
let r = parse!(i; doit("doit", 1337));
assert_eq!(r, Data::Value(123, ("doit", 1337)));
}
#[test]
fn two_actions() {
fn doit(i: Input) -> Data<u32, ()> {
assert_eq!(i.0, 123);
Data::Value(321, 1)
}
fn something(i: Input) -> Data<u32, ()> {
assert_eq!(i.0, 321);
Data::Value(123, 2)
}
let i = Input(123);
let r = parse!(i; doit(); something());
assert_eq!(r, Data::Value(123, 2));
}
#[test]
fn two_actions2() {
fn doit(i: Input, n: u32) -> Data<u32, ()> {
assert_eq!(i.0, 123);
Data::Value(321, n)
}
fn something(i: Input, n: u32) -> Data<u32, ()> {
assert_eq!(i.0, 321);
Data::Value(123, n)
}
let i = Input(123);
let r = parse!(i; doit(22); something(33));
assert_eq!(r, Data::Value(123, 33));
}
#[test]
fn two_actions3() {
fn doit(i: Input, n: u32, x: i32) -> Data<(u32, i32), ()> {
assert_eq!(i.0, 123);
Data::Value(321, (n, x))
}
fn something(i: Input, n: u32, x: i32) -> Data<(u32, i32), ()> {
assert_eq!(i.0, 321);
Data::Value(123, (n, x))
}
let i = Input(123);
let r = parse!(i; doit(22, 1); something(33, 2));
assert_eq!(r, Data::Value(123, (33, 2)));
}
#[test]
fn action_ret() {
fn doit(i: Input, x: i32) -> Data<i32, ()> {
assert_eq!(i.0, 123);
Data::Value(321, x)
}
let i1 = Input(123);
let i2 = Input(123);
let r1: Data<_, ()> = parse!(i1; doit(2); ret 5);
let r2 = parse!(i2; doit(2); ret @ _, (): 5);
assert_eq!(r1, Data::Value(321, 5));
assert_eq!(r2, Data::Value(321, 5));
}
#[test]
fn action_ret2() {
fn doit(i: Input, x: i32) -> Data<i32, ()> {
assert_eq!(i.0, 123);
Data::Value(321, x)
}
fn something(i: Input, n: u32, x: i32) -> Data<(u32, i32), ()> {
assert_eq!(i.0, 321);
Data::Value(111, (n, x))
}
let i1 = Input(123);
let i2 = Input(123);
let r1: Data<_, ()> = parse! {i1; doit(2); something(4, 5); ret 5};
let r2 = parse! {i2; doit(2); something(4, 5); ret @ _, (): 5};
assert_eq!(r1, Data::Value(111, 5));
assert_eq!(r2, Data::Value(111, 5));
}
#[test]
fn bind() {
fn doit(i: Input, x: i32) -> Data<i32, ()> {
assert_eq!(i.0, 123);
Data::Value(321, x)
}
let i1 = Input(123);
let i2 = Input(123);
let r1: Data<_, ()> = parse! {i1; let n = doit(40); ret n + 2};
let r2 = parse! {i2; let n = doit(40); ret @ _, (): n + 2};
assert_eq!(r1, Data::Value(321, 42));
assert_eq!(r2, Data::Value(321, 42));
}
#[test]
fn bind2() {
fn doit(i: Input, x: i32) -> Data<i32, ()> {
assert_eq!(i.0, 123);
Data::Value(321, x)
}
fn something(i: Input, n: i32, x: u32) -> Data<i32, ()> {
assert_eq!(i.0, 321);
Data::Value(111, n - x as i32)
}
let i1 = Input(123);
let i2 = Input(123);
let r1: Data<_, ()> = parse! {i1; let n = doit(40); let x = something(n, 4); ret x + 6};
let r2 = parse! {i2; let n = doit(40); let x = something(n, 4);
ret @ _, (): x + 6};
assert_eq!(r1, Data::Value(111, 42));
assert_eq!(r2, Data::Value(111, 42));
}
#[test]
fn bind3() {
fn doit(i: Input, x: i32) -> Data<i32, u8> {
assert_eq!(i.0, 123);
Data::Value(321, x)
}
let i1 = Input(123);
let i2 = Input(123);
let r1: Data<(), u8> = parse! {i1; let n = doit(40); err n as u8 + 2};
let r2 = parse! {i2; let n = doit(40); err @ (), u8: n as u8 + 2};
assert_eq!(r1, Data::Error(321, 42));
assert_eq!(r2, Data::Error(321, 42));
}
#[test]
fn bind4() {
fn doit(i: Input, x: i32) -> Data<i32, u8> {
assert_eq!(i.0, 123);
Data::Value(321, x)
}
fn something(i: Input, n: i32, x: u32) -> Data<i32, u8> {
assert_eq!(i.0, 321);
Data::Value(111, n - x as i32)
}
let i1 = Input(123);
let i2 = Input(123);
let r1: Data<(), u8> =
parse! {i1; let n = doit(40); let x = something(n, 4); err x as u8 + 6};
let r2 = parse! {i2; let n = doit(40); let x = something(n, 4);
err @ (), u8: x as u8 + 6};
assert_eq!(r1, Data::Error(111, 42));
assert_eq!(r2, Data::Error(111, 42));
}
#[test]
fn bind_then() {
fn doit(i: Input, x: i32) -> Data<i32, ()> {
assert_eq!(i.0, 111);
Data::Value(321, x)
}
fn something(i: Input, n: i32, x: u32) -> Data<i32, ()> {
assert_eq!(i.0, 123);
Data::Value(111, n - x as i32)
}
let i1 = Input(123);
let i2 = Input(123);
let r1: Data<_, ()> = parse! {i1; let x = something(6, 4); doit(x)};
let r2 = parse! {i2; let x = something(6, 4); doit(x)};
assert_eq!(r1, Data::Value(321, 2));
assert_eq!(r2, Data::Value(321, 2));
}
#[test]
fn bind_then2() {
fn doit(i: Input, x: i32) -> Data<i32, ()> {
assert_eq!(i.0, 111);
Data::Value(321, x)
}
fn something(i: Input, n: i32, x: u32) -> Data<i32, ()> {
assert_eq!(i.0, 123);
Data::Value(111, n - x as i32)
}
let i1 = Input(123);
let i2 = Input(123);
let r1: Data<_, ()> = parse! {i1; let _x = something(6, 4); doit(3)};
let r2 = parse! {i2; let _x = something(6, 4); doit(3)};
assert_eq!(r1, Data::Value(321, 3));
assert_eq!(r2, Data::Value(321, 3));
}
#[test]
fn bind_type() {
fn doit<N>(i: Input, x: N) -> Data<N, ()> {
assert_eq!(i.0, 123);
Data::Value(321, x)
}
let i1 = Input(123);
let i2 = Input(123);
let r1: Data<_, ()> = parse! {i1; let n: u64 = doit(42); ret n};
let r2 = parse! {i2; let n: u64 = doit(42); ret @ _, (): n};
assert_eq!(r1, Data::Value(321, 42u64));
assert_eq!(r2, Data::Value(321, 42u64));
}
#[test]
fn bind_pattern() {
fn something(i: Input, n: u32, x: u32) -> Data<(u32, u32), ()> {
assert_eq!(i.0, 123);
Data::Value(111, (n, x))
}
let i1 = Input(123);
let i2 = Input(123);
let r1: Data<_, ()> = parse! {i1; let (x, y) = something(2, 4); ret x + y};
let r2 = parse! {i2; let (x, y) = something(2, 4); ret @ _, (): x + y};
assert_eq!(r1, Data::Value(111, 6));
assert_eq!(r2, Data::Value(111, 6));
}
#[test]
fn bind_pattern2() {
fn doit(i: Input, x: i32) -> Data<i32, ()> {
assert_eq!(i.0, 123);
Data::Value(321, x)
}
fn something(i: Input, n: i32, x: u32) -> Data<(i32, u32), ()> {
assert_eq!(i.0, 321);
Data::Value(111, (n, x))
}
let i1 = Input(123);
let i2 = Input(123);
let r1: Data<_, ()> = parse! {i1; let n = doit(40); let (x, y) = something(n, 4);
ret x + y as i32};
let r2 = parse! {i2; let n = doit(40); let (x, y) = something(n, 4);
ret @ _, (): x + y as i32};
assert_eq!(r1, Data::Value(111, 44));
assert_eq!(r2, Data::Value(111, 44));
}
#[test]
fn action_err() {
fn doit(i: Input, x: i32) -> Data<i32, u8> {
assert_eq!(i.0, 123);
Data::Value(321, x)
}
let i1 = Input(123);
let i2 = Input(123);
let r1: Data<(), u8> = parse!(i1; doit(2); err 5);
let r2 = parse!(i2; doit(2); err @ (), u8: 5);
assert_eq!(r1, Data::Error(321, 5));
assert_eq!(r2, Data::Error(321, 5));
}
#[test]
fn action_err2() {
fn doit(i: Input, x: i32) -> Data<i32, u8> {
assert_eq!(i.0, 123);
Data::Value(321, x)
}
fn something(i: Input, n: u32, x: i32) -> Data<(u32, i32), u8> {
assert_eq!(i.0, 321);
Data::Value(111, (n, x))
}
let i1 = Input(123);
let i2 = Input(123);
let r1: Data<(), u8> = parse! {i1; doit(2); something(4, 5); err 5};
let r2 = parse! {i2; doit(2); something(4, 5); err @ (), u8: 5};
assert_eq!(r1, Data::Error(111, 5));
assert_eq!(r2, Data::Error(111, 5));
}
#[test]
fn inline_action() {
let i = Input(123);
let r = parse! {i;
s -> {
assert_eq!(s, Input(123));
s.ret::<_, ()>(23)
}
};
assert_eq!(r, Data::Value(123, 23));
}
#[test]
fn inline_action2() {
fn doit(i: Input) -> Data<u32, ()> {
assert_eq!(i, Input(123));
Data::Value(321, 2)
}
let i = Input(123);
let r = parse! {i;
doit();
s -> {
assert_eq!(s, Input(321));
s.ret::<_, ()>(23)
}
};
assert_eq!(r, Data::Value(321, 23));
}
#[test]
fn inline_action3() {
let i = Input(123);
let r = parse! {i;
s -> s.ret::<u8, ()>(23)
};
assert_eq!(r, Data::Value(123, 23));
}
#[test]
fn inline_action_bind() {
let i = Input(123);
let r = parse! {i;
let v = s -> {
assert_eq!(s, Input(123));
s.ret(23)
};
ret @ u32, (): v + 2
};
assert_eq!(r, Data::Value(123, 25));
}
#[test]
fn inline_action_bind2() {
fn doit(i: Input) -> Data<u32, ()> {
assert_eq!(i, Input(123));
Data::Value(321, 2)
}
let i = Input(123);
let r = parse! {i;
let n = doit();
let v = s -> {
assert_eq!(n, 2);
assert_eq!(s, Input(321));
s.ret(23 + n)
};
ret @ u32, (): v + 3
};
assert_eq!(r, Data::Value(321, 28));
}
#[test]
fn expr_ret() {
let i1 = Input(123);
let i2 = Input(123);
let r1: Data<_, ()> = parse! {i1; let a = ret "test"; ret a};
let r2: Data<_, ()> = parse! {i2; ret "throwaway"; ret "foo"};
assert_eq!(r1, Data::Value(123, "test"));
assert_eq!(r2, Data::Value(123, "foo"));
}
#[test]
fn expr_err() {
let i1 = Input(123);
let i2 = Input(123);
let r1: Data<&str, &str> = parse! {i1; let a = err "error"; ret a};
let r2: Data<(), &str> = parse! {i2; err @ (), _: "this"; err "not this"};
assert_eq!(r1, Data::Error(123, "error"));
assert_eq!(r2, Data::Error(123, "this"));
}
#[test]
fn alt() {
fn fail(i: Input) -> Data<u32, ()> {
assert_eq!(i, Input(123));
Data::Error(456, ())
}
fn doit(i: Input) -> Data<u32, ()> {
assert_eq!(i, Input(123));
Data::Value(321, 2)
}
let i1 = Input(123);
let i2 = Input(123);
let i3 = Input(123);
let i4 = Input(123);
let r1 = parse! {i1; fail() <|> doit() };
let r2 = parse! {i2; doit() <|> fail() };
let r3 = parse! {i3; doit() <|> doit() };
let r4 = parse! {i4; fail() <|> fail() };
assert_eq!(r1, Data::Value(321, 2));
assert_eq!(r2, Data::Value(321, 2));
assert_eq!(r3, Data::Value(321, 2));
assert_eq!(r4, Data::Error(456, ()));
}
#[test]
fn alt2() {
fn fail(i: Input) -> Data<u32, ()> {
assert_eq!(i, Input(123));
Data::Error(456, ())
}
fn doit(i: Input) -> Data<u32, ()> {
assert_eq!(i, Input(123));
Data::Value(321, 2)
}
let i = Input(123);
let r1 = parse! {i; fail() <|> fail() <|> doit() };
assert_eq!(r1, Data::Value(321, 2));
}
#[test]
fn chain_alt() {
fn fail(i: Input) -> Data<u32, ()> {
assert_eq!(i, Input(123));
Data::Error(456, ())
}
fn doit(i: Input) -> Data<u32, ()> {
assert_eq!(i, Input(123));
Data::Value(321, 2)
}
fn next(i: Input) -> Data<u32, ()> {
assert_eq!(i, Input(321));
Data::Value(322, 42)
}
let i1 = Input(123);
let i2 = Input(123);
let i3 = Input(123);
let r1 = parse! {i1; fail() <|> doit(); next() };
let r2 = parse! {i2; doit() <|> fail(); next() };
let r3 = parse! {i3; fail() <|> fail(); next() };
assert_eq!(r1, Data::Value(322, 42));
assert_eq!(r2, Data::Value(322, 42));
assert_eq!(r3, Data::Error(456, ()));
}
#[test]
fn precedence_skip_then() {
fn a(i: Input) -> Data<u32, ()> {
assert_eq!(i, Input(123));
Data::Value(321, 2)
}
fn b(i: Input) -> Data<u32, ()> {
assert_eq!(i, Input(321));
Data::Value(322, 42)
}
fn c(i: Input) -> Data<u32, ()> {
assert_eq!(i, Input(322));
Data::Value(323, 43)
}
let i1 = Input(123);
let i2 = Input(123);
let i3 = Input(123);
let i4 = Input(123);
let i5 = Input(123);
let i6 = Input(123);
let i7 = Input(123);
let i_8 = Input(123);
let i9 = Input(123);
let i10 = Input(123);
let i11 = Input(123);
let i12 = Input(123);
let r1 = parse! {i1; a() <* b() <* c()};
let r2 = parse! {i2; a() <* b() >> c()};
let r3 = parse! {i3; a() >> b() <* c()};
let r4 = parse! {i4; a() >> b() >> c()};
let r5 = parse! {i5; (a() <* b()) <* c()};
let r6 = parse! {i6; a() <* (b() <* c())};
let r7 = parse! {i7; (a() <* b()) >> c()};
let r8 = parse! {i_8; a() <* (b() >> c())};
let r9 = parse! {i9; (a() >> b()) <* c()};
let r10 = parse! {i10; a() >> (b() <* c())};
let r11 = parse! {i11; (a() >> b()) >> c()};
let r12 = parse! {i12; a() >> (b() >> c())};
assert_eq!(r1, Data::Value(323, 2));
assert_eq!(r2, Data::Value(323, 43));
assert_eq!(r3, Data::Value(323, 42));
assert_eq!(r4, Data::Value(323, 43));
assert_eq!(r5, Data::Value(323, 2));
assert_eq!(r6, Data::Value(323, 2));
assert_eq!(r7, Data::Value(323, 43));
assert_eq!(r8, Data::Value(323, 2));
assert_eq!(r9, Data::Value(323, 42));
assert_eq!(r10, Data::Value(323, 42));
assert_eq!(r11, Data::Value(323, 43));
assert_eq!(r12, Data::Value(323, 43));
}
#[test]
fn precedence_skip_alt() {
fn a(i: Input) -> Data<u32, ()> {
assert_eq!(i, Input(123));
Data::Value(321, 2)
}
fn b(i: Input) -> Data<u32, ()> {
assert_eq!(i, Input(321));
Data::Value(322, 42)
}
fn c(i: Input) -> Data<u32, ()> {
assert_eq!(i, Input(322));
Data::Value(323, 43)
}
fn c_a(i: Input) -> Data<u32, ()> {
assert_eq!(i, Input(321));
Data::Value(323, 43)
}
let i1 = Input(123);
let i2 = Input(123);
let i3 = Input(123);
let i4 = Input(123);
let i5 = Input(123);
let i6 = Input(123);
let i7 = Input(123);
let i_8 = Input(123);
let i9 = Input(123);
let i10 = Input(123);
let i11 = Input(123);
let i12 = Input(123);
let r1 = parse! {i1; a() <* b() <* c()};
let r2 = parse! {i2; a() <* b() <|> c()};
let r3 = parse! {i3; a() <|> b() <* c()};
let r4 = parse! {i4; a() <|> b() <|> c()};
let r5 = parse! {i5; (a() <* b()) <* c()};
let r6 = parse! {i6; (a() <* b()) <|> c()};
let r7 = parse! {i7; (a() <|> b()) <* c_a()};
let r8 = parse! {i_8; (a() <|> b()) <|> c()};
let r9 = parse! {i9; a() <* (b() <* c())};
let r10 = parse! {i10; a() <* (b() <|> c())};
let r11 = parse! {i11; a() <|> (b() <* c())};
let r12 = parse! {i12; a() <|> (b() <|> c())};
assert_eq!(r1, Data::Value(323, 2));
assert_eq!(r2, Data::Value(322, 2));
assert_eq!(r3, Data::Value(321, 2));
assert_eq!(r4, Data::Value(321, 2));
assert_eq!(r5, Data::Value(323, 2));
assert_eq!(r6, Data::Value(322, 2));
assert_eq!(r7, Data::Value(323, 2));
assert_eq!(r8, Data::Value(321, 2));
assert_eq!(r9, Data::Value(323, 2));
assert_eq!(r10, Data::Value(322, 2));
assert_eq!(r11, Data::Value(321, 2));
assert_eq!(r12, Data::Value(321, 2));
}
#[test]
fn precedence_alt_then() {
fn a(i: Input) -> Data<u32, ()> {
assert_eq!(i, Input(123));
Data::Value(321, 2)
}
fn b(i: Input) -> Data<u32, ()> {
assert_eq!(i, Input(321));
Data::Value(322, 42)
}
fn c(i: Input) -> Data<u32, ()> {
assert_eq!(i, Input(322));
Data::Value(323, 43)
}
fn c_a(i: Input) -> Data<u32, ()> {
assert_eq!(i, Input(321));
Data::Value(323, 43)
}
let i1 = Input(123);
let i2 = Input(123);
let i3 = Input(123);
let i4 = Input(123);
let i5 = Input(123);
let i6 = Input(123);
let i7 = Input(123);
let i_8 = Input(123);
let i9 = Input(123);
let i10 = Input(123);
let i11 = Input(123);
let i12 = Input(123);
let r1 = parse! {i1; a() <|> b() <|> c()};
let r2 = parse! {i2; a() <|> b() >> c_a()};
let r3 = parse! {i3; a() >> b() <|> c()};
let r4 = parse! {i4; a() >> b() >> c()};
let r5 = parse! {i5; (a() <|> b()) <|> c()};
let r6 = parse! {i6; (a() <|> b()) >> c_a()};
let r7 = parse! {i7; (a() >> b()) <|> c()};
let r8 = parse! {i_8; (a() >> b()) >> c()};
let r9 = parse! {i9; a() <|> (b() <|> c())};
let r10 = parse! {i10; a() <|> (b() >> c_a())};
let r11 = parse! {i11; a() >> (b() <|> c())};
let r12 = parse! {i12; a() >> (b() >> c())};
assert_eq!(r1, Data::Value(321, 2));
assert_eq!(r2, Data::Value(323, 43));
assert_eq!(r3, Data::Value(322, 42));
assert_eq!(r4, Data::Value(323, 43));
assert_eq!(r5, Data::Value(321, 2));
assert_eq!(r6, Data::Value(323, 43));
assert_eq!(r7, Data::Value(322, 42));
assert_eq!(r8, Data::Value(323, 43));
assert_eq!(r9, Data::Value(321, 2));
assert_eq!(r10, Data::Value(321, 2));
assert_eq!(r11, Data::Value(322, 42));
assert_eq!(r12, Data::Value(323, 43));
}
#[test]
fn alt_inline_action() {
let i = Input(123);
let r: Data<_, ()> = parse! {i;
(input -> {
assert_eq!(input, Input(123));
Data::Value::<u32, ()>(321, 21)
}) <|> (input -> {
assert_eq!(input, Input(321));
Data::Value(333, 42)
})
};
assert_eq!(r, Data::Value(321, 21));
}
#[test]
fn then_inline_action() {
let i = Input(123);
let r: Data<_, ()> = parse! {i;
(input -> {
assert_eq!(input, Input(123));
Data::Value(321, 21)
}) >> (input -> {
assert_eq!(input, Input(321));
Data::Value(333, 42)
})
};
assert_eq!(r, Data::Value(333, 42));
}
#[test]
fn skip_inline_action() {
let i = Input(123);
let r: Data<_, ()> = parse! {i;
(input -> {
assert_eq!(input, Input(123));
Data::Value(321, 21)
}) <* (input -> {
assert_eq!(input, Input(321));
Data::Value(333, 42)
})
};
assert_eq!(r, Data::Value(333, 21));
}
#[test]
fn max_alt() {
fn a(i: Input) -> Data<u32, ()> {
assert_eq!(i, Input(123));
Data::Value(321, 2)
}
let i = Input(123);
let r = parse! {i; a() <|> a() <|> a() <|> a() <|> a() <|> a() <|> a() <|> a() <|> a()};
assert_eq!(r, Data::Value(321, 2));
}
}