Macro synom::cond_reduce [] [src]

macro_rules! cond_reduce {
    ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => { ... };
    ($i:expr, $cond:expr, $f:expr) => { ... };
}

Fail to parse if condition is false, otherwise parse the given parser.

This is typically used inside of option! or alt!.

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,
    });
}