diff options
| author | John Turner <jturner.usa@gmail.com> | 2025-11-01 18:14:13 +0000 |
|---|---|---|
| committer | John Turner <jturner.usa@gmail.com> | 2025-11-01 18:14:13 +0000 |
| commit | 13af9e0fccdbdb1ded8401623d4633415ff8033b (patch) | |
| tree | 0d66dc961f0c8466812ff528e01707cc0332911b | |
| parent | da2980e5c9e7da3839eb71e450f206b1121d326e (diff) | |
| download | mon-13af9e0fccdbdb1ded8401623d4633415ff8033b.tar.gz | |
impl Find combinator
| -rw-r--r-- | src/lib.rs | 44 |
1 files changed, 44 insertions, 0 deletions
@@ -198,6 +198,10 @@ pub trait Parser<I: Input>: Sized { delimiter, } } + + fn find(self) -> impl ParserIter<I, Item = Self::Output> { + Find { parser: self } + } } pub trait ParserIter<I: Input> { @@ -951,6 +955,35 @@ where } } +struct Find<P> { + parser: P, +} + +impl<I, P> ParserIter<I> for Find<P> +where + I: Input, + P: Parser<I>, +{ + type Item = P::Output; + + fn next<OM: Mode, EM: Mode>( + &self, + mut it: InputIter<I>, + ) -> Option<ParserResult<I, Self::Item, OM, EM>> { + while !it.is_finished() { + it = match self.parser.run::<OM, EM, ()>(it.clone()) { + Ok((rest, output)) => return Some(Ok((rest, output))), + Err(_) => match take(1).check(it.clone()) { + Ok((rest, _)) => rest, + Err(_) => return None, + }, + }; + } + + None + } +} + pub fn eof<I>() -> impl Parser<I, Output = ()> where I: Input, @@ -1100,6 +1133,17 @@ mod test { } #[test] + fn test_find() { + let input = "hello world"; + let it = InputIter::new(input); + + assert_eq!( + alpha1().find().at_least(1).parse_finished(it).unwrap(), + vec!["hello", "world"] + ); + } + + #[test] #[cfg(feature = "regex")] fn test_regex_parser() { let it = InputIter::new("abc 123"); |
