use std::{borrow::Cow, ops::Deref, sync::LazyLock};
use crate::{
Container, FileId, NoAllocContainer, ParserInput, ParserResult, ParsingError, parsers::*,
};
pub trait Parser<T> {
fn parse_inner(&self, input: &mut ParserInput) -> ParserResult<T>;
}
pub trait ParserNonConstUtils<T>: Parser<T> {
fn parse(&self, input: &mut ParserInput) -> ParserResult<T> {
let mut input_copy = *input;
let result = self.parse_inner(&mut input_copy);
result.inspect(|span| input.advance(span.at))
}
fn parse_str(&self, str: &str) -> ParserResult<T> {
self.parse_str_with_file_id(str, FileId::None)
}
fn parse_str_with_file_id(&self, str: &str, file_id: FileId) -> ParserResult<T> {
self.parse(&mut ParserInput::new(str, file_id))
}
fn erase_type(self) -> Box<dyn Parser<T> + Send + Sync>
where
Self: Sized + Send + Sync + 'static,
{
Box::new(self)
}
}
pub const trait ParserConstUtils<T>: Parser<T> {
fn then<U, P: Parser<U>>(self, other: P) -> Then<T, Self, U, P>
where
Self: Sized,
{
Then::new(self, other)
}
fn then_ignore<U, P: Parser<U>>(self, other: P) -> ThenIgnore<T, Self, U, P>
where
Self: Sized,
{
ThenIgnore::new(self, other)
}
fn ignore_then<U, P: Parser<U>>(self, other: P) -> IgnoreThen<T, Self, U, P>
where
Self: Sized,
{
IgnoreThen::new(self, other)
}
fn followed_by<U, P: Parser<U>>(self, other: P) -> FollowedBy<T, Self, U, P>
where
Self: Sized,
{
FollowedBy::new(self, other)
}
fn not_followed_by<U, P: Parser<U>>(self, other: P) -> NotFollowedBy<T, Self, U, P>
where
Self: Sized,
{
NotFollowedBy::new(self, other)
}
fn repeated(self) -> Repeated<T, Self, NoAllocContainer>
where
Self: Sized,
{
Repeated::new(self)
}
fn repeated_into_vec(self) -> Repeated<T, Self, Vec<T>>
where
Self: Sized,
{
Repeated::new(self)
}
fn repeated_into_container<C: Container<T>>(self) -> Repeated<T, Self, C>
where
Self: Sized,
{
Repeated::new(self)
}
fn or_not(self) -> OrNot<T, Self>
where
Self: Sized,
{
OrNot::new(self)
}
fn map<U, F: Fn(T) -> U>(self, mapper: F) -> Map<T, Self, U, F>
where
Self: Sized,
{
Map::new(self, mapper)
}
fn map_consumed_str<U, F: Fn(&str) -> U>(self, mapper: F) -> MapConsumedStr<T, Self, U, F>
where
Self: Sized,
{
MapConsumedStr::new(self, mapper)
}
fn and_then<U, F: Fn(T) -> Result<U, ParsingError>>(self, mapper: F) -> AndThen<T, Self, U, F>
where
Self: Sized,
{
AndThen::new(self, mapper)
}
fn and_then_or_critical<U, F: Fn(T) -> Result<U, Cow<'static, str>>>(
self,
mapper: F,
) -> AndThenOrCritical<T, Self, U, F>
where
Self: Sized,
{
AndThenOrCritical::new(self, mapper)
}
fn spanned(self) -> Spanned<T, Self>
where
Self: Sized,
{
Spanned::new(self)
}
fn collect<C>(self) -> Map<T, Self, C, fn(T) -> C>
where
Self: Sized,
T: IntoIterator,
C: FromIterator<T::Item>,
{
self.map(C::from_iter)
}
fn collect_string(self) -> CollectString<T, Self>
where
Self: Sized,
{
CollectString::new(self)
}
fn atomic_err(self, message: &'static str) -> AtomicErr<T, Self>
where
Self: Sized,
{
AtomicErr::new(self, message)
}
fn critical(self, message: &'static str) -> Critical<T, Self>
where
Self: Sized,
{
Critical::new(self, Some(message))
}
fn critical_auto_msg(self) -> Critical<T, Self>
where
Self: Sized,
{
Critical::new(self, None)
}
fn silenced(self) -> Silenced<T, Self>
where
Self: Sized,
{
Silenced::new(self)
}
fn padded_by<P, PP: Parser<P>>(self, padding: PP) -> PaddedBy<T, Self, P, PP>
where
Self: Sized,
{
PaddedBy::new(self, padding)
}
fn surrounded_by<L, LP: Parser<L>, R, RP: Parser<R>>(
self,
left: LP,
right: RP,
) -> SurroundedBy<L, LP, T, Self, R, RP>
where
Self: Sized,
{
SurroundedBy::new(left, self, right)
}
fn separated_by<S, P: Parser<S>>(self, sep: P) -> SeparatedBy<T, Self, S, P, NoAllocContainer>
where
Self: Sized,
{
SeparatedBy::new(self, sep)
}
fn separated_by_into_vec<S, P: Parser<S>>(self, sep: P) -> SeparatedBy<T, Self, S, P, Vec<T>>
where
Self: Sized,
{
SeparatedBy::new(self, sep)
}
fn separated_by_into_container<C: Container<T>, S, P: Parser<S>>(
self,
sep: P,
) -> SeparatedBy<T, Self, S, P, C>
where
Self: Sized,
{
SeparatedBy::new(self, sep)
}
fn flattened<U, S>(self) -> Flattened<U, S, T, Self, NoAllocContainer>
where
Self: Sized,
T: IntoIterator<Item = S>,
S: IntoIterator<Item = U>,
{
Flattened::new(self)
}
fn flatten_into_vec<U, S>(self) -> Flattened<U, S, T, Self, Vec<U>>
where
Self: Sized,
T: IntoIterator<Item = S>,
S: IntoIterator<Item = U>,
{
Flattened::new(self)
}
fn flatten_into_container<U, S, C: Container<U>>(self) -> Flattened<U, S, T, Self, C>
where
Self: Sized,
T: IntoIterator<Item = S>,
S: IntoIterator<Item = U>,
{
Flattened::new(self)
}
fn to<U: Copy>(self, data: U) -> To<T, Self, U>
where
Self: Sized,
{
To::new(self, data)
}
fn full(self) -> Full<T, Self>
where
Self: Sized,
{
Full::new(self)
}
fn or<P: Parser<T>>(self, other: P) -> Choice<(Self, P), T>
where
Self: Sized,
{
Choice::<(Self, P), T>::new((self, other))
}
fn validate<F: Fn(&T) -> bool>(self, validator: F) -> Validate<T, Self, F>
where
Self: Sized,
{
Validate::new(self, validator)
}
fn validate_or_critical<F: Fn(&T) -> bool>(
self,
validator: F,
message: &'static str,
) -> ValidateOrCriticalMsg<T, Self, F>
where
Self: Sized,
{
ValidateOrCriticalMsg::new(self, validator, message)
}
fn validate_or_dynamic_critical<F: Fn(&T) -> Result<(), Cow<'static, str>>>(
self,
validator: F,
) -> ValidateOrDynamicCriticalMsg<T, Self, F>
where
Self: Sized,
{
ValidateOrDynamicCriticalMsg::new(self, validator)
}
fn debug<F: for<'a, 'b> Fn(DebugType<'a, 'b, T>)>(self, debugger: F) -> Debugging<T, Self, F>
where
Self: Sized,
{
Debugging::new(self, debugger)
}
fn static_ref(&'static self) -> StaticRef<T, Self>
where
Self: Sized,
{
StaticRef::new(self)
}
}
impl<T, P: Parser<T>> const ParserConstUtils<T> for P {}
impl<T, P: Parser<T>> ParserNonConstUtils<T> for P {}
impl<T, P: Parser<T> + ?Sized> Parser<T> for Box<P> {
fn parse_inner(&self, input: &mut ParserInput) -> ParserResult<T> {
self.deref().parse_inner(input)
}
}
impl<T, P: Parser<T>> Parser<T> for LazyLock<P> {
fn parse_inner(&self, input: &mut ParserInput) -> ParserResult<T> {
self.deref().parse_inner(input)
}
}