diff --git a/src/combinators.rs b/src/combinators.rs index 4ffe931..f4913f6 100644 --- a/src/combinators.rs +++ b/src/combinators.rs @@ -2,19 +2,21 @@ use std::marker::PhantomData; use crate::{ParseResult, Parser}; -pub fn repeated
(parser: P) -> impl Parser, E> +pub fn repeated
(parser: P) -> Repeated
where P: Parser, { Repeated::new(parser) } -struct Repeated
+pub struct Repeated
where
P: Parser,
{
inner_parser: P,
phantom: PhantomData<(I, O, E)>,
+ at_least: Option Repeated
@@ -25,6 +27,31 @@ where
Self {
inner_parser,
phantom: PhantomData,
+ at_least: None,
+ at_most: None,
+ }
+ }
+ pub fn at_least(self, at_least: u32) -> Self {
+ Self {
+ at_least: Some(at_least),
+ ..self
+ }
+ }
+ pub fn at_most(self, at_most: u32) -> Self {
+ Self {
+ at_most: Some(at_most),
+ ..self
+ }
+ }
+ pub fn separated_by Parser, E> for Repeated
where
P: Parser,
+ E: Default,
{
- fn parse(&self, input: I) -> ParseResult, E> {
- let mut acc = input;
+ fn parse(&self, mut input: I) -> ParseResult, E> {
+ let at_least = self.at_least.unwrap_or(0);
+ let at_most = self.at_most.unwrap_or(u32::MAX);
+
let mut results = vec![];
+ let mut count = 0;
+
+ if at_most == 0 {
+ return Ok((vec![], input));
+ }
loop {
- match self.inner_parser.parse(acc) {
+ match self.inner_parser.parse(input) {
Ok((item, rest)) => {
results.push(item);
- acc = rest;
+ input = rest;
+ count += 1;
+ if count >= at_most {
+ break;
+ }
}
Err((_err, rest)) => {
- acc = rest;
+ input = rest;
break;
}
}
}
- Ok((results, acc))
+
+ if count < at_least {
+ return Err((Default::default(), input));
+ }
+ Ok((results, input))
+ }
+}
+
+pub struct SeparatedBy ,
+ delimiter: D,
+ allow_trailing: bool,
+}
+
+impl