From 34d8eeb989012b0f20041b11a60ced24ca702527 Mon Sep 17 00:00:00 2001 From: John Turner Date: Fri, 14 Nov 2025 22:22:44 +0000 Subject: impl SeparatedByWithTrailing combinator --- src/lib.rs | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 7c1bbcc..02972af 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -169,6 +169,16 @@ pub trait Parser: Sized { } } + fn separated_by_with_trailing

(self, delimiter: P) -> impl ParserIter + where + P: Parser, + { + SeparatedByWithTrailing { + parser: self, + delimiter, + } + } + fn find(self) -> impl ParserIter { Find { parser: self } } @@ -274,6 +284,44 @@ where } } +struct SeparatedByWithTrailing { + parser: P1, + delimiter: P2, +} + +impl ParserIter for SeparatedByWithTrailing +where + I: Input, + P1: Parser, + P2: Parser, +{ + type Item = P1::Output; + + fn next( + &self, + it: InputIter, + ) -> Option> { + if it.is_finished() { + None + } else { + let (rest, output) = match self.parser.run::(it) { + Ok((rest, output)) => match self.delimiter.check(rest.clone()) { + Ok(_) => (rest, output), + Err(_) => return Some(Err(EM::bind(|| rest))), + }, + Err(rest) => return Some(Err(rest)), + }; + + let rest = match self.delimiter.check(rest.clone()) { + Ok((rest, _)) => rest, + _ => rest, + }; + + Some(Ok((rest, output))) + } + } +} + struct AtLeast

{ parser: P, count: usize, @@ -1046,6 +1094,32 @@ mod test { ); } + #[test] + fn test_separated_by_with_trailing() { + let input = "1.0."; + let it = InputIter::new(input); + + numeric1() + .separated_by_with_trailing(tag(".")) + .at_least(1) + .check_finished(it) + .unwrap(); + } + + #[test] + fn test_separated_by_with_trailing_without_trailing() { + let input = "1.0"; + let it = InputIter::new(input); + + assert!( + numeric1() + .separated_by_with_trailing(tag(".")) + .at_least(1) + .check_finished(it) + .is_err() + ); + } + #[test] fn test_find() { let input = "hello world"; -- cgit v1.2.3