use crate::types::ParserOutput;
use crate::{ParseContext, Reported, Result};
pub trait Parser {
type Output;
type RawOutput: ParserOutput<UserType = Self::Output>;
type Iter<'parse>: ParseIter<'parse, RawOutput = Self::RawOutput>
where
Self: 'parse;
fn parse(&self, s: &str) -> Result<Self::Output> {
self.parse_raw(s).map(|v| v.into_user_type())
}
fn parse_iter<'parse>(
&'parse self,
context: &mut ParseContext<'parse>,
start: usize,
) -> Result<Self::Iter<'parse>, Reported>;
fn parse_raw(&self, s: &str) -> Result<Self::RawOutput> {
let mut ctx = ParseContext::new(s);
let mut it = match self.parse_iter(&mut ctx, 0) {
Ok(iter) => iter,
Err(Reported) => return Err(ctx.into_reported_error()),
};
while it.match_end() != s.len() {
ctx.error_extra(it.match_end());
if it.backtrack(&mut ctx).is_err() {
return Err(ctx.into_reported_error());
}
}
Ok(it.convert())
}
}
pub trait ParseIter<'parse> {
type RawOutput;
fn match_end(&self) -> usize;
fn backtrack(&mut self, context: &mut ParseContext<'parse>) -> Result<(), Reported>;
fn convert(&self) -> Self::RawOutput;
}
impl<'a, P> Parser for &'a P
where
P: Parser + ?Sized,
{
type Output = P::Output;
type RawOutput = P::RawOutput;
type Iter<'parse> = P::Iter<'parse>
where
P: 'parse,
'a: 'parse;
fn parse_iter<'parse>(
&'parse self,
context: &mut ParseContext<'parse>,
start: usize,
) -> Result<Self::Iter<'parse>, Reported> {
<P as Parser>::parse_iter(self, context, start)
}
}