aott 0.2.0

Aspect Of The Tokens - a parser combinator framework.
Documentation
use core::cell::OnceCell;

use crate::{
        input::InputType,
        parser::{Parser, ParserExtras},
};

type OnceParser<'a, I, O, E> = OnceCell<Box<dyn Parser<I, O, E> + 'a>>;

pub struct Recursive<'a, I: InputType, O, E: ParserExtras<I>>(
        RecursiveImp<OnceParser<'a, I, O, E>>,
);

enum RecursiveImp<T> {
        Owned(crate::sync::RefC<T>),
        Unowned(crate::sync::RefW<T>),
}

impl<'a, I: InputType, O, E: ParserExtras<I>> Recursive<'a, I, O, E> {
        fn cell(&self) -> crate::sync::RefC<OnceParser<'a, I, O, E>> {
                match &self.0 {
                        RecursiveImp::Owned(own) => own.clone(),
                        RecursiveImp::Unowned(unown) => unown
                                .upgrade()
                                .expect("recursive parser used before definition"),
                }
        }
        pub fn declare() -> Self {
                Self(RecursiveImp::Owned(crate::sync::RefC::new(OnceCell::new())))
        }

        pub fn define(&mut self, parser: impl Parser<I, O, E> + 'a) {
                self.cell()
                        .set(Box::new(parser))
                        .unwrap_or_else(|_| panic!("Parser defined more than once"))
        }
}

impl<'a, I: InputType, O, E: ParserExtras<I>> Clone for Recursive<'a, I, O, E> {
        fn clone(&self) -> Self {
                Self(match &self.0 {
                        RecursiveImp::Owned(own) => {
                                RecursiveImp::Unowned(crate::sync::RefC::downgrade(own))
                        }
                        RecursiveImp::Unowned(unown) => {
                                RecursiveImp::Unowned(crate::sync::RefW::clone(unown))
                        }
                })
        }
}

impl<'a, I: InputType, O, E: ParserExtras<I>> Parser<I, O, E> for Recursive<'a, I, O, E> {
        fn check<'parse>(
                &self,
                input: crate::input::Input<'parse, I, E>,
        ) -> crate::IResult<'parse, I, E, ()> {
                self.cell()
                        .get()
                        .expect("Recursive parser used before definition")
                        .as_ref()
                        .check(input)
        }

        fn parse<'parse>(
                &self,
                input: crate::input::Input<'parse, I, E>,
        ) -> crate::IResult<'parse, I, E, O> {
                self.cell()
                        .get()
                        .expect("Recursive parser used before definition")
                        .as_ref()
                        .parse(input)
        }
}