Macro combine::parser [] [src]

macro_rules! parser {
    (
        $(#[$attr:meta])*
        pub fn $name: ident [$($type_params: tt)*]( $($arg: ident :  $arg_type: ty),* )
            ($input_type: ty) -> $output_type: ty
            { $($parser: tt)* }
    ) => { ... };
    (
        $(#[$attr:meta])*
        fn $name: ident [$($type_params: tt)*]( $($arg: ident :  $arg_type: ty),* )
            ($input_type: ty) -> $output_type: ty
            { $($parser: tt)* }
    ) => { ... };
    (
        $(#[$attr:meta])*
        pub fn $name: ident [$($type_params: tt)*]( $($arg: ident :  $arg_type: ty),* )
            ($input_type: ty) -> $output_type: ty
            where [$($where_clause: tt)*]
        { $($parser: tt)* }
    ) => { ... };
    (
        $(#[$attr:meta])*
        fn $name: ident [$($type_params: tt)*]( $($arg: ident :  $arg_type: ty),*) ($input_type: ty) -> $output_type: ty
            where [$($where_clause: tt)*]
        { $($parser: tt)* }
    ) => { ... };
    (
        $(#[$derive:meta])*
        pub struct $type_name: ident;
        $(#[$attr:meta])*
        pub fn $name: ident [$($type_params: tt)*]( $($arg: ident :  $arg_type: ty),* )
            ($input_type: ty) -> $output_type: ty
            where [$($where_clause: tt)*]
        { $($parser: tt)* }
    ) => { ... };
    (
        $(#[$derive:meta])*
        struct $type_name: ident;
        $(#[$attr:meta])*
        fn $name: ident [$($type_params: tt)*]( $($arg: ident :  $arg_type: ty),*) ($input_type: ty) -> $output_type: ty
            where [$($where_clause: tt)*]
        { $($parser: tt)* }
    ) => { ... };
}

Declares a named parser which can easily be reused.

The expression which creates the parser should have no side effects as it may be called multiple times even during a single parse attempt.

#[macro_use]
extern crate combine;
use combine::char::digit;
use combine::{any, choice, many1, Parser, Stream};

parser!{
    fn integer[I]()(I) -> i32
        where [I: Stream<Item = char>]
    {
        // The body must be a block body ( `{ <block body> }`) which ends with an expression
        // which evaluates to a parser
        let digits = many1(digit());
        digits.and_then(|s: String| s.parse())
    }
}

#[derive(Debug, PartialEq)]
pub enum IntOrString {
    Int(i32),
    String(String),
}
// prefix with `pub` to declare a public parser
parser!{
    // Documentation comments works as well

    /// Parses an integer or a string (any characters)
    pub fn integer_or_string[I]()(I) -> IntOrString
        where [I: Stream<Item = char>]
    {
        choice!(
            integer().map(IntOrString::Int),
            many1(any()).map(IntOrString::String)
        )
    }
}

parser!{
    // Give the created type a unique name
    #[derive(Clone)]
    pub struct Twice;
    pub fn twice[F, P](f: F)(P::Input) -> (P::Output, P::Output)
        where [P: Parser,
               F: FnMut() -> P]
    {
        (f(), f())
    }
}

fn main() {
    assert_eq!(integer().parse("123"), Ok((123, "")));
    assert!(integer().parse("!").is_err());

    assert_eq!(integer_or_string().parse("123"), Ok((IntOrString::Int(123), "")));
    assert_eq!(
        integer_or_string().parse("abc"),
        Ok((IntOrString::String("abc".to_string()), ""))
    );
    assert_eq!(twice(|| digit()).parse("123"), Ok((('1', '2'), "3")));
}