From 6633d10af0f9a2331c66b1485fbd447e410931b7 Mon Sep 17 00:00:00 2001 From: Greg Shuflin Date: Thu, 20 Oct 2022 23:47:06 -0700 Subject: [PATCH] choice work --- src/choice.rs | 147 +++++++++++++++++--------------------------------- 1 file changed, 49 insertions(+), 98 deletions(-) diff --git a/src/choice.rs b/src/choice.rs index 4ed3fe4..fb2cd16 100644 --- a/src/choice.rs +++ b/src/choice.rs @@ -31,21 +31,8 @@ where 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()) + let parsers = vec![&self.0 as &dyn Parser, &self.1]; + choice_loop(input, parsers) } } @@ -57,22 +44,8 @@ where 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()) + let parsers = vec![&self.0 as &dyn Parser, &self.1, &self.2]; + choice_loop(input, parsers) } } @@ -85,23 +58,8 @@ where 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()) + let parsers = vec![&self.0 as &dyn Parser, &self.1, &self.2, &self.3]; + choice_loop(input, parsers) } } @@ -115,32 +73,14 @@ where 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()) + let parsers = vec![ + &self.0 as &dyn Parser, + &self.1, + &self.2, + &self.3, + &self.4, + ]; + choice_loop(input, parsers) } } @@ -155,35 +95,34 @@ where 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; - let parser6 = &self.5; + let parsers = vec![ + &self.0 as &dyn Parser, + &self.1, + &self.2, + &self.3, + &self.4, + &self.5, + ]; + choice_loop(input, parsers) + } +} - //TODO need a more principled way to return an error when no choices work - let mut err = None; +fn choice_loop(input: I, parsers: Vec<&dyn Parser>) -> ParseResult +where + I: Clone, +{ + //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, - parser6, - ] - .iter() - { - match parser.parse(input.clone()) { - Ok(result) => return Ok(result), - Err(e) => { - err = Some(e); - } + for parser in parsers.iter() { + match parser.parse(input.clone()) { + Ok(result) => return Ok(result), + Err(e) => { + err = Some(e); } } - Err(err.unwrap()) } + Err(err.unwrap()) } #[cfg(test)] @@ -200,4 +139,16 @@ mod tests { ); 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")); + } }