use std::fmt::Debug;
use crate::{
parsers::{
and_p::{AndCombinator, AndThenParser, IdentityAndCombinator, KeepSecondOutputOnly},
map_p::{MapParser, TryMapParser},
or_p::OrThenParser,
},
type_alias::ParserRes,
};
pub trait Parser
where
Self: Sized,
{
type Output: Debug;
fn parse(&self, input: &str) -> ParserRes<Self::Output>;
fn parse_and_then_map<F, MappedOutput>(&self, input: &str, f: F) -> ParserRes<MappedOutput>
where
F: FnOnce(Self::Output) -> MappedOutput,
{
self.parse(input).map(|(a, rest)| (f(a), rest))
}
fn and_then<P>(self, other: P) -> AndThenParser<Self, P, IdentityAndCombinator>
where
P: Parser,
{
AndThenParser::from((self, other))
}
fn and_then_combine_with<P, C>(self, other: P, combinator: C) -> AndThenParser<Self, P, C>
where
P: Parser,
C: AndCombinator<Self::Output, P::Output>,
{
AndThenParser::from((self, other, combinator))
}
fn otherwise<P>(self, other: P) -> OrThenParser<Self, P>
where
P: Parser,
{
OrThenParser::from((self, other))
}
fn with_mapping<T>(self, mapping: &'_ dyn Fn(Self::Output) -> T) -> MapParser<Self, T> {
MapParser {
parser: self,
mapping,
}
}
fn with_try_mapping<T>(
self,
try_map: &'_ dyn Fn(Self::Output) -> Option<T>,
) -> TryMapParser<Self, T> {
TryMapParser {
parser: self,
try_map,
}
}
fn preceed<P>(self, other: P) -> AndThenParser<P, Self, KeepSecondOutputOnly>
where
P: Parser,
{
AndThenParser::from((other, self, KeepSecondOutputOnly))
}
}