use crate::parser::{ParseResult, Parser}; pub fn choice2(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), } } pub fn choice(choices: C) -> impl Parser where C: Choice, I: Clone, { move |input| choices.parse(input) } pub trait Choice { fn parse(&self, input: I) -> ParseResult; } impl Choice for (P1, P2) where P1: Parser, P2: Parser, I: Clone, { fn parse(&self, input: I) -> ParseResult { let parser1 = &self.0; let parser2 = &self.1; //TODO need a more principled way to return an error when no choices work let mut err = None; for parser in [parser1 as &dyn Parser, parser2].iter() { match parser.parse(input.clone()) { Ok(result) => return Ok(result), Err(e) => { err = Some(e); } } } Err(err.unwrap()) } } #[cfg(test)] mod tests { use super::*; use crate::combinators::one_or_more; use crate::primitives::literal; #[test] fn test_choice() { let p = choice2(literal("gnostika").to(1), one_or_more(literal(" ")).to(2)); assert_eq!(p.parse("gnostika twentynine"), Ok((1, " twentynine"))); } }