From 438ade86160efc42ecab98322ceec8ef8d73aacf Mon Sep 17 00:00:00 2001 From: John Turner Date: Mon, 17 Nov 2025 21:19:21 +0000 Subject: let ParserIters store some state by passing in a &mut ParserIterState struct to next --- src/lib.rs | 49 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 02972af..fe9a720 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -184,12 +184,17 @@ pub trait Parser: Sized { } } +pub struct ParserIterState { + finished: bool, +} + pub trait ParserIter { type Item; fn next( &self, it: InputIter, + state: &mut ParserIterState, ) -> Option>; fn many(self) -> impl Parser> @@ -234,6 +239,7 @@ where fn next( &self, it: InputIter, + _: &mut ParserIterState, ) -> Option> { if it.is_finished() { None @@ -262,8 +268,9 @@ where fn next( &self, it: InputIter, + state: &mut ParserIterState, ) -> Option> { - if it.is_finished() { + if it.is_finished() || state.finished { None } else { let (rest, output) = match self.parser.run::(it) { @@ -271,15 +278,16 @@ where Err(rest) => return Some(Err(rest)), }; - let rest = match self.delimiter.check(rest.clone()) { + match self.delimiter.check(rest.clone()) { Ok((rest, _)) => match self.parser.check(rest.clone()) { - Ok(_) => rest, - Err(_) => return Some(Err(EM::bind(|| rest))), + Ok(_) => Some(Ok((rest, output))), + Err(_) => Some(Err(EM::bind(|| rest))), }, - _ => rest, - }; - - Some(Ok((rest, output))) + _ => { + state.finished = true; + Some(Ok((rest, output))) + } + } } } } @@ -300,6 +308,7 @@ where fn next( &self, it: InputIter, + _: &mut ParserIterState, ) -> Option> { if it.is_finished() { None @@ -340,9 +349,10 @@ where ) -> ParserResult { let mut outputs = OM::bind(|| Vec::new()); let mut i = 0; + let mut state = ParserIterState { finished: false }; while !it.is_finished() { - it = match self.parser.next::(it.clone()) { + it = match self.parser.next::(it.clone(), &mut state) { Some(Ok((rest, output))) => { outputs = OM::combine(outputs, output, |mut acc, e| { acc.push(e); @@ -384,9 +394,10 @@ where mut it: InputIter, ) -> ParserResult { let mut outputs = OM::bind(|| Vec::new()); + let mut state = ParserIterState { finished: false }; for _ in 0..self.count { - it = match self.parser.next::(it.clone()) { + it = match self.parser.next::(it.clone(), &mut state) { Some(Ok((rest, output))) => { outputs = OM::combine(outputs, output, |mut acc, e| { acc.push(e); @@ -418,9 +429,10 @@ where mut it: InputIter, ) -> ParserResult { let mut outputs = OM::bind(|| Vec::new()); + let mut state = ParserIterState { finished: false }; while !it.is_finished() { - it = match self.parser.next::(it.clone()) { + it = match self.parser.next::(it.clone(), &mut state) { Some(Ok((rest, output))) => { outputs = OM::combine(outputs, output, |mut acc, e| { acc.push(e); @@ -922,6 +934,7 @@ where fn next( &self, mut it: InputIter, + _: &mut ParserIterState, ) -> Option> { while !it.is_finished() { it = match self.parser.run::(it.clone()) { @@ -1106,6 +1119,20 @@ mod test { .unwrap(); } + #[test] + fn test_separated_by_with_adjacent_p() { + let input = "p_p_pp_p"; + let it = InputIter::new(input); + + assert!( + tag("p") + .separated_by(tag("_")) + .at_least(1) + .check_finished(it) + .is_err() + ); + } + #[test] fn test_separated_by_with_trailing_without_trailing() { let input = "1.0"; -- cgit v1.2.3