use crate::{
error::{Error, ErrorKind},
parser::*,
};
#[derive(Clone)]
pub struct PMany<P> {
p: P,
at_least: usize,
at_most: usize,
}
pub fn pmany<P>(p: P, at_least: usize, at_most: usize) -> PMany<P> {
PMany {
p,
at_least,
at_most,
}
}
impl<P> PMany<P> {
pub fn at_least(mut self, n: usize) -> Self {
self.at_least = n;
self
}
pub fn at_most(mut self, n: usize) -> Self {
self.at_most = n;
self
}
}
impl<'a, K, O, P> ParserCore<'a, K, Vec<O>> for PMany<P>
where
K: PartialEq + Clone + 'a,
O: Clone + 'a,
P: Parser<'a, K, O>,
{
fn parse(&self, i: PInput<'a, K>) -> Result<PSuccess<'a, K, Vec<O>>, Error<'a, K>> {
let start = i.loc;
let mut vals: Vec<O> = vec![];
let mut input = i;
while let Ok(PSuccess { val, rest }) = self.p.parse(input.clone()) {
vals.push(val);
input = rest;
}
if vals.len() >= self.at_least && vals.len() <= self.at_most {
Ok(PSuccess {
val: vals,
rest: input,
})
} else {
Err(Error {
kind: vec![ErrorKind::Custom(format!(
"Expected {} elements, but found {} elements.",
if self.at_most == usize::MAX {
format!("at least {}", self.at_least)
} else {
format!("between {} and {}", self.at_least, self.at_most)
},
vals.len()
))],
span: (start, input.loc),
state: input,
})
}
}
}
impl<'a, K, O, P> Parser<'a, K, Vec<O>> for PMany<P>
where
K: PartialEq + Clone + 'a,
O: Clone + 'a,
P: Parser<'a, K, O>,
{
}