use crate::parser::{ParseResult, Parser}; pub fn choice2(parser1: P1, parser2: P2) -> impl Parser where P1: Parser, P2: Parser, I: Clone, { move |input: I| match parser1.parse(input.clone()) { 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()) } } impl Choice for (P1, P2, P3) where P1: Parser, P2: Parser, P3: Parser, I: Clone, { fn parse(&self, input: I) -> ParseResult { let parser1 = &self.0; let parser2 = &self.1; let parser3 = &self.2; //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, parser3].iter() { match parser.parse(input.clone()) { Ok(result) => return Ok(result), Err(e) => { err = Some(e); } } } Err(err.unwrap()) } } impl Choice for (P1, P2, P3, P4) where P1: Parser, P2: Parser, P3: Parser, P4: Parser, I: Clone, { fn parse(&self, input: I) -> ParseResult { let parser1 = &self.0; let parser2 = &self.1; let parser3 = &self.2; let parser4 = &self.3; //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, parser3, parser4].iter() { match parser.parse(input.clone()) { Ok(result) => return Ok(result), Err(e) => { err = Some(e); } } } Err(err.unwrap()) } } impl Choice for (P1, P2, P3, P4, P5) where P1: Parser, P2: Parser, P3: Parser, P4: Parser, P5: Parser, I: Clone, { fn parse(&self, input: I) -> ParseResult { let parser1 = &self.0; let parser2 = &self.1; let parser3 = &self.2; let parser4 = &self.3; let parser5 = &self.4; //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, parser3, parser4, parser5, ] .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"))); } }