From b8250a0f3975b63f54eea370d9d0907e92252984 Mon Sep 17 00:00:00 2001 From: John Turner Date: Mon, 27 Oct 2025 01:37:29 -0400 Subject: bring back separated_list but with a range parameter --- src/lib.rs | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index cdc5d0f..02ab717 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,8 @@ use core::{ ops::{Bound, Range, RangeBounds}, }; +use regex::Replacer; + use crate::{ input::{Character, Input, InputIter}, mode::{Check, Emit, Mode}, @@ -192,6 +194,22 @@ pub trait Parser: Sized { fn not(self) -> impl Parser { Not { parser: self } } + + fn separated_list( + self, + delimiter: P, + range: R, + ) -> impl Parser> + where + P: Parser, + R: RangeBounds, + { + SeparatedList { + parser: self, + delimiter, + range, + } + } } impl Parser for F @@ -411,6 +429,56 @@ where } } +struct SeparatedList { + parser: P1, + delimiter: P2, + range: R, +} + +impl Parser for SeparatedList +where + I: Input, + P1: Parser, + P2: Parser, + R: RangeBounds, +{ + type Output = Vec; + + fn run>( + &self, + mut it: InputIter, + ) -> ParserResult { + Tracer::trace("separated list", it.clone()); + + let mut outputs = OM::bind(|| Vec::new()); + let mut i = 0usize; + + while (Bound::Unbounded, self.range.end_bound()).contains(&i) { + it = match self.parser.run::(it.clone()) { + Ok((rest, output)) => { + outputs = OM::combine(outputs, output, |mut acc, e| { + acc.push(e); + acc + }); + rest + } + _ if self.range.contains(&i) => break, + _ => return Err(EM::bind(|| it)), + }; + + it = match self.delimiter.check(it.clone()) { + Ok((rest, _)) => rest, + _ if self.range.contains(&i) => break, + _ => return Err(EM::bind(|| it)), + }; + + i += 1; + } + + Ok((it, outputs)) + } +} + pub struct OneOf { it: It, } @@ -888,6 +956,17 @@ pub mod str { mod test { use super::*; + #[test] + fn test_separated_list() { + let input = "a b c"; + let it = InputIter::new(input); + + alpha1() + .separated_list(whitespace(), 1..) + .check_finished(it) + .unwrap(); + } + #[test] fn test_regex_parser() { let it = InputIter::new("abc 123"); -- cgit v1.2.3