use crate::{ParseResult, Parser}; pub trait Choice { fn parse_choice(&self, input: I) -> Result<(O, I), (E, I)>; } pub fn choice, I, O, E>(choices: C) -> impl Parser { move |input| choices.parse_choice(input) } fn choice_loop<'a, I, O, E>( mut input: I, parsers: &'a [&'a dyn Parser], ) -> ParseResult { //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) { Ok(res) => return Ok(res), Err((e, rest)) => { err = Some(e); input = rest; } } } Err((err.unwrap(), input)) } impl Choice for (P1, P2) where P1: Parser, P2: Parser, { fn parse_choice(&self, input: I) -> Result<(O, I), (E, I)> { choice_loop(input, &[&self.0, &self.1]) } } impl Choice for (P1, P2, P3) where P1: Parser, P2: Parser, P3: Parser, { fn parse_choice(&self, input: I) -> Result<(O, I), (E, I)> { choice_loop(input, &[&self.0, &self.1, &self.2]) } } impl Choice for (P1, P2, P3, P4) where P1: Parser, P2: Parser, P3: Parser, P4: Parser, { fn parse_choice(&self, input: I) -> Result<(O, I), (E, I)> { choice_loop(input, &[&self.0, &self.1, &self.2, &self.3]) } } impl Choice for (P1, P2, P3, P4, P5) where P1: Parser, P2: Parser, P3: Parser, P4: Parser, P5: Parser, { fn parse_choice(&self, input: I) -> Result<(O, I), (E, I)> { choice_loop(input, &[&self.0, &self.1, &self.2, &self.3, &self.4]) } }