From e6037210c61b3da6d51faf0b4b1b4e3110274831 Mon Sep 17 00:00:00 2001 From: John Turner Date: Mon, 27 Oct 2025 01:10:42 -0400 Subject: replace take_while and separated_list with list combinator --- src/lib.rs | 228 +++++++++++-------------------------------------------------- 1 file changed, 39 insertions(+), 189 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 3454e96..ad5a479 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,7 @@ use core::{ fmt, iter::{IntoIterator, Iterator}, marker::Sized, - ops::Range, + ops::{Bound, Range, RangeBounds}, }; use crate::{ @@ -151,23 +151,13 @@ pub trait Parser: Sized { Recognize { parser: self } } - fn separated_list

(self, delimiter: P) -> impl Parser> + fn list(self, range: R) -> impl Parser> where - P: Parser, + R: RangeBounds, { - SeparatedList { + List { parser: self, - delimiter, - } - } - - fn separated_list1

(self, delimiter: P) -> impl Parser> - where - P: Parser, - { - SeparatedList1 { - parser: self, - delimiter, + range, } } @@ -371,86 +361,48 @@ where Take { amt } } -pub struct TakeWhile

{ +struct List { parser: P, + range: R, } -impl Parser for TakeWhile

+impl Parser for List where I: Input, P: Parser, + R: RangeBounds, { - type Output = I; + type Output = Vec; fn run>( &self, mut it: InputIter, ) -> ParserResult { - Tracer::trace("takewhile", it.clone()); - - let start = it.clone(); - - while let Ok((rest, _)) = self.parser.run::(it.clone()) { - it = rest; - } - - Ok(( - it.clone(), - OM::bind(|| it.input.slice(start.position()..it.position())), - )) - } -} - -pub fn take_while(parser: P) -> impl Parser -where - I: Input, - P: Parser, -{ - TakeWhile { parser } -} - -pub struct TakeWhile1

{ - parser: P, -} - -impl Parser for TakeWhile1

-where - I: Input, - P: Parser, -{ - type Output = I; + Tracer::trace("list", it.clone()); - fn run>( - &self, - mut it: InputIter, - ) -> ParserResult { - Tracer::trace("takewhile1", it.clone()); + let mut outputs = OM::bind(|| Vec::new()); + let mut i = 0; - let start = it.clone(); + 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 + } + Err(_) if self.range.contains(&i) => break, + Err(rest) => return Err(rest), + }; - while let Ok((rest, _)) = self.parser.run::(it.clone()) { - it = rest; + i += 1; } - if it.position() > start.position() { - Ok(( - it.clone(), - OM::bind(|| it.input.slice(start.position()..it.position())), - )) - } else { - Err(EM::bind(|| it)) - } + Ok((it, outputs)) } } -pub fn take_while1(parser: P) -> impl Parser -where - I: Input, - P: Parser, -{ - TakeWhile1 { parser } -} - pub struct OneOf { it: It, } @@ -682,101 +634,6 @@ where Tag(tag) } -struct SeparatedList { - parser: P1, - delimiter: P2, -} - -impl Parser for SeparatedList -where - I: Input, - P1: Parser, - P2: Parser, -{ - type Output = Vec; - - fn run>( - &self, - mut it: InputIter, - ) -> ParserResult { - Tracer::trace("separated list", it.clone()); - - let mut outputs = OM::bind(|| Vec::new()); - - loop { - it = match self.parser.run::(it.clone()) { - Ok((rest, output)) => { - outputs = OM::combine(outputs, output, |mut acc, e| { - acc.push(e); - acc - }); - rest - } - _ => break, - }; - - it = match self.delimiter.check(it.clone()) { - Ok((rest, _)) => rest, - _ => break, - }; - } - - Ok((it, outputs)) - } -} - -pub struct SeparatedList1 { - parser: P1, - delimiter: P2, -} - -impl Parser for SeparatedList1 -where - I: Input, - P1: Parser, - P2: Parser, -{ - type Output = Vec; - - fn run>( - &self, - mut it: InputIter, - ) -> ParserResult { - Tracer::trace("separated list 1", it.clone()); - - it = match self.delimiter.check(it.clone()) { - Ok((rest, _)) => rest, - Err(_) => it, - }; - - let mut outputs = OM::bind(|| Vec::new()); - let mut len = 0; - - loop { - it = match self.parser.run::(it.clone()) { - Ok((rest, output)) => { - outputs = OM::combine(outputs, output, |mut acc, e| { - acc.push(e); - acc - }); - len += 1; - rest - } - _ if len > 0 => break, - _ => return Err(EM::bind(|| it)), - }; - - it = match self.delimiter.check(it.clone()) { - Ok((rest, _)) => rest, - _ if len > 0 => break, - _ => return Err(EM::bind(|| it)), - }; - } - - Ok((it, outputs)) - } -} - struct Not

{ parser: P, } @@ -943,7 +800,7 @@ where I: Input, I::Item: Character, { - take_while(r#if(|c: &I::Item| c.is_alphabetic())) + r#if(|c: &I::Item| c.is_alphabetic()).list(0..).recognize() } pub fn alpha1() -> impl Parser @@ -951,7 +808,7 @@ where I: Input, I::Item: Character, { - take_while1(r#if(|c: &I::Item| c.is_alphabetic())) + r#if(|c: &I::Item| c.is_alphabetic()).list(1..).recognize() } pub fn numeric() -> impl Parser @@ -959,7 +816,7 @@ where I: Input, I::Item: Character, { - take_while(r#if(|c: &I::Item| c.is_numeric())) + r#if(|c: &I::Item| c.is_numeric()).list(0..).recognize() } pub fn numeric1() -> impl Parser @@ -967,7 +824,7 @@ where I: Input, I::Item: Character, { - take_while1(r#if(|c: &I::Item| c.is_numeric())) + r#if(|c: &I::Item| c.is_numeric()).list(1..).recognize() } pub fn alphanumeric() -> impl Parser @@ -975,7 +832,9 @@ where I: Input, I::Item: Character, { - take_while(r#if(|c: &I::Item| c.is_alphanumeric())) + r#if(|c: &I::Item| c.is_alphanumeric()) + .list(0..) + .recognize() } pub fn alphanumeric1() -> impl Parser @@ -983,7 +842,9 @@ where I: Input, I::Item: Character, { - take_while1(r#if(|c: &I::Item| c.is_alphanumeric())) + r#if(|c: &I::Item| c.is_alphanumeric()) + .list(1..) + .recognize() } pub fn whitespace() -> impl Parser @@ -991,7 +852,7 @@ where I: Input, I::Item: Character, { - take_while(r#if(|c: &I::Item| c.is_whitespace())) + r#if(|c: &I::Item| c.is_whitespace()).list(0..).recognize() } pub fn whitespace1() -> impl Parser @@ -999,7 +860,7 @@ where I: Input, I::Item: Character, { - take_while1(r#if(|c: &I::Item| c.is_whitespace())) + r#if(|c: &I::Item| c.is_whitespace()).list(1..).recognize() } pub mod str { @@ -1035,17 +896,6 @@ 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()) - .check_finished(it) - .unwrap(); - } - #[test] fn test_regex_parser() { let it = InputIter::new("abc 123"); -- cgit v1.2.3