chasa 0.5.0

A parser combinator focused on rollback/commit, streaming inputs, and composable method chains.
Documentation
use core::marker::PhantomData;

use reborrow_generic::Reborrow;
use seq_macro::seq;

use crate::back::RbBack;
use crate::error::ErrorSink;
use crate::error::std::Unexpected;
use crate::input::{In, Input};
use crate::parser::prim::{from_fn_once, value};
use crate::parser::{Parser, ParserMut, ParserOnce, SkipParser, SkipParserMut, SkipParserOnce};

pub trait TrieState: Sized {
    type Item;
    type Value;
    fn step(&mut self, ch: Self::Item) -> bool;
    fn value(&self) -> Option<Self::Value>;

    fn longest_match<A>(self) -> TrieParser<Self, A> {
        TrieParser(self, PhantomData)
    }

    fn longest_match_then<O, F, I, N, L, E>(self, f: F) -> TrieThen<Self, F, (I, N, L, E)>
    where
        I: Input,
        N: Reborrow,
        L: RbBack,
        E: ErrorSink<I::Pos>,
        F: FnMut(Self::Item, Self::Value, In<I, N, L, E>) -> Option<O>,
    {
        TrieThen(self, f, PhantomData)
    }
}

pub struct TrieParser<T, A>(T, PhantomData<fn() -> A>);

fn run_trie_parser<T, I, N, L, E>(state: &mut T, mut i: In<I, N, L, E>) -> Option<T::Value>
where
    T: TrieState<Item = I::Item>,
    I: Input,
    N: Reborrow,
    L: RbBack,
    E: ErrorSink<I::Pos>,
    I::Item: Clone,
    Unexpected<I::Item>: Into<E::Error>,
{
    i.satisfy(|c| state.step(c))?;
    if let Some(v) = state.value() {
        i.choice((from_fn_once(|i| run_trie_parser(state, i)), value(v)))
    } else {
        run_trie_parser(state, i)
    }
}

impl<I, N, L, E, T> SkipParserOnce<I, N, L, E> for TrieParser<T, (I, N, L, E)>
where
    T: TrieState<Item = I::Item>,
    I: Input,
    N: Reborrow,
    L: RbBack,
    E: ErrorSink<I::Pos>,
    I::Item: Clone,
    Unexpected<I::Item>: Into<E::Error>,
{
    #[inline]
    fn discard_once(self, i: In<I, N, L, E>) -> Option<()> {
        let mut state = self.0;
        run_trie_parser(&mut state, i).map(|_| ())
    }
}

impl<I, N, L, E, T> ParserOnce<I, N, L, E> for TrieParser<T, (I, N, L, E)>
where
    T: TrieState<Item = I::Item>,
    I: Input,
    N: Reborrow,
    L: RbBack,
    E: ErrorSink<I::Pos>,
    I::Item: Clone,
    Unexpected<I::Item>: Into<E::Error>,
{
    type Out = T::Value;
    #[inline]
    fn parse_once(self, i: In<I, N, L, E>) -> Option<Self::Out> {
        let mut state = self.0;
        run_trie_parser(&mut state, i)
    }
}

impl<I, N, L, E, T> SkipParserMut<I, N, L, E> for TrieParser<T, (I, N, L, E)>
where
    T: TrieState<Item = I::Item>,
    I: Input,
    N: Reborrow,
    L: RbBack,
    E: ErrorSink<I::Pos>,
    I::Item: Clone,
    Unexpected<I::Item>: Into<E::Error>,
{
    #[inline]
    fn discard_mut(&mut self, i: In<I, N, L, E>) -> Option<()> {
        run_trie_parser(&mut self.0, i).map(|_| ())
    }
}

impl<I, N, L, E, T> ParserMut<I, N, L, E> for TrieParser<T, (I, N, L, E)>
where
    T: TrieState<Item = I::Item>,
    I: Input,
    N: Reborrow,
    L: RbBack,
    E: ErrorSink<I::Pos>,
    I::Item: Clone,
    Unexpected<I::Item>: Into<E::Error>,
{
    #[inline]
    fn parse_mut(&mut self, i: In<I, N, L, E>) -> Option<Self::Out> {
        run_trie_parser(&mut self.0, i)
    }
}

impl<I, N, L, E, T> SkipParser<I, N, L, E> for TrieParser<T, (I, N, L, E)>
where
    T: TrieState<Item = I::Item> + Clone,
    I: Input,
    N: Reborrow,
    L: RbBack,
    E: ErrorSink<I::Pos>,
    I::Item: Clone,
    Unexpected<I::Item>: Into<E::Error>,
{
    #[inline]
    fn discard(&self, i: In<I, N, L, E>) -> Option<()> {
        let mut state = self.0.clone();
        run_trie_parser(&mut state, i).map(|_| ())
    }
}

impl<I, N, L, E, T> Parser<I, N, L, E> for TrieParser<T, (I, N, L, E)>
where
    T: TrieState<Item = I::Item> + Clone,
    I: Input,
    N: Reborrow,
    L: RbBack,
    E: ErrorSink<I::Pos>,
    I::Item: Clone,
    Unexpected<I::Item>: Into<E::Error>,
{
    #[inline]
    fn parse(&self, i: In<I, N, L, E>) -> Option<Self::Out> {
        let mut state = self.0.clone();
        run_trie_parser(&mut state, i)
    }
}

pub struct TrieThen<T, F, A>(T, F, PhantomData<fn() -> A>);

fn run_trie_then<T, O, I, N, L, E>(
    state: &mut T,
    f: &mut impl FnMut(T::Item, T::Value, In<I, N, L, E>) -> Option<O>,
    mut i: In<I, N, L, E>,
) -> Option<O>
where
    T: TrieState<Item = I::Item>,
    I: Input,
    N: Reborrow,
    L: RbBack,
    E: ErrorSink<I::Pos>,
    I::Item: Clone,
    Unexpected<I::Item>: Into<E::Error>,
{
    let c = i.satisfy(|c| state.step(c))?;
    if let Some(v) = state.value() {
        if let Some(o) = i.maybe(from_fn_once(|i| run_trie_then(state, f, i)))? {
            Some(o)
        } else {
            f(c, v, i)
        }
    } else {
        run_trie_then(state, f, i)
    }
}

impl<T, F, O, I, N, L, E> SkipParserOnce<I, N, L, E> for TrieThen<T, F, (I, N, L, E)>
where
    T: TrieState<Item = I::Item>,
    I: Input,
    N: Reborrow,
    L: RbBack,
    E: ErrorSink<I::Pos>,
    I::Item: Clone,
    Unexpected<I::Item>: Into<E::Error>,
    F: FnMut(T::Item, T::Value, In<I, N, L, E>) -> Option<O>,
{
    #[inline]
    fn discard_once(mut self, i: In<I, N, L, E>) -> Option<()> {
        run_trie_then(&mut self.0, &mut self.1, i).map(|_| ())
    }
}

impl<T, F, O, I, N, L, E> ParserOnce<I, N, L, E> for TrieThen<T, F, (I, N, L, E)>
where
    T: TrieState<Item = I::Item>,
    I: Input,
    N: Reborrow,
    L: RbBack,
    E: ErrorSink<I::Pos>,
    I::Item: Clone,
    Unexpected<I::Item>: Into<E::Error>,
    F: FnMut(T::Item, T::Value, In<I, N, L, E>) -> Option<O>,
{
    type Out = O;
    #[inline]
    fn parse_once(mut self, i: In<I, N, L, E>) -> Option<O> {
        run_trie_then(&mut self.0, &mut self.1, i)
    }
}

impl<T, F, O, I, N, L, E> SkipParserMut<I, N, L, E> for TrieThen<T, F, (I, N, L, E)>
where
    T: TrieState<Item = I::Item>,
    I: Input,
    N: Reborrow,
    L: RbBack,
    E: ErrorSink<I::Pos>,
    I::Item: Clone,
    Unexpected<I::Item>: Into<E::Error>,
    F: FnMut(T::Item, T::Value, In<I, N, L, E>) -> Option<O>,
{
    #[inline]
    fn discard_mut(&mut self, i: In<I, N, L, E>) -> Option<()> {
        run_trie_then(&mut self.0, &mut self.1, i).map(|_| ())
    }
}

impl<T, F, O, I, N, L, E> ParserMut<I, N, L, E> for TrieThen<T, F, (I, N, L, E)>
where
    T: TrieState<Item = I::Item>,
    I: Input,
    N: Reborrow,
    L: RbBack,
    E: ErrorSink<I::Pos>,
    I::Item: Clone,
    Unexpected<I::Item>: Into<E::Error>,
    F: FnMut(T::Item, T::Value, In<I, N, L, E>) -> Option<O>,
{
    #[inline]
    fn parse_mut(&mut self, i: In<I, N, L, E>) -> Option<Self::Out> {
        run_trie_then(&mut self.0, &mut self.1, i)
    }
}

impl<T, F, O, I, N, L, E> SkipParser<I, N, L, E> for TrieThen<T, F, (I, N, L, E)>
where
    T: TrieState<Item = I::Item> + Clone,
    I: Input,
    N: Reborrow,
    L: RbBack,
    E: ErrorSink<I::Pos>,
    I::Item: Clone,
    Unexpected<I::Item>: Into<E::Error>,
    F: FnMut(T::Item, T::Value, In<I, N, L, E>) -> Option<O> + Clone,
{
    #[inline]
    fn discard(&self, i: In<I, N, L, E>) -> Option<()> {
        let mut state = self.0.clone();
        let mut f = self.1.clone();
        run_trie_then(&mut state, &mut f, i).map(|_| ())
    }
}

impl<T, F, O, I, N, L, E> Parser<I, N, L, E> for TrieThen<T, F, (I, N, L, E)>
where
    T: TrieState<Item = I::Item> + Clone,
    I: Input,
    N: Reborrow,
    L: RbBack,
    E: ErrorSink<I::Pos>,
    I::Item: Clone,
    Unexpected<I::Item>: Into<E::Error>,
    F: FnMut(T::Item, T::Value, In<I, N, L, E>) -> Option<O> + Clone,
{
    #[inline]
    fn parse(&self, i: In<I, N, L, E>) -> Option<Self::Out> {
        let mut state = self.0.clone();
        let mut f = self.1.clone();
        run_trie_then(&mut state, &mut f, i)
    }
}

macro_rules! trie_state_impl {
    ($N:literal) => {
        seq!(n in 1..=$N {
            impl<Item, Value, #(T~n,)*> TrieState for ( #(T~n,)* )
            where
                Item: Clone,
                #(T~n: TrieState<Item = Item, Value = Value>,)*
            {
                type Item = Item;
                type Value = Value;

                fn step(&mut self, ch: Self::Item) -> bool {
                    let ( #(s~n,)* ) = self;
                    let mut any = false;
                    #( any |= s~n.step(ch.clone()); )*
                    any
                }

                fn value(&self) -> Option<Self::Value> {
                    let ( #(s~n,)* ) = self;
                    #( let v~n = s~n.value(); if v~n.is_some() { return v~n; } )*
                    None
                }
            }
        });
    };
}

seq!(N in 2..=16 { trie_state_impl!(N); });