use crate::parse::*;
use formally_support::*;
pub trait Many<'c, Out: 'c>: Parse<'c, Out> {
fn skip(self) -> Parser<'c, ()> {
Parser::new(move |state: &mut State| {
loop {
let mut split = state.split();
match self.parse_from(&mut split) {
Ok(_) => split.commit(),
Err(_) if !split.has_advanced() => return Ok(()),
Err(err) => return Err(err),
}
}
})
}
fn sep_by_while_counting<S, E, F>(
self,
cond: F,
sep: Parser<'static, S>,
min: usize,
max: usize,
) -> Parser<'c, E>
where
E: 'c + Default + Extend<Out>,
F: 'c + Clone + Fn(&Out) -> bool,
S: 'c,
{
Parser::new(move |state: &mut State| {
let mut out = E::default();
let mut found = 0;
let mut elapsed = None;
let mut first = true;
loop {
let mut split = state.split();
if !first {
State::skip(&mut split);
match sep.parse_from(&mut split) {
Ok(_) => {}
Err(_) if split.has_advanced() => {
split.commit();
return Err(DiagnosticEmitted.into());
}
Err(_) => break,
}
}
first = false;
let mut split2 = split.split();
State::skip(&mut split2);
match self.parse_from(&mut split2) {
Ok(value) => {
if !cond(&value) {
elapsed = split.elapsed();
break;
}
out.extend(Some(value));
split2.commit();
split.commit();
found += 1;
if found == max {
break;
}
}
Err(_) if split2.has_advanced() => {
split2.commit();
split.commit();
return Err(DiagnosticEmitted.into());
}
Err(_) => break,
}
}
if found < min {
error!(
state,
elapsed,
SyntaxIssue::ManyButNotEnough {
min,
found,
name: self.name().clone(),
}
);
return Err(DiagnosticEmitted.into());
}
Ok(out)
})
}
fn sep_by_while<S, E, F>(self, cond: F, sep: Parser<'static, S>) -> Parser<'c, E>
where
E: 'c + Default + Extend<Out>,
F: 'c + Clone + Fn(&Out) -> bool,
S: 'c,
{
self.sep_by_while_counting(cond, sep, 0, usize::MAX)
}
fn sep_by<S, E>(self, sep: Parser<'static, S>) -> Parser<'c, E>
where
E: 'c + Default + Extend<Out>,
S: 'c,
{
self.sep_by_while(|_| true, sep)
}
fn sep_by1_while<S, E, F>(self, cond: F, sep: Parser<'static, S>) -> Parser<'c, E>
where
E: 'c + Default + Extend<Out>,
F: 'c + Clone + Fn(&Out) -> bool,
S: 'c,
{
self.sep_by_while_counting(cond, sep, 1, usize::MAX)
}
fn sep_by1<S, E>(self, sep: Parser<'static, S>) -> Parser<'c, E>
where
E: 'c + Default + Extend<Out>,
S: 'c,
{
self.sep_by1_while(|_| true, sep)
}
fn sep_by_n<S, E>(self, n: usize, sep: Parser<'static, S>) -> Parser<'c, E>
where
E: 'c + Default + Extend<Out>,
S: 'c,
{
self.sep_by_while_counting(|_| true, sep, n, n)
}
fn many_while_counting<E, F>(self, cond: F, min: usize, max: usize) -> Parser<'c, E>
where
E: 'c + Default + Extend<Out>,
F: 'c + Clone + Fn(&Out) -> bool,
{
self.sep_by_while_counting(cond, succeed(), min, max)
}
fn concat(self, p2: Parser<'c, Out>) -> Parser<'c, Out>
where
Out: Default + IntoIterator + Extend<<Out as IntoIterator>::Item>,
{
Parser::new(move |state: &mut State| {
let mut out = Out::default();
out.extend(self.parse_from(state)?);
out.extend(p2.parse_from(state)?);
Ok(out)
})
}
fn many_while<E, F>(self, cond: F) -> Parser<'c, E>
where
E: 'c + Default + Extend<Out>,
F: 'c + Clone + Fn(&Out) -> bool,
{
self.many_while_counting(cond, 0, usize::MAX)
}
fn many<E>(self) -> Parser<'c, E>
where
E: 'c + Default + Extend<Out>,
{
self.many_while(|_| true)
}
fn many1_while<E, F>(self, cond: F) -> Parser<'c, E>
where
E: 'c + Default + Extend<Out>,
F: 'c + Clone + Fn(&Out) -> bool,
{
self.many_while_counting(cond, 1, usize::MAX)
}
fn many1<E>(self) -> Parser<'c, E>
where
E: 'c + Default + Extend<Out>,
{
self.many1_while(|_| true)
}
fn many_counting<E>(self, min: usize, max: usize) -> Parser<'c, E>
where
E: 'c + Default + Extend<Out>,
{
self.many_while_counting(|_| true, min, max)
}
fn many_n<E>(self, n: usize) -> Parser<'c, E>
where
E: 'c + Default + Extend<Out>,
{
self.many_while_counting(|_| true, n, n)
}
fn once<E>(self) -> Parser<'c, E>
where
E: 'c + Default + Extend<Out>,
{
self.many_n(1)
}
}
impl<'c, Out: 'c, T: Parse<'c, Out>> Many<'c, Out> for T {}
pub trait ToVec<'c, Out>: Parse<'c, Vec<Out>> {
fn to_vec(self) -> Self {
self
}
}
impl<'c, Out: 'c, T: Parse<'c, Vec<Out>>> ToVec<'c, Out> for T {}
mod private {
#[derive(Default)]
pub struct SinkT {}
}
impl<A> Extend<A> for private::SinkT {
fn extend<T: IntoIterator<Item = A>>(&mut self, _iter: T) {}
}
pub trait Sink<'c>: Parse<'c, private::SinkT> {
fn sink(self) -> Parser<'c, ()> {
self.ignore()
}
}
impl<'c, T: Parse<'c, private::SinkT>> Sink<'c> for T {}
pub trait ToString<'c>: Parse<'c, String> {
fn to_string(self) -> Self {
self
}
}
impl<'c, T: Parse<'c, String>> ToString<'c> for T {}