use crate::{
error::{Error, ErrorDisplay},
parser::{
and::PAnd, between::PBetween, bind::PBind, debug::PDebug, delim::PDelim,
fold_left::PFoldLeft, ignore_then::PIgnoreThen, into::PInto, many::PMany,
map_error::PMapError, map_with_span::PMapWithSpan, not::PNot, or::POr, padded::PPaddedBy,
seq::PSeq, then_ignore::PThenIgnore, until_end::PUntilEnd,
},
prelude::{
debug, pand, pbetween, pbind, pdelim, pfoldl, pignore_then, pinto, pmany, pmap_error,
pmap_with_span, pnot, por, ppadded, pseq, pthen_ignore, puntil_end,
},
};
pub type Span = (usize, usize);
#[derive(Clone, Debug)]
pub struct PInput<'a, T: PartialEq + Clone + 'a> {
pub tokens: &'a [T],
pub loc: usize,
}
#[derive(Clone)]
pub struct PSuccess<'a, T, O>
where
T: PartialEq + Clone,
{
pub val: O,
pub rest: PInput<'a, T>,
}
pub trait ParserCore<'a, K, O>
where
K: PartialEq + Clone + 'a,
{
fn parse(&self, i: PInput<'a, K>) -> Result<PSuccess<'a, K, O>, Error<'a, K>>;
}
pub trait Parser<'a, K: PartialEq + Clone + 'a, O: Clone + 'a>:
ParserCore<'a, K, O> + Sized + Clone
{
fn then<P2, O2>(self, p2: P2) -> PSeq<Self, P2>
where
O2: Clone + 'a,
P2: Parser<'a, K, O2>,
{
pseq(self, p2)
}
fn or<P2>(self, p2: P2) -> POr<Self, P2>
where
P2: Parser<'a, K, O>,
{
por(self, p2)
}
fn map<O2, F>(self, f: F) -> PBind<Self, O, O2>
where
F: Fn(O) -> O2 + 'static,
O2: Clone + 'a,
{
pbind(self, f)
}
fn between<A, P1, P2>(self, l: P1, r: P2) -> PBetween<P1, Self, P2, A>
where
A: Clone + 'a,
P1: Parser<'a, K, A>,
P2: Parser<'a, K, A>,
{
pbetween(l, self, r)
}
fn many(self) -> PMany<Self> {
pmany(self, 0, usize::MAX)
}
fn many1(self) -> PMany<Self> {
pmany(self, 1, usize::MAX)
}
fn delimited_by<PD, A>(self, delim: PD) -> PDelim<Self, PD, A>
where
A: Clone + 'a,
PD: Parser<'a, K, A>,
{
pdelim(self, delim, 0, usize::MAX, true)
}
fn delimited_by1<PD, A>(self, delim: PD) -> PDelim<Self, PD, A>
where
A: Clone + 'a,
PD: Parser<'a, K, A>,
{
pdelim(self, delim, 1, usize::MAX, true)
}
fn not(self) -> PNot<Self, O> {
pnot(self)
}
fn padded_by<PD, A>(self, pad: PD) -> PPaddedBy<Self, PD, A>
where
A: Clone + 'a,
PD: Parser<'a, K, A> + Clone,
{
ppadded(self, pad)
}
fn into_<Out>(self, out: Out) -> PInto<Self, O, Out, K>
where
Out: PartialEq + Clone + 'a,
{
pinto(self, out)
}
fn debug(self, label: &'static str) -> PDebug<Self>
where
K: ErrorDisplay,
{
debug(self, label)
}
fn and<P2, A>(self, second: P2) -> PAnd<Self, P2, A>
where
A: Clone + 'a,
P2: Parser<'a, K, A>,
{
pand(self, second)
}
fn until_end(self) -> PUntilEnd<Self, K> {
puntil_end(self)
}
fn foldl<TP, F, I, O2>(self, tail: TP, f: F) -> PFoldLeft<Self, TP, F, I, O2>
where
O2: Clone + 'a,
I: IntoIterator<Item = O2> + Clone + 'a,
TP: Parser<'a, K, I>,
F: Fn(O, O2) -> O + Clone + 'a,
{
pfoldl(self, tail, f)
}
fn ignore_then<P2, OO>(self, then: P2) -> PIgnoreThen<Self, P2, O>
where
OO: Clone + 'a,
P2: Parser<'a, K, OO>,
{
pignore_then(self, then)
}
fn then_ignore<P2, OI>(self, ignore: P2) -> PThenIgnore<Self, P2, OI>
where
OI: Clone + 'a,
P2: Parser<'a, K, OI>,
{
pthen_ignore(self, ignore)
}
fn map_with_span<F, O2>(self, f: F) -> PMapWithSpan<Self, O, O2>
where
F: Fn(O, Span) -> O2 + 'static,
O2: Clone + 'a,
{
pmap_with_span(self, f)
}
fn map_error<F>(self, f: F) -> PMapError<'a, K, Self>
where
F: Fn(Error<'a, K>) -> Error<'a, K> + 'static,
{
pmap_error(self, f)
}
}