Macro combine::parser [−][src]
macro_rules! parser { (type PartialState = $partial_state : ty ; $(#[$attr : meta]) * $fn_vis : vis fn $name : ident [$($type_params : tt) *] ($($arg : ident : $arg_type : ty), *) ($input_type : ty) -> $output_type : ty where [$($where_clause : tt) *] $parser : block) => { ... }; ($(#[$derive : meta]) * $struct_vis : vis struct $type_name : ident ; type PartialState = $partial_state : ty ; $(#[$attr : meta]) * $fn_vis : vis fn $name : ident [$($type_params : tt) *] ($($arg : ident : $arg_type : ty), *) ($input_type : ty) -> $output_type : ty where [$($where_clause : tt) *] $parser : block) => { ... }; ($(#[$attr : meta]) * $fn_vis : vis fn $name : ident [$($type_params : tt) *] ($($arg : ident : $arg_type : ty), *) ($input_type : ty) -> $output_type : ty where [$($where_clause : tt) *] $parser : block) => { ... }; ($(#[$derive : meta]) * $struct_vis : vis struct $type_name : ident ; $(#[$attr : meta]) * $fn_vis : vis fn $name : ident [$($type_params : tt) *] ($($arg : ident : $arg_type : ty), *) ($input_type : ty) -> $output_type : ty where [$($where_clause : tt) *] $parser : block) => { ... }; }
Expand description
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.
NOTE: If you are using rust nightly you can use impl Trait
instead. See the json parser for
an example.
#[macro_use] extern crate combine; use combine::parser::char::digit; use combine::{any, choice, from_str, many1, Parser, EasyParser, Stream}; use combine::error::ParseError; parser!{ /// `[Input]` represents a normal type parameters and lifetime declaration for the function /// It gets expanded to `<Input>` fn integer[Input]()(Input) -> i32 where [ Input: Stream<Token = char>, Input::Error: ParseError<char, Input::Range, Input::Position>, <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError: From<::std::num::ParseIntError>, ] { // The body must be a block body ( `{ <block body> }`) which ends with an expression // which evaluates to a parser from_str(many1::<String, _, _>(digit())) } } #[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[Input]()(Input) -> IntOrString where [ Input: Stream<Token = char>, Input::Error: ParseError<char, Input::Range, Input::Position>, <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError: From<::std::num::ParseIntError>, ] { 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[Input, F, P](f: F)(Input) -> (P::Output, P::Output) where [P: Parser<Input>, F: FnMut() -> P] { (f(), f()) } } fn main() { assert_eq!(integer().easy_parse("123"), Ok((123, ""))); assert!(integer().easy_parse("!").is_err()); assert_eq!( integer_or_string().easy_parse("123"), Ok((IntOrString::Int(123), "")) ); assert_eq!( integer_or_string().easy_parse("abc"), Ok((IntOrString::String("abc".to_string()), "")) ); assert_eq!(twice(|| digit()).parse("123"), Ok((('1', '2'), "3"))); }