From 57058764776fa3d9aa0d75bbe6875fd1414c0d48 Mon Sep 17 00:00:00 2001 From: Greg Shuflin Date: Thu, 20 Oct 2022 23:29:06 -0700 Subject: [PATCH] Separated by --- src/combinators.rs | 72 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 13 deletions(-) diff --git a/src/combinators.rs b/src/combinators.rs index b7302d0..5f2fe80 100644 --- a/src/combinators.rs +++ b/src/combinators.rs @@ -49,15 +49,16 @@ where } } - pub fn delimited_by(self, delimiter: D) -> DelimitedBy<'a, I, O> + pub fn separated_by(self, delimiter: D, allow_trailing: bool) -> SeparatedBy<'a, I, O> where D: Parser + 'a, O2: 'a, I: 'a, { - DelimitedBy { + SeparatedBy { inner_repeated: self, delimiter: BoxedParser::new(delimiter.to(())), + allow_trailing, } } } @@ -94,21 +95,24 @@ where } } -pub struct DelimitedBy<'a, I, O> +pub struct SeparatedBy<'a, I, O> where I: Clone, { inner_repeated: Repeated<'a, I, O>, delimiter: BoxedParser<'a, I, (), I>, + allow_trailing: bool, } -impl<'a, I, O> Parser, I> for DelimitedBy<'a, I, O> +impl<'a, I, O> Parser, I> for SeparatedBy<'a, I, O> where I: Clone + 'a, { fn parse(&self, input: I) -> ParseResult, I> { let at_least = self.inner_repeated.at_least.unwrap_or(0); let at_most = self.inner_repeated.at_most.unwrap_or(u16::MAX); + let parser = &self.inner_repeated.inner_parser; + let delimiter = &self.delimiter; if at_most == 0 { return Ok((vec![], input)); @@ -116,20 +120,51 @@ where let mut results = Vec::new(); let mut count: u16 = 0; - let mut further_input = input.clone(); + let mut further_input; + + match parser.parse(input.clone()) { + Ok((item, rest)) => { + results.push(item); + further_input = rest; + } + Err(_e) => { + if at_least > 0 { + return Err(input); + } else { + return Ok((vec![], input)); + } + } + } + + loop { + match delimiter.parse(further_input.clone()) { + Ok(((), rest)) => { + further_input = rest; + } + Err(_e) => { + break; + } + } + + match parser.parse(further_input.clone()) { + Ok((item, rest)) => { + results.push(item); + further_input = rest; + count += 1; + } + Err(_e) if self.allow_trailing => { + break; + } + Err(e) => { + return Err(e); + } + } - while let Ok((item, rest)) = self - .inner_repeated - .inner_parser - .parse(further_input.clone()) - { - results.push(item); - further_input = rest; - count += 1; if count >= at_most { break; } } + if count < at_least { return Err(input); } @@ -175,4 +210,15 @@ mod tests { assert_eq!(output.len(), 1); assert_eq!(rest, "ecks"); } + + #[test] + fn test_separated_by() { + let p = repeated(literal("garb").to(20)) + .separated_by(repeated(literal(" ")).at_least(1), false); + + assert_eq!( + p.parse("garb garb garb garb").unwrap(), + (vec![20, 20, 20, 20], "") + ); + } }