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