summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Turner <jturner.usa@gmail.com>2025-11-01 18:14:13 +0000
committerJohn Turner <jturner.usa@gmail.com>2025-11-01 18:14:13 +0000
commit13af9e0fccdbdb1ded8401623d4633415ff8033b (patch)
tree0d66dc961f0c8466812ff528e01707cc0332911b
parentda2980e5c9e7da3839eb71e450f206b1121d326e (diff)
downloadmon-13af9e0fccdbdb1ded8401623d4633415ff8033b.tar.gz
impl Find combinator
-rw-r--r--src/lib.rs44
1 files changed, 44 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
index d963e36..d2af3ac 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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");