use crate::{combinators::{bind, filter, into_type, left, map, map_if, right}, slicelike::SliceLike};
pub struct AnpaState<'a, I: SliceLike, S> {
pub input: I,
pub user_state: &'a mut S,
}
pub struct AnpaStateOwned<I: SliceLike, S> {
pub input: I,
pub user_state: S,
}
pub struct AnpaResult<T, O> {
pub state: T,
pub result: Option<O>
}
pub trait Parser<I: ?Sized, O = I, S = ()>: FnOnce(&mut AnpaState<I, S>) -> Option<O> + Copy {}
create_parser_trait!(StrParser, str, "Convenience alias for a parser that parses a `&'a str`.");
create_parser_trait!(U8Parser, [u8], "Convenience alias for a parser that parses a `&'a [u8]`.");
impl<I, O, S, F: FnOnce(&mut AnpaState<I, S>) -> Option<O> + Copy> Parser<I, O, S> for F {}
pub trait ParserExt<I: SliceLike, O, S>: Parser<I, O, S> {
fn map<O2>(self, f: impl FnOnce(O) -> O2 + Copy) -> impl Parser<I, O2, S>;
fn map_if<O2>(self, f: impl FnOnce(O) -> Option<O2> + Copy) -> impl Parser<I, O2, S>;
fn filter(self, f: impl FnOnce(&O) -> bool + Copy) -> impl Parser<I, O, S>;
fn bind<O2, P: Parser<I, O2, S>>(self, f: impl FnOnce(O) -> P + Copy) -> impl Parser<I, O2, S>;
fn right<O2, P: Parser<I, O2, S>>(self, p: P) -> impl Parser<I, O2, S>;
fn left<O2, P: Parser<I, O2, S>>(self, p: P) -> impl Parser<I, O, S>;
fn parse_state(self, input: I, user_state: &'_ mut S) -> AnpaResult<AnpaState<'_, I, S>, O>;
fn parse_state_owned(self, input: I, user_state: S) -> AnpaResult<AnpaStateOwned<I, S>, O>;
#[cfg(feature = "std")]
fn debug(self, name: &'static str) -> impl Parser<I, O, S>;
}
pub trait ParserExtNoState<I: SliceLike, O>: Parser<I, O, ()> {
fn parse(self, input: I) -> AnpaResult<I, O>;
}
impl<I: SliceLike, O, P: Parser<I, O, ()>> ParserExtNoState<I, O> for P {
#[inline(always)]
fn parse(self, input: I) -> AnpaResult<I, O> {
parse(self, input)
}
}
pub trait ParserExtDefaultState<I: SliceLike, O, S: Default>: Parser<I, O, S> {
fn parse_default(self, input: I) -> AnpaResult<AnpaStateOwned<I, S>, O>;
}
impl<I: SliceLike, O, S: Default, P: Parser<I, O, S>> ParserExtDefaultState<I, O, S> for P {
#[inline(always)]
fn parse_default(self, input: I) -> AnpaResult<AnpaStateOwned<I, S>, O> {
parse_default(self, input)
}
}
pub trait ParserInto<I, O1: Into<O2>, O2, S>: Parser<I, O1, S> {
fn into_type(self) -> impl Parser<I, O2, S>;
}
impl<I: SliceLike, O1: Into<O2>, O2, S, P: Parser<I, O1, S>> ParserInto<I, O1, O2, S> for P {
#[inline(always)]
fn into_type(self) -> impl Parser<I, O2, S> {
into_type(self)
}
}
impl<I: SliceLike, O, S, P: Parser<I, O, S>> ParserExt<I, O ,S> for P {
#[inline(always)]
fn map<O2>(self, f: impl FnOnce(O) -> O2 + Copy) -> impl Parser<I, O2, S> {
map(self, f)
}
#[inline(always)]
fn map_if<O2>(self, f: impl FnOnce(O) -> Option<O2> + Copy) -> impl Parser<I, O2, S> {
map_if(self, f)
}
#[inline(always)]
fn filter(self, f: impl FnOnce(&O) -> bool + Copy) -> impl Parser<I, O, S> {
filter(self, f)
}
#[inline(always)]
fn bind<O2, P2: Parser<I, O2, S>>(self, f: impl FnOnce(O) -> P2 + Copy) -> impl Parser<I, O2, S> {
bind(self, f)
}
#[inline(always)]
fn right<O2, P2: Parser<I, O2, S>>(self, p: P2) -> impl Parser<I, O2, S> {
right(self, p)
}
#[inline(always)]
fn left<O2, P2: Parser<I, O2, S>>(self, p: P2) -> impl Parser<I, O, S> {
left(self, p)
}
#[inline(always)]
fn parse_state(self, input: I, user_state: &'_ mut S) -> AnpaResult<AnpaState<'_, I, S>, O> {
parse_state(self, input, user_state)
}
#[inline(always)]
fn parse_state_owned(self, input: I, user_state: S) -> AnpaResult<AnpaStateOwned<I, S>, O> {
parse_state_owned(self, input, user_state)
}
#[cfg(feature = "std")]
fn debug(self, name: &'static str) -> impl Parser<I, O, S> {
use std::println;
create_parser!(s, {
let res = self(s);
match res {
Some(_) => println!("{name}: Succeeded"),
None => println!("{name}: Failed"),
}
res
})
}
}
#[inline]
pub fn parse_state<I: SliceLike, O, S>(p: impl Parser<I, O, S>,
input: I,
user_state: &'_ mut S) -> AnpaResult<AnpaState<'_, I, S>, O> {
let mut parser_state = AnpaState { input, user_state };
let result = p(&mut parser_state);
AnpaResult { state: parser_state, result }
}
#[inline]
pub fn parse_state_owned<I: SliceLike, O, S>(p: impl Parser<I, O, S>,
input: I,
mut user_state: S) -> AnpaResult<AnpaStateOwned<I, S>, O> {
let mut parser_state = AnpaState { input, user_state: &mut user_state };
let result = p(&mut parser_state);
AnpaResult { state: AnpaStateOwned { input: parser_state.input, user_state }, result }
}
#[inline(always)]
pub fn parse_default<I: SliceLike, O, S: Default>(p: impl Parser<I, O, S>,
input: I) -> AnpaResult<AnpaStateOwned<I, S>, O> {
parse_state_owned(p, input, S::default())
}
#[inline]
pub fn parse<I: SliceLike, O>(p: impl Parser<I, O, ()>,
input: I) -> AnpaResult<I, O> {
let mut parser_state = AnpaState { input, user_state: &mut () };
let result = p(&mut parser_state);
AnpaResult { state: parser_state.input, result }
}