diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib.rs | 228 |
1 files changed, 39 insertions, 189 deletions
@@ -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<I: Input>: Sized { Recognize { parser: self } } - fn separated_list<P>(self, delimiter: P) -> impl Parser<I, Output = Vec<Self::Output>> + fn list<R>(self, range: R) -> impl Parser<I, Output = Vec<Self::Output>> where - P: Parser<I>, + R: RangeBounds<usize>, { - SeparatedList { + List { parser: self, - delimiter, - } - } - - fn separated_list1<P>(self, delimiter: P) -> impl Parser<I, Output = Vec<Self::Output>> - where - P: Parser<I>, - { - SeparatedList1 { - parser: self, - delimiter, + range, } } @@ -371,86 +361,48 @@ where Take { amt } } -pub struct TakeWhile<P> { +struct List<P, R> { parser: P, + range: R, } -impl<I, P> Parser<I> for TakeWhile<P> +impl<I, P, R> Parser<I> for List<P, R> where I: Input, P: Parser<I>, + R: RangeBounds<usize>, { - type Output = I; + type Output = Vec<P::Output>; fn run<OM: Mode, EM: Mode, Tracer: Trace<I>>( &self, mut it: InputIter<I>, ) -> ParserResult<I, Self::Output, OM, EM> { - Tracer::trace("takewhile", it.clone()); - - let start = it.clone(); - - while let Ok((rest, _)) = self.parser.run::<Check, Check, Tracer>(it.clone()) { - it = rest; - } - - Ok(( - it.clone(), - OM::bind(|| it.input.slice(start.position()..it.position())), - )) - } -} - -pub fn take_while<I, P>(parser: P) -> impl Parser<I, Output = I> -where - I: Input, - P: Parser<I>, -{ - TakeWhile { parser } -} - -pub struct TakeWhile1<P> { - parser: P, -} - -impl<I, P> Parser<I> for TakeWhile1<P> -where - I: Input, - P: Parser<I>, -{ - type Output = I; + Tracer::trace("list", it.clone()); - fn run<OM: Mode, EM: Mode, Tracer: Trace<I>>( - &self, - mut it: InputIter<I>, - ) -> ParserResult<I, Self::Output, OM, EM> { - 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::<OM, EM, Tracer>(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::<Check, Check, Tracer>(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<I, P>(parser: P) -> impl Parser<I, Output = I> -where - I: Input, - P: Parser<I>, -{ - TakeWhile1 { parser } -} - pub struct OneOf<It> { it: It, } @@ -682,101 +634,6 @@ where Tag(tag) } -struct SeparatedList<P1, P2> { - parser: P1, - delimiter: P2, -} - -impl<I, P1, P2> Parser<I> for SeparatedList<P1, P2> -where - I: Input, - P1: Parser<I>, - P2: Parser<I>, -{ - type Output = Vec<P1::Output>; - - fn run<OM: Mode, EM: Mode, Tracer: Trace<I>>( - &self, - mut it: InputIter<I>, - ) -> ParserResult<I, Self::Output, OM, EM> { - Tracer::trace("separated list", it.clone()); - - let mut outputs = OM::bind(|| Vec::new()); - - loop { - it = match self.parser.run::<OM, EM, Tracer>(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<P1, P2> { - parser: P1, - delimiter: P2, -} - -impl<I, P1, P2> Parser<I> for SeparatedList1<P1, P2> -where - I: Input, - P1: Parser<I>, - P2: Parser<I>, -{ - type Output = Vec<P1::Output>; - - fn run<OM: Mode, EM: Mode, Tracer: Trace<I>>( - &self, - mut it: InputIter<I>, - ) -> ParserResult<I, Self::Output, OM, EM> { - 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::<OM, EM, Tracer>(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<P> { 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<I>() -> impl Parser<I, Output = I> @@ -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<I>() -> impl Parser<I, Output = I> @@ -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<I>() -> impl Parser<I, Output = I> @@ -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<I>() -> impl Parser<I, Output = I> @@ -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<I>() -> impl Parser<I, Output = I> @@ -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<I>() -> impl Parser<I, Output = I> @@ -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<I>() -> impl Parser<I, Output = I> @@ -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 { @@ -1036,17 +897,6 @@ 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"); |
