From 6f2cec695bc04b2b6d9ac83edca52158f097931a Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Fri, 3 Feb 2017 19:23:48 +0100 Subject: [PATCH] feat: Add the choice! macro This macro should give a cleaner way of writing multiple alternative parsers and may also result in faster code. --- src/combinator.rs | 31 ++++++++++++++++++++++++++++++- src/primitives.rs | 3 +++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/combinator.rs b/src/combinator.rs index 370613c2..7af0cc69 100644 --- a/src/combinator.rs +++ b/src/combinator.rs @@ -567,7 +567,7 @@ pub fn count(count: usize, parser: P) -> Count } /// Takes an array of parsers and tries to apply them each in order. -/// Fails if all parsers fails or if an applied parser consumes input before failing. +/// Fails if all the parsers fails or if an applied parser consumes input before failing. /// /// ``` /// # extern crate combine; @@ -598,6 +598,35 @@ pub fn choice(ps: S) -> Choice Choice(ps, PhantomData) } +/// Takes a number of parsers and tries to apply them each in order. +/// Fails if all the parsers fails or if an applied parser consumes input before failing. +/// +/// ``` +/// # #[macro_use] +/// # extern crate combine; +/// # use combine::*; +/// # use combine::char::{digit, letter, string}; +/// # use combine::primitives::Error; +/// # fn main() { +/// let mut parser = choice!( +/// many1(digit()), +/// string("let").map(|s| s.to_string()), +/// many1(letter())); +/// assert_eq!(parser.parse("let"), Ok(("let".to_string(), ""))); +/// assert_eq!(parser.parse("123abc"), Ok(("123".to_string(), "abc"))); +/// assert!(parser.parse(":123").is_err()); +/// # } +/// ``` +#[macro_export] +macro_rules! choice { + ($first : expr) => { + $first + }; + ($first : expr, $($rest : expr),+) => { + $first.or(choice!($($rest),+)) + } +} + #[derive(Clone)] pub struct Unexpected(Info, PhantomData I>) where I: Stream; impl Parser for Unexpected diff --git a/src/primitives.rs b/src/primitives.rs index f7679e5a..47acca32 100644 --- a/src/primitives.rs +++ b/src/primitives.rs @@ -1319,6 +1319,9 @@ pub trait Parser { /// Returns a parser which attempts to parse using `self`. If `self` fails without consuming any /// input it tries to consume the same input using `p`. /// + /// If you are looking to chain 3 or more parsers using `or` you may consider using the + /// `choice!` macro instead, which can be clearer and may result in a faster parser. + /// /// ``` /// # extern crate combine; /// # use combine::*;