From 8002b83a865cdb665c215d9b0d4df3fe30cb6c07 Mon Sep 17 00:00:00 2001 From: Greg Shuflin Date: Sun, 16 Oct 2022 01:29:48 -0700 Subject: [PATCH] choice combinator --- src/lib.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index b523613..9e55347 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,17 @@ trait Parser { BoxedParser::new(map(self, map_fn)) } + fn to<'a, O2>(self, item: O2) -> BoxedParser<'a, I, O2, E> + where + Self: Sized + 'a, + I: 'a, + O: 'a, + O2: Clone + 'a, + E: 'a, + { + self.map(move |_| item.clone()) + } + fn then<'a, P, O2>(self, next_parser: P) -> BoxedParser<'a, I, (O, O2), E> where Self: Sized + 'a, @@ -182,6 +193,18 @@ fn any_char(input: &str) -> ParseResult<&str, char, &str> { } } +fn choice(parser1: P1, parser2: P2) -> impl Parser +where + P1: Parser, + P2: Parser, + I: Copy, +{ + move |input| match parser1.parse(input) { + ok @ Ok(..) => ok, + Err(_e) => parser2.parse(input), + } +} + #[cfg(test)] mod tests { use super::*; @@ -229,4 +252,10 @@ mod tests { let p = pred(any_char, |c| *c == 'f'); assert_eq!(p.parse("frog"), Ok(('f', "rog"))); } + + #[test] + fn test_choice() { + let p = choice(literal("gnostika").to(1), one_or_more(literal(" ")).to(2)); + assert_eq!(p.parse("gnostika twentynine"), Ok((1, " twentynine"))); + } }