macro_rules! cond_reduce {
($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => { ... };
($i:expr, $cond:expr, $f:expr) => { ... };
}Expand description
Fail to parse if condition is false, otherwise parse the given parser.
This is typically used inside of option! or alt!.
- Syntax:
cond_reduce!(CONDITION, THING) - Output:
THING
extern crate syn;
#[macro_use] extern crate synom;
use syn::parse::boolean;
#[derive(Debug, PartialEq)]
struct VariadicBools {
data: Vec<bool>,
variadic: bool,
}
// Parse one or more comma-separated booleans, possibly ending in "..." to
// indicate there may be more.
named!(variadic_bools -> VariadicBools, do_parse!(
data: separated_nonempty_list!(punct!(","), boolean) >>
trailing_comma: option!(punct!(",")) >>
// Only allow "..." if there is a comma after the last boolean. Using
// `cond_reduce!` is more convenient here than using `cond!`. The
// alternatives are:
//
// - `cond!(c, option!(p))` or `option!(cond!(c, p))`
// Gives `Some(Some("..."))` for variadic and `Some(None)` or `None`
// which both mean not variadic.
// - `cond_reduce!(c, option!(p))`
// Incorrect; would fail to parse if there is no trailing comma.
// - `option!(cond_reduce!(c, p))`
// Gives `Some("...")` for variadic and `None` otherwise. Perfect!
variadic: option!(cond_reduce!(trailing_comma.is_some(), punct!("..."))) >>
(VariadicBools {
data: data,
variadic: variadic.is_some(),
})
));
fn main() {
let input = "true, true";
let parsed = variadic_bools(input).expect("variadic bools");
assert_eq!(parsed, VariadicBools {
data: vec![true, true],
variadic: false,
});
let input = "true, ...";
let parsed = variadic_bools(input).expect("variadic bools");
assert_eq!(parsed, VariadicBools {
data: vec![true],
variadic: true,
});
}