use crate::prelude::{
debug, pand, pbetween, pbind, pdelim, pinto, pmany, pnot, por, ppadded, pseq,
};
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 struct PFail<'a, T>
where
T: PartialEq + Clone,
{
pub error: Vec<String>,
pub span: Vec<Span>,
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>, PFail<'a, K>>;
}
pub trait Parser<'a, K: PartialEq + Clone + 'a, O: 'a>: ParserCore<'a, K, O> + Sized {
fn then<O2, T>(self, p2: T) -> impl Parser<'a, K, (O, O2)>
where
T: Parser<'a, K, O2>,
O2: 'a,
{
pseq(self, p2)
}
fn or<T>(self, p2: T) -> impl Parser<'a, K, O>
where
T: Parser<'a, K, O>,
{
por(self, p2)
}
fn map<O2, F>(self, f: F) -> impl Parser<'a, K, O2>
where
F: Fn(O) -> O2 + 'static,
O2: 'a,
{
pbind(self, f)
}
fn between<A, P1, P2>(self, l: P1, r: P2) -> impl Parser<'a, K, O>
where
A: 'a,
P1: Parser<'a, K, A>,
P2: Parser<'a, K, A>,
{
pbetween(l, self, r)
}
fn many(self) -> impl Parser<'a, K, Vec<O>> {
pmany(self)
}
fn delimited_by<PD, A>(self, delim: PD) -> impl Parser<'a, K, Vec<O>>
where
A: 'a,
PD: Parser<'a, K, A>,
{
pdelim(self, delim)
}
fn not(self) -> impl Parser<'a, K, ()> {
pnot(self)
}
fn padded_by<P, A>(self, pad: P) -> impl Parser<'a, K, O>
where
A: 'a,
P: Parser<'a, K, A> + Clone,
{
ppadded(self, pad)
}
fn into_<Out>(self, out: Out) -> impl Parser<'a, K, Out>
where
Out: PartialEq + Clone + 'a,
{
pinto(self, out)
}
fn debug(self, label: &'static str) -> impl Parser<'a, K, O> {
debug(self, label)
}
fn and<P2, A>(self, second: P2) -> impl Parser<'a, K, O>
where
A: 'a,
P2: Parser<'a, K, A>,
{
pand(self, second)
}
}