summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Turner <jturner.usa@gmail.com>2025-10-27 01:10:42 -0400
committerJohn Turner <jturner.usa@gmail.com>2025-10-27 01:10:42 -0400
commite6037210c61b3da6d51faf0b4b1b4e3110274831 (patch)
tree31f8351d1efb28243acb8087465c2db7d667db49
parent191a3e2d48e153492e1480166a8511d0563c957c (diff)
downloadmon-e6037210c61b3da6d51faf0b4b1b4e3110274831.tar.gz
replace take_while and separated_list with list combinator
-rw-r--r--src/lib.rs228
-rw-r--r--tests/sexpr.rs3
2 files changed, 41 insertions, 190 deletions
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<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");
diff --git a/tests/sexpr.rs b/tests/sexpr.rs
index dd00b73..4434670 100644
--- a/tests/sexpr.rs
+++ b/tests/sexpr.rs
@@ -32,7 +32,8 @@ fn int<'a>() -> impl Parser<&'a str, Output = Sexpr> {
fn sexpr<'a>(it: InputIter<&'a str>) -> ParserResult<&'a str, Sexpr> {
sexpr
- .separated_list(whitespace())
+ .followed_by(whitespace())
+ .list(0..)
.delimited_by(tag("("), tag(")"))
.map(|output| Sexpr::List(output))
.or(atom())