use crate::parser::{ParseResult, Parser, ParserInput, Representation}; pub fn choice2(parser1: P1, parser2: P2) -> impl Parser where P1: Parser, P2: Parser, I: ParserInput + Clone, { choice((parser1, parser2)) } pub fn choice(choices: C) -> impl Parser where C: Choice, I: ParserInput + Clone, { let rep = choices.representation(); (move |input| choices.parse(input), rep) } pub trait Choice { fn parse(&self, input: I) -> ParseResult; fn representation(&self) -> Representation; } impl Choice for (P1, P2) where P1: Parser, P2: Parser, I: ParserInput + Clone, { fn parse(&self, input: I) -> ParseResult { let parsers = vec![&self.0 as &dyn Parser, &self.1]; choice_loop(input, parsers) } fn representation(&self) -> Representation { let parsers = vec![&self.0 as &dyn Parser, &self.1]; repr_loop(parsers) } } impl Choice for (P1, P2, P3) where P1: Parser, P2: Parser, P3: Parser, I: ParserInput + Clone, { fn parse(&self, input: I) -> ParseResult { let parsers = vec![&self.0 as &dyn Parser, &self.1, &self.2]; choice_loop(input, parsers) } fn representation(&self) -> Representation { let parsers = vec![&self.0 as &dyn Parser, &self.1, &self.2]; repr_loop(parsers) } } impl Choice for (P1, P2, P3, P4) where P1: Parser, P2: Parser, P3: Parser, P4: Parser, I: ParserInput + Clone, { fn parse(&self, input: I) -> ParseResult { let parsers = vec![&self.0 as &dyn Parser, &self.1, &self.2, &self.3]; choice_loop(input, parsers) } fn representation(&self) -> Representation { let parsers = vec![&self.0 as &dyn Parser, &self.1, &self.2, &self.3]; repr_loop(parsers) } } impl Choice for (P1, P2, P3, P4, P5) where P1: Parser, P2: Parser, P3: Parser, P4: Parser, P5: Parser, I: ParserInput + Clone, { fn parse(&self, input: I) -> ParseResult { let parsers = vec![ &self.0 as &dyn Parser, &self.1, &self.2, &self.3, &self.4, ]; choice_loop(input, parsers) } fn representation(&self) -> Representation { let parsers = vec![ &self.0 as &dyn Parser, &self.1, &self.2, &self.3, &self.4, ]; repr_loop(parsers) } } impl Choice for (P1, P2, P3, P4, P5, P6) where P1: Parser, P2: Parser, P3: Parser, P4: Parser, P5: Parser, P6: Parser, I: ParserInput + Clone, { fn parse(&self, input: I) -> ParseResult { let parsers = vec![ &self.0 as &dyn Parser, &self.1, &self.2, &self.3, &self.4, &self.5, ]; choice_loop(input, parsers) } fn representation(&self) -> Representation { let parsers = vec![ &self.0 as &dyn Parser, &self.1, &self.2, &self.3, &self.4, &self.5, ]; repr_loop(parsers) } } fn choice_loop(input: I, parsers: Vec<&dyn Parser>) -> ParseResult where I: ParserInput + Clone, { //TODO need a more principled way to return an error when no choices work let mut err = None; for parser in parsers.iter() { match parser.parse(input.clone()) { Ok(result) => return Ok(result), Err(e) => { err = Some(e); } } } Err(err.unwrap()) } fn repr_loop(parsers: Vec<&dyn Parser>) -> Representation where I: ParserInput + Clone, { let mut iter = parsers.iter().map(|p| p.representation()); Representation::from_choice(&mut iter) } #[cfg(test)] mod tests { use super::*; use crate::combinators::repeated; use crate::primitives::literal; #[test] fn test_choice() { let p = choice2( literal("gnostika").to(1), repeated(literal(" ")).at_least(1).to(2), ); assert_eq!(p.parse("gnostika twentynine"), Ok((1, " twentynine"))); } #[test] fn test_several_choices() { let p = choice(( literal("a").to(1), literal("q").to(10), repeated(literal("chutney")).to(200), literal("banana").to(10000), )); assert_eq!(p.parse("q drugs").unwrap(), (10, " drugs")); } }