use std::fmt;
use crate::combinators::{Then, Transform};
use crate::state::ParseState;
#[derive(Debug, PartialEq)]
pub enum ParseError {
EOF,
Fail(&'static str, usize),
TransformFail(&'static str, usize, Box<ParseError>),
ExecFail(String),
}
pub fn execerr<S: AsRef<str>>(s: S) -> ParseError {
ParseError::ExecFail(s.as_ref().to_string())
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ParseError::EOF => f.write_str("EOF"),
ParseError::Fail(s, pos) => write!(f, "Parse fail: {} at {}", s, pos),
ParseError::TransformFail(s, pos, inner) => {
write!(f, "Transform fail: {} at {} due to ", s, pos).and_then(|()| inner.fmt(f))
}
ParseError::ExecFail(s) => write!(f, "Logic error: {}", s),
}
}
}
pub type ParseResult<R> = Result<R, ParseError>;
pub trait Parser {
type Result;
fn parse(
&mut self,
st: &mut ParseState<impl Iterator<Item = char>>,
) -> ParseResult<Self::Result>;
fn apply<R2, F: Fn(Self::Result) -> ParseResult<R2>>(
self,
f: F,
) -> Transform<Self::Result, R2, Self, F>
where
Self: std::marker::Sized,
{
Transform::new(self, f)
}
fn then<R2, P: Parser<Result = R2>>(self, p: P) -> Then<Self, P>
where
Self: std::marker::Sized,
{
Then::new(self, p)
}
}