parze 0.4.1

A clean, efficient parser combinator
Documentation
use crate::error::ParseError;

#[derive(Debug)]
pub struct Fail<E>(usize, E);

impl<E> Fail<E> {
    pub fn new(idx: usize, err: E) -> Self {
        Self(idx, err)
    }

    pub fn take_error(self) -> E {
        self.1
    }

    pub fn map_err<G>(self, f: impl Fn(E) -> G) -> Fail<G> {
        Self(self.0, f(self.1))
    }

    pub fn max<'a, T: Clone + 'a>(self, other: impl Into<MayFail<E>>) -> Self where E: ParseError<'a, T> {
        match other.into().0 {
            Some((idx, err)) if idx == self.0 => Self(idx, err.combine(self.1)),
            Some((idx, err)) if idx > self.0 => Self(idx, err),
            Some((idx, _)) if idx < self.0 => Self(self.0, self.1),
            _ => self,
        }
    }
}

#[derive(Debug)]
pub struct MayFail<E>(Option<(usize, E)>);

impl<E> MayFail<E> {
    pub fn none() -> Self {
        Self(None)
    }

    pub fn map_err<G>(self, f: impl Fn(E) -> G) -> MayFail<G> {
        MayFail(self.0.map(|(idx, e)| (idx, f(e))))
    }

    pub fn max<'a, T: Clone + 'a>(self, other: impl Into<MayFail<E>>) -> Self where E: ParseError<'a, T> {
        match (self.0, other.into().0) {
            (Some((a_idx, a)), Some((b_idx, b)))
                if a_idx == b_idx => Self(Some((a_idx, a.combine(b)))),
            (Some((a_idx, _)), Some((b_idx, b)))
                if a_idx > b_idx => Self(Some((b_idx, b))),
            (Some((a_idx, a)), Some((b_idx, _)))
                if a_idx < b_idx => Self(Some((a_idx, a))),
            (Some((a_idx, a)), _) => Self(Some((a_idx, a))),
            (_, Some((b_idx, b))) => Self(Some((b_idx, b))),
            _ => Self(None),
        }
    }
}

impl<E> From<Fail<E>> for MayFail<E> {
    fn from(fail: Fail<E>) -> Self {
        Self(Some((fail.0, fail.1)))
    }
}