diff options
Diffstat (limited to 'src/lib.rs')
| -rw-r--r-- | src/lib.rs | 74 |
1 files changed, 74 insertions, 0 deletions
@@ -169,6 +169,16 @@ pub trait Parser<I: Input>: Sized { } } + fn separated_by_with_trailing<P>(self, delimiter: P) -> impl ParserIter<I, Item = Self::Output> + where + P: Parser<I>, + { + SeparatedByWithTrailing { + parser: self, + delimiter, + } + } + fn find(self) -> impl ParserIter<I, Item = Self::Output> { Find { parser: self } } @@ -274,6 +284,44 @@ where } } +struct SeparatedByWithTrailing<P1, P2> { + parser: P1, + delimiter: P2, +} + +impl<I, P1, P2> ParserIter<I> for SeparatedByWithTrailing<P1, P2> +where + I: Input, + P1: Parser<I>, + P2: Parser<I>, +{ + type Item = P1::Output; + + fn next<OM: Mode, EM: Mode>( + &self, + it: InputIter<I>, + ) -> Option<ParserResult<I, Self::Item, OM, EM>> { + if it.is_finished() { + None + } else { + let (rest, output) = match self.parser.run::<OM, EM>(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<P> { parser: P, count: usize, @@ -1047,6 +1095,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"; let it = InputIter::new(input); |
