use crate::location::{Meta, Span};
use crate::parse::{list::List, Concat, ParseResult, Parser};
use crate::parsers::{empty, space, value};
use std::iter::FromIterator;
use std::marker::PhantomData;
use std::ops::{Bound, RangeBounds};
pub trait ParserExt<T, E>: Parser<T, E> + Sized {
fn or<P: Parser<T, E>>(self, other: P) -> Or<Self, P, E> {
Or(self, other, PhantomData)
}
fn map<V, F: Fn(T) -> V>(self, map: F) -> Map<Self, F, T, E> {
Map(self, map, PhantomData)
}
fn and_then<V, Q: Parser<V, E>, F: Fn(T) -> Q>(self, map: F) -> AndThen<Self, F, T, E> {
AndThen(self, map, PhantomData)
}
fn fold<P: Parser<T, E>, F: Fn(T) -> P>(self, fold: F) -> Fold<Self, F, E> {
Fold(self, fold, PhantomData)
}
fn on_failure<P: Parser<T, E>>(self, other: P) -> OnFailure<Self, P, E> {
OnFailure(self, other, PhantomData)
}
fn on_none<P: Parser<T, E>>(self, other: P) -> OnNone<Self, P, E> {
OnNone(self, other, PhantomData)
}
fn drop<V, P: Parser<V, E>>(self, other: P) -> Drop<Self, P, V, E> {
Drop(self, other, PhantomData)
}
fn maybe_drop<V, P: Parser<V, E>>(self, other: P) -> MaybeDrop<Self, P, V, E> {
MaybeDrop(self, other, PhantomData)
}
fn skip<V, P: Parser<V, E>>(self, keep: P) -> Skip<Self, P, T, E> {
Skip(self, keep, PhantomData)
}
fn condition<F: Fn(&T) -> bool>(self, condition: F) -> Condition<Self, F, E> {
Condition(self, condition, PhantomData)
}
fn end(self) -> End<Self, E> {
End(self, PhantomData)
}
fn catch(self) -> Catch<Self, E> {
Catch(self, PhantomData)
}
fn meta(self) -> MetaMap<Self, E> {
MetaMap(self, PhantomData)
}
fn to_list(self) -> ListMap<Self, E> {
ListMap(self, PhantomData)
}
fn delimited_by<D, P: Parser<D, E>, R: RangeBounds<usize>>(
self,
delimiter: P,
repetitions: R,
) -> DelimitedBy<Self, P, D, R, E> {
DelimitedBy(self, delimiter, repetitions, PhantomData)
}
fn strictly_delimited_by<D, P: Parser<D, E>, R: RangeBounds<usize>>(
self,
delimiter: P,
repetitions: R,
) -> StrictlyDelimitedBy<Self, P, D, R, E> {
StrictlyDelimitedBy(self, delimiter, repetitions, PhantomData)
}
fn surrounded_by<O: Clone, C: Clone, OP: Parser<O, E>, CP: Parser<C, E>>(
self,
open: OP,
close: CP,
) -> SurroundedBy<Self, OP, CP, O, C, E> {
SurroundedBy(self, open, close, PhantomData)
}
fn pair<B, P: Parser<B, E>>(self, other: P) -> Pair<Self, P, E> {
Pair(self, other, PhantomData)
}
fn space_after(self) -> SpaceAfter<Self, E> {
SpaceAfter(self, PhantomData)
}
fn maybe_space_after(self) -> MaybeSpaceAfter<Self, E> {
MaybeSpaceAfter(self, PhantomData)
}
fn space_before(self) -> SpaceBefore<Self, E> {
SpaceBefore(self, PhantomData)
}
fn maybe_space_before(self) -> MaybeSpaceBefore<Self, E> {
MaybeSpaceBefore(self, PhantomData)
}
fn space_around(self) -> SpaceAround<Self, E> {
SpaceAround(self, PhantomData)
}
fn maybe_space_around(self) -> MaybeSpaceAround<Self, E> {
MaybeSpaceAround(self, PhantomData)
}
}
impl<T, E, P: Parser<T, E>> ParserExt<T, E> for P {}
pub trait ConcatParserExt<T: Concat + Clone, E>: Parser<T, E> + Sized {
fn multiple(self) -> Multiple<Self, E> {
Multiple(self, PhantomData)
}
fn maybe(self) -> Maybe<Self, E> {
Maybe(self, PhantomData)
}
fn and<P: Parser<T, E>>(self, other: P) -> And<Self, P, E> {
And(self, other, PhantomData)
}
fn repeated<R: RangeBounds<usize> + Clone>(self, repetitions: R) -> Repeat<Self, R, E> {
Repeat(self, repetitions, PhantomData)
}
}
impl<T: Concat + Clone, E, P: Parser<T, E>> ConcatParserExt<T, E> for P {}
pub trait ListParserExt<T, E>: Parser<List<T>, E> + Sized {
fn collect<I: FromIterator<T>>(self) -> Collect<Self, T, I, E> {
Collect(self, PhantomData)
}
}
impl<T, E, P: Parser<List<T>, E>> ListParserExt<T, E> for P {}
pub trait BoxedParserExt<'p, T, E>: Parser<T, E> + Sized + 'p {
fn boxed(self) -> Boxed<dyn Parser<T, E> + 'p> {
Boxed::new(self)
}
fn ref_parser(&'p self) -> Referenced<'p, Self, E> {
Referenced(self, PhantomData)
}
}
impl<'p, T: 'p, E: 'p, P: Parser<T, E> + 'p> BoxedParserExt<'p, T, E> for P {}
pub trait TextParserExt<E>: Parser<Span, E> + Sized {
fn copy_string(self) -> StringMap<Self, E> {
StringMap(self, PhantomData)
}
fn str_condition<F: Fn(&str) -> bool>(self, f: F) -> StrCondition<Self, F, E> {
StrCondition(self, f, PhantomData)
}
}
impl<E, P: Parser<Span, E>> TextParserExt<E> for P {}
pub struct Multiple<P, E>(P, PhantomData<E>);
impl<T: Concat + Clone, E, P: Parser<T, E>> Parser<T, E> for Multiple<P, E> {
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
self.0
.parse(source, location)
.and_then(&|parsed, source, mut location| {
self.parse(source, location.take())
.map(&|tail| parsed.clone().concat(tail))
.or(ParseResult::success(parsed, source, location))
})
}
}
pub struct Repeat<P, R, E>(P, R, PhantomData<E>);
#[derive(Clone)]
struct Counter<P>(P, usize);
impl<P: Concat> Concat for Counter<P> {
fn empty() -> Self {
Counter(P::empty(), 0)
}
fn empty_at(location: Span) -> Self {
Counter(P::empty_at(location), 0)
}
fn concat(self, other: Self) -> Self {
Counter(self.0.concat(other.0), self.1 + other.1)
}
}
impl<T: Concat + Clone, E, R: RangeBounds<usize>, P: Parser<T, E>> Parser<T, E>
for Repeat<P, R, E>
{
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
self.0
.ref_parser()
.map(|parsed| Counter(parsed, 1))
.multiple()
.maybe()
.parse(source, location)
.and_then(&|Counter(parsed, length), source, location| {
let long_enough = match self.1.start_bound() {
Bound::Included(minimum) if length < *minimum => ParseResult::none(location),
Bound::Excluded(minimum) if length <= *minimum => ParseResult::none(location),
_ => ParseResult::success(parsed.clone(), source, location),
};
match self.1.end_bound() {
Bound::Included(maximum) if length > *maximum => ParseResult::none(location),
Bound::Excluded(maximum) if length >= *maximum => ParseResult::none(location),
_ => long_enough,
}
})
}
}
pub struct Maybe<P, E>(P, PhantomData<E>);
impl<T: Concat, E, P: Parser<T, E>> Parser<T, E> for Maybe<P, E> {
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
self.0
.parse(source, location.clone())
.or(empty(source, location))
}
}
pub struct Condition<P, F, E>(P, F, PhantomData<E>);
impl<T, E, P: Parser<T, E>, F: Fn(&T) -> bool> Parser<T, E> for Condition<P, F, E> {
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
self.0
.parse(source, location)
.and_then(&|parsed, source, location| {
if self.1(&parsed) {
ParseResult::success(parsed, source, location)
} else {
ParseResult::none(location)
}
})
}
}
pub struct Matching<P, F, E>(P, F, PhantomData<E>);
impl<T: PartialEq<V>, V, E, P: Parser<T, E>> Parser<T, E> for Matching<P, V, E> {
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
self.0
.parse(source, location)
.and_then(&|parsed, source, location| {
if parsed == self.1 {
ParseResult::success(parsed, source, location)
} else {
ParseResult::none(location)
}
})
}
}
pub struct Or<A, B, E>(A, B, PhantomData<E>);
impl<A, B, T: Clone, E> Parser<T, E> for Or<A, B, E>
where
A: Parser<T, E>,
B: Parser<T, E>,
{
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
self.0
.parse(source, location.clone())
.or(self.1.parse(source, location))
}
}
pub struct And<A, B, E>(A, B, PhantomData<E>);
impl<A, B, T, E> Parser<T, E> for And<A, B, E>
where
T: Concat + Clone,
A: Parser<T, E>,
B: Parser<T, E>,
{
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
self.0
.parse(source, location)
.and_then(&|prefix, source, location| {
self.1
.parse(source, location)
.map(&|suffix| prefix.clone().concat(suffix))
})
}
}
pub struct Map<P, F, T, E>(P, F, PhantomData<(T, E)>);
impl<P, F, T, E, V> Parser<V, E> for Map<P, F, T, E>
where
P: Parser<T, E>,
F: Fn(T) -> V,
{
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, V, E> {
self.0.parse(source, location).map(&self.1)
}
}
pub struct AndThen<P, F, T, E>(P, F, PhantomData<(T, E)>);
impl<P, F, T, E, Q, V> Parser<V, E> for AndThen<P, F, T, E>
where
P: Parser<T, E>,
Q: Parser<V, E>,
F: Fn(T) -> Q,
{
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, V, E> {
self.0
.parse(source, location)
.and_then(&|value, source, location| (self.1)(value).parse(source, location))
}
}
pub struct Fold<P, F, E>(P, F, PhantomData<E>);
impl<P, F, T, E, Q> Parser<T, E> for Fold<P, F, E>
where
T: Clone,
P: Parser<T, E>,
Q: Parser<T, E>,
F: Fn(T) -> Q + Clone,
{
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
self.0
.ref_parser()
.and_then(|parsed| {
(self.1)(parsed.clone())
.fold(self.1.clone())
.or(value(parsed))
})
.parse(source, location)
}
}
pub struct OnFailure<A, B, E>(A, B, PhantomData<E>);
impl<A, B, T: Clone, E> Parser<T, E> for OnFailure<A, B, E>
where
A: Parser<T, E>,
B: Parser<T, E>,
{
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
let parse = self.0.parse(source, location.clone());
if parse.is_success() {
parse
} else {
parse.or(self.1.parse(source, location))
}
}
}
pub struct OnNone<A, B, E>(A, B, PhantomData<E>);
impl<A, B, T: Clone, E> Parser<T, E> for OnNone<A, B, E>
where
A: Parser<T, E>,
B: Parser<T, E>,
{
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
let parse = self.0.parse(source, location.clone());
if parse.is_none() {
parse.or(self.1.parse(source, location))
} else {
parse
}
}
}
pub struct Drop<A, B, V, E>(A, B, PhantomData<(V, E)>);
impl<A, B, T: Clone, V, E> Parser<T, E> for Drop<A, B, V, E>
where
A: Parser<T, E>,
B: Parser<V, E>,
{
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
self.0
.parse(source, location)
.and_then(&|keep, source, location| {
self.1.parse(source, location).map(&|_| keep.clone())
})
}
}
pub struct MaybeDrop<A, B, V, E>(A, B, PhantomData<(V, E)>);
impl<A, B, T: Clone, V, E> Parser<T, E> for MaybeDrop<A, B, V, E>
where
A: Parser<T, E>,
B: Parser<V, E>,
{
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
self.0
.parse(source, location)
.and_then(&|keep, source, location| {
self.1
.parse(source, location)
.map(&|_| keep.clone())
.or(ParseResult::success(keep, source, location))
})
}
}
pub struct Skip<P, Q, T, E>(P, Q, PhantomData<(T, E)>);
impl<P, Q, T, V, E> Parser<V, E> for Skip<P, Q, T, E>
where
P: Parser<T, E>,
Q: Parser<V, E>,
{
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, V, E> {
self.0
.parse(source, location)
.and_then(&|_, source, location| self.1.parse(source, location))
}
}
pub struct Boxed<P: ?Sized>(Box<P>);
impl<'p, T, E> Boxed<dyn Parser<T, E> + 'p> {
pub(crate) fn new<P: Parser<T, E> + 'p>(parser: P) -> Self {
let boxed: Box<dyn Parser<T, E> + 'p> = Box::new(parser);
Boxed(boxed)
}
}
impl<'p, T, E> Parser<T, E> for Boxed<dyn Parser<T, E> + 'p> {
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
self.0.parse(source, location)
}
}
pub struct Referenced<'p, P, E>(&'p P, PhantomData<E>);
impl<'p, T, E, P: Parser<T, E>> Parser<T, E> for Referenced<'p, P, E> {
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
self.0.parse(source, location)
}
}
pub struct End<P, E>(P, PhantomData<E>);
impl<T, E, P: Parser<T, E>> Parser<T, E> for End<P, E> {
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
self.0
.parse(source, location)
.and_then(&|value, source, location| {
if source.len() == 0 {
ParseResult::success(value, source, location)
} else {
ParseResult::none(location)
}
})
}
}
pub struct Catch<P, E>(P, PhantomData<E>);
impl<T, E, P: Parser<T, E>> Parser<T, E> for Catch<P, E> {
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
self.0.parse(source, location).catch()
}
}
pub struct MetaMap<P, E>(P, PhantomData<E>);
impl<T, E, P: Parser<T, E>> Parser<Meta<T, Span>, E> for MetaMap<P, E> {
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, Meta<T, Span>, E> {
self.0.parse(source, location).meta()
}
}
pub struct ListMap<P, E>(P, PhantomData<E>);
impl<T, E, P: Parser<T, E>> Parser<List<T>, E> for ListMap<P, E> {
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, List<T>, E> {
self.0.parse(source, location).map(&List::single)
}
}
pub struct DelimitedBy<P, S, D, R, E>(P, S, R, PhantomData<(D, E)>);
impl<T, D, E, R, P, S> Parser<List<T>, E> for DelimitedBy<P, S, D, R, E>
where
T: Clone,
R: RangeBounds<usize> + Clone,
P: Parser<T, E>,
S: Parser<D, E>,
{
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, List<T>, E> {
self.0
.ref_parser()
.drop(self.1.ref_parser())
.to_list()
.multiple()
.maybe()
.and(
self.0
.ref_parser()
.to_list()
.maybe_drop(self.1.ref_parser()),
)
.maybe()
.parse(source, location)
.and_then(&|parsed, source, location| {
let length = parsed.length();
let long_enough = match self.2.start_bound() {
Bound::Included(minimum) if length < *minimum => ParseResult::none(location),
Bound::Excluded(minimum) if length <= *minimum => ParseResult::none(location),
_ => ParseResult::success(parsed.clone(), source, location),
};
match self.2.end_bound() {
Bound::Included(maximum) if length > *maximum => ParseResult::none(location),
Bound::Excluded(maximum) if length >= *maximum => ParseResult::none(location),
_ => long_enough,
}
})
}
}
pub struct StrictlyDelimitedBy<P, S, D, R, E>(P, S, R, PhantomData<(D, E)>);
impl<T, D, E, R, P, S> Parser<List<T>, E> for StrictlyDelimitedBy<P, S, D, R, E>
where
T: Clone,
R: RangeBounds<usize> + Clone,
P: Parser<T, E>,
S: Parser<D, E>,
{
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, List<T>, E> {
self.0
.ref_parser()
.drop(self.1.ref_parser())
.to_list()
.multiple()
.maybe()
.and(self.0.ref_parser().to_list())
.maybe()
.parse(source, location)
.and_then(&|parsed, source, location| {
let length = parsed.length();
let long_enough = match self.2.start_bound() {
Bound::Included(minimum) if length < *minimum => ParseResult::none(location),
Bound::Excluded(minimum) if length <= *minimum => ParseResult::none(location),
_ => ParseResult::success(parsed.clone(), source, location),
};
match self.2.end_bound() {
Bound::Included(maximum) if length > *maximum => ParseResult::none(location),
Bound::Excluded(maximum) if length >= *maximum => ParseResult::none(location),
_ => long_enough,
}
})
}
}
pub struct SurroundedBy<P, OP, CP, O, C, E>(P, OP, CP, PhantomData<(O, C, E)>);
impl<T, O, C, P, OP, CP, E> Parser<T, E> for SurroundedBy<P, OP, CP, O, C, E>
where
T: Clone,
P: Parser<T, E>,
OP: Parser<C, E>,
CP: Parser<C, E>,
{
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
self.1
.ref_parser()
.skip(self.0.ref_parser())
.drop(self.2.ref_parser())
.parse(source, location)
}
}
pub struct StringMap<P, E>(P, PhantomData<E>);
impl<E, P: Parser<Span, E>> Parser<String, E> for StringMap<P, E> {
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, String, E> {
self.0
.parse(source, location)
.map(&|s| s.subslice(&location, source).to_owned())
}
}
pub struct StrCondition<P, F, E>(P, F, PhantomData<E>);
impl<E, P: Parser<Span, E>, F: Fn(&str) -> bool> Parser<Span, E> for StrCondition<P, F, E> {
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, Span, E> {
self.0
.parse(source, location)
.and_then(&|parsed, remaining, remaining_location| {
if self.1(parsed.subslice(&location, source)) {
ParseResult::success(parsed, remaining, remaining_location)
} else {
ParseResult::none(location)
}
})
}
}
pub struct Collect<P, T, I, E>(P, PhantomData<(T, I, E)>);
impl<T, I: FromIterator<T>, E, P: Parser<List<T>, E>> Parser<I, E> for Collect<P, T, I, E> {
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, I, E> {
let result = self.0.parse(source, location);
if result.single_parse() || result.is_none() {
result.map(&|parsed| parsed.drain().collect())
} else {
panic!(
"Cannot collect on parse with more than one result: {}",
location
);
}
}
}
pub struct Pair<A, B, E>(A, B, PhantomData<E>);
impl<A, B, PA, PB, E> Parser<(A, B), E> for Pair<PA, PB, E>
where
A: Clone,
PA: Parser<A, E>,
PB: Parser<B, E>,
{
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, (A, B), E> {
self.0
.ref_parser()
.and_then(move |left| self.1.ref_parser().map(move |right| (left.clone(), right)))
.parse(source, location)
}
}
pub struct SpaceAfter<P, E>(P, PhantomData<E>);
impl<T: Clone, E, P: Parser<T, E>> Parser<T, E> for SpaceAfter<P, E> {
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
self.0.ref_parser().drop(space).parse(source, location)
}
}
pub struct MaybeSpaceAfter<P, E>(P, PhantomData<E>);
impl<T: Clone, E, P: Parser<T, E>> Parser<T, E> for MaybeSpaceAfter<P, E> {
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
self.0
.ref_parser()
.drop(space.maybe())
.parse(source, location)
}
}
pub struct SpaceBefore<P, E>(P, PhantomData<E>);
impl<T, E, P: Parser<T, E>> Parser<T, E> for SpaceBefore<P, E> {
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
space.skip(self.0.ref_parser()).parse(source, location)
}
}
pub struct MaybeSpaceBefore<P, E>(P, PhantomData<E>);
impl<T: Clone, E, P: Parser<T, E>> Parser<T, E> for MaybeSpaceBefore<P, E> {
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
space
.maybe()
.skip(self.0.ref_parser())
.parse(source, location)
}
}
pub struct SpaceAround<P, E>(P, PhantomData<E>);
impl<T: Clone, E, P: Parser<T, E>> Parser<T, E> for SpaceAround<P, E> {
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
self.0
.ref_parser()
.space_before()
.space_after()
.parse(source, location)
}
}
pub struct MaybeSpaceAround<P, E>(P, PhantomData<E>);
impl<T: Clone, E, P: Parser<T, E>> Parser<T, E> for MaybeSpaceAround<P, E> {
fn parse<'s>(&self, source: &'s str, location: Span) -> ParseResult<'s, T, E> {
self.0
.ref_parser()
.maybe_space_before()
.maybe_space_after()
.parse(source, location)
}
}