summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Turner <jturner.usa@gmail.com>2025-11-14 22:22:44 +0000
committerJohn Turner <jturner.usa@gmail.com>2025-11-14 22:22:44 +0000
commit34d8eeb989012b0f20041b11a60ced24ca702527 (patch)
treefa19e5edb3540d00d02c2b1245c58028ed505f00
parente6c5335d43bfbf2fffa3d3c44cde404c970e5ee6 (diff)
downloadmon-34d8eeb989012b0f20041b11a60ced24ca702527.tar.gz
impl SeparatedByWithTrailing combinator
-rw-r--r--src/lib.rs74
1 files changed, 74 insertions, 0 deletions
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<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);