use crate::{
error::{
self, ErrorInfo, ParseError,
ParseResult::{self, *},
ResultExt, StreamError, Tracked,
},
lib::marker::PhantomData,
stream::{uncons, Stream, StreamOnce},
Parser,
};
#[derive(Copy, Clone)]
pub struct Any<Input>(PhantomData<fn(Input) -> Input>);
impl<Input> Parser<Input> for Any<Input>
where
Input: Stream,
{
type Output = Input::Token;
type PartialState = ();
#[inline]
fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<Input::Token, Input::Error> {
uncons(input)
}
}
pub fn any<Input>() -> Any<Input>
where
Input: Stream,
{
Any(PhantomData)
}
#[derive(Copy, Clone)]
pub struct Satisfy<Input, P> {
predicate: P,
_marker: PhantomData<Input>,
}
fn satisfy_impl<Input, P, R>(input: &mut Input, mut predicate: P) -> ParseResult<R, Input::Error>
where
Input: Stream,
P: FnMut(Input::Token) -> Option<R>,
{
let position = input.position();
match uncons(input) {
PeekOk(c) | CommitOk(c) => match predicate(c) {
Some(c) => CommitOk(c),
None => PeekErr(Input::Error::empty(position).into()),
},
PeekErr(err) => PeekErr(err),
CommitErr(err) => CommitErr(err),
}
}
impl<Input, P> Parser<Input> for Satisfy<Input, P>
where
Input: Stream,
P: FnMut(Input::Token) -> bool,
{
type Output = Input::Token;
type PartialState = ();
#[inline]
fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<Self::Output, Input::Error> {
satisfy_impl(input, |c| {
if (self.predicate)(c.clone()) {
Some(c)
} else {
None
}
})
}
}
pub fn satisfy<Input, P>(predicate: P) -> Satisfy<Input, P>
where
Input: Stream,
P: FnMut(Input::Token) -> bool,
{
Satisfy {
predicate,
_marker: PhantomData,
}
}
#[derive(Copy, Clone)]
pub struct SatisfyMap<Input, P> {
predicate: P,
_marker: PhantomData<Input>,
}
impl<Input, P, R> Parser<Input> for SatisfyMap<Input, P>
where
Input: Stream,
P: FnMut(Input::Token) -> Option<R>,
{
type Output = R;
type PartialState = ();
#[inline]
fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<Self::Output, Input::Error> {
satisfy_impl(input, &mut self.predicate)
}
}
pub fn satisfy_map<Input, P, R>(predicate: P) -> SatisfyMap<Input, P>
where
Input: Stream,
P: FnMut(Input::Token) -> Option<R>,
{
SatisfyMap {
predicate,
_marker: PhantomData,
}
}
#[derive(Copy, Clone)]
pub struct Token<Input>
where
Input: Stream,
Input::Token: PartialEq,
{
c: Input::Token,
_marker: PhantomData<Input>,
}
impl<Input> Parser<Input> for Token<Input>
where
Input: Stream,
Input::Token: PartialEq + Clone,
{
type Output = Input::Token;
type PartialState = ();
#[inline]
fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<Input::Token, Input::Error> {
satisfy_impl(input, |c| if c == self.c { Some(c) } else { None })
}
fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
errors.error.add_expected(error::Token(self.c.clone()));
}
}
pub fn token<Input>(c: Input::Token) -> Token<Input>
where
Input: Stream,
Input::Token: PartialEq,
{
Token {
c,
_marker: PhantomData,
}
}
#[derive(Clone)]
pub struct Tokens<C, E, T, Input>
where
Input: Stream,
{
cmp: C,
expected: E,
tokens: T,
_marker: PhantomData<Input>,
}
impl<Input, C, E, T> Parser<Input> for Tokens<C, E, T, Input>
where
C: FnMut(T::Item, Input::Token) -> bool,
E: for<'s> ErrorInfo<'s, Input::Token, Input::Range>,
T: Clone + IntoIterator,
Input: Stream,
{
type Output = T;
type PartialState = ();
#[inline]
fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<T, Input::Error> {
let start = input.position();
let mut committed = false;
for c in self.tokens.clone() {
match crate::stream::uncons(input) {
CommitOk(other) | PeekOk(other) => {
if !(self.cmp)(c, other.clone()) {
return if committed {
let mut errors = <Input as StreamOnce>::Error::from_error(
start,
StreamError::unexpected_token(other),
);
errors.add_expected(&self.expected);
CommitErr(errors)
} else {
PeekErr(<Input as StreamOnce>::Error::empty(start).into())
};
}
committed = true;
}
PeekErr(mut error) => {
error.error.set_position(start);
return if committed {
CommitErr(error.error)
} else {
PeekErr(error)
};
}
CommitErr(mut error) => {
error.set_position(start);
return CommitErr(error);
}
}
}
if committed {
CommitOk(self.tokens.clone())
} else {
PeekOk(self.tokens.clone())
}
}
fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
errors.error.add_expected(&self.expected);
}
}
pub fn tokens<C, E, T, Input>(cmp: C, expected: E, tokens: T) -> Tokens<C, E, T, Input>
where
C: FnMut(T::Item, Input::Token) -> bool,
T: Clone + IntoIterator,
Input: Stream,
{
Tokens {
cmp,
expected,
tokens,
_marker: PhantomData,
}
}
#[derive(Clone)]
pub struct TokensCmp<C, T, Input>
where
Input: Stream,
{
cmp: C,
tokens: T,
_marker: PhantomData<Input>,
}
impl<Input, C, T> Parser<Input> for TokensCmp<C, T, Input>
where
C: FnMut(T::Item, Input::Token) -> bool,
T: Clone + IntoIterator,
Input: Stream,
{
type Output = T;
type PartialState = ();
#[inline]
fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<T, Input::Error> {
let start = input.position();
let mut committed = false;
for c in self.tokens.clone() {
match crate::stream::uncons(input) {
CommitOk(other) | PeekOk(other) => {
if !(self.cmp)(c, other.clone()) {
return if committed {
let errors = <Input as StreamOnce>::Error::from_error(
start,
StreamError::unexpected_token(other),
);
CommitErr(errors)
} else {
PeekErr(<Input as StreamOnce>::Error::empty(start).into())
};
}
committed = true;
}
PeekErr(mut error) => {
error.error.set_position(start);
return if committed {
CommitErr(error.error)
} else {
PeekErr(error)
};
}
CommitErr(mut error) => {
error.set_position(start);
return CommitErr(error);
}
}
}
if committed {
CommitOk(self.tokens.clone())
} else {
PeekOk(self.tokens.clone())
}
}
}
pub fn tokens_cmp<C, T, I>(tokens: T, cmp: C) -> TokensCmp<C, T, I>
where
C: FnMut(T::Item, I::Token) -> bool,
T: Clone + IntoIterator,
I: Stream,
{
TokensCmp {
cmp,
tokens,
_marker: PhantomData,
}
}
#[derive(Copy, Clone)]
pub struct Position<Input>
where
Input: Stream,
{
_marker: PhantomData<Input>,
}
impl<Input> Parser<Input> for Position<Input>
where
Input: Stream,
{
type Output = Input::Position;
type PartialState = ();
#[inline]
fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<Input::Position, Input::Error> {
PeekOk(input.position())
}
}
pub fn position<Input>() -> Position<Input>
where
Input: Stream,
{
Position {
_marker: PhantomData,
}
}
#[derive(Copy, Clone)]
pub struct OneOf<T, Input>
where
Input: Stream,
{
tokens: T,
_marker: PhantomData<Input>,
}
impl<Input, T> Parser<Input> for OneOf<T, Input>
where
T: Clone + IntoIterator<Item = Input::Token>,
Input: Stream,
Input::Token: PartialEq,
{
type Output = Input::Token;
type PartialState = ();
#[inline]
fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<Input::Token, Input::Error> {
satisfy(|c| self.tokens.clone().into_iter().any(|t| t == c)).parse_lazy(input)
}
fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
for expected in self.tokens.clone() {
errors.error.add_expected(error::Token(expected));
}
}
}
pub fn one_of<T, Input>(tokens: T) -> OneOf<T, Input>
where
T: Clone + IntoIterator,
Input: Stream,
Input::Token: PartialEq<T::Item>,
{
OneOf {
tokens,
_marker: PhantomData,
}
}
#[derive(Copy, Clone)]
pub struct NoneOf<T, Input>
where
Input: Stream,
{
tokens: T,
_marker: PhantomData<Input>,
}
impl<Input, T> Parser<Input> for NoneOf<T, Input>
where
T: Clone + IntoIterator<Item = Input::Token>,
Input: Stream,
Input::Token: PartialEq,
{
type Output = Input::Token;
type PartialState = ();
#[inline]
fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<Input::Token, Input::Error> {
satisfy(|c| self.tokens.clone().into_iter().all(|t| t != c)).parse_lazy(input)
}
}
pub fn none_of<T, Input>(tokens: T) -> NoneOf<T, Input>
where
T: Clone + IntoIterator,
Input: Stream,
Input::Token: PartialEq<T::Item>,
{
NoneOf {
tokens,
_marker: PhantomData,
}
}
#[derive(Copy, Clone)]
pub struct Value<Input, T>(T, PhantomData<fn(Input) -> Input>);
impl<Input, T> Parser<Input> for Value<Input, T>
where
Input: Stream,
T: Clone,
{
type Output = T;
type PartialState = ();
#[inline]
fn parse_lazy(&mut self, _: &mut Input) -> ParseResult<T, Input::Error> {
PeekOk(self.0.clone())
}
}
pub fn value<Input, T>(v: T) -> Value<Input, T>
where
Input: Stream,
T: Clone,
{
Value(v, PhantomData)
}
#[derive(Copy, Clone)]
pub struct Produce<Input, F>(F, PhantomData<fn(Input) -> Input>);
impl<Input, F, R> Parser<Input> for Produce<Input, F>
where
Input: Stream,
F: FnMut() -> R,
{
type Output = R;
type PartialState = ();
#[inline]
fn parse_lazy(&mut self, _: &mut Input) -> ParseResult<R, Input::Error> {
PeekOk((self.0)())
}
}
pub fn produce<Input, F, R>(f: F) -> Produce<Input, F>
where
Input: Stream,
F: FnMut() -> R,
{
Produce(f, PhantomData)
}
#[derive(Copy, Clone)]
pub struct Eof<Input>(PhantomData<Input>);
impl<Input> Parser<Input> for Eof<Input>
where
Input: Stream,
{
type Output = ();
type PartialState = ();
#[inline]
fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<(), Input::Error> {
let before = input.checkpoint();
match input.uncons() {
Err(ref err) if err.is_unexpected_end_of_input() => PeekOk(()),
_ => {
ctry!(input.reset(before).committed());
PeekErr(<Input as StreamOnce>::Error::empty(input.position()).into())
}
}
}
fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
errors.error.add_expected("end of input");
}
}
pub fn eof<Input>() -> Eof<Input>
where
Input: Stream,
{
Eof(PhantomData)
}