use std::cell::RefCell; use std::rc::Rc; use nom::branch::alt; use nom::bytes::complete::take; use nom::combinator::not; use nom::error::ContextError; use nom::error::ErrorKind; use nom::error::ParseError; use nom::error::VerboseError; use nom::IResult; use nom::Parser; use tracing::trace; type Link<'r, T> = Option<&'r Node<'r, T>>; type Matcher = dyn for<'s> Fn(&'s str) -> IResult<&'s str, &'s str, VerboseError<&'s str>>; pub type OrgModeContextNode<'r> = ContextTree<'r, ContextElement<'r>>; struct Node<'r, T> { elem: T, next: Link<'r, T>, } pub struct ContextTree<'r, T> { head: Option>, } impl<'r, T> ContextTree<'r, T> { pub fn new() -> Self { ContextTree { head: None } } pub fn with_additional_node(&'r self, element: T) -> ContextTree<'r, T> { let new_node = Node { elem: element, next: self.head.as_ref(), }; ContextTree { head: Some(new_node), } } } pub enum ContextElement<'r> { FailMatcherNode(FailMatcherNode<'r>), PreviousElementNode(PreviousElementNode<'r>), } pub struct FailMatcherNode<'r> { pub fail_matcher: ChainBehavior<'r>, } pub struct PreviousElementNode<'r> { pub dummy: &'r str, } #[derive(Clone)] pub enum ChainBehavior<'r> { AndParent(Option<&'r Matcher>), IgnoreParent(Option<&'r Matcher>), } pub trait OrgModeContextTree<'r> { fn with_additional_fail_matcher(&'r self, fail_matcher: &'r Matcher) -> OrgModeContextNode<'r>; fn match_fail<'s>(&'r self, i: &'s str) -> IResult<&'s str, &'s str, VerboseError<&'s str>>; } impl<'r> OrgModeContextTree<'r> for OrgModeContextNode<'r> { fn with_additional_fail_matcher( &'r self, fail_matcher: &'r Matcher, ) -> ContextTree<'r, ContextElement<'r>> { self.with_additional_node(ContextElement::FailMatcherNode(FailMatcherNode { fail_matcher: ChainBehavior::AndParent(Some(fail_matcher)), })) } // fn with_previous_element(&'r self, dummy: &'r str) -> ContextTree<'r, PreviousElementNode<'r>> { // self.with_additional_node(PreviousElementNode { // dummy // }) // } fn match_fail<'s>(&'r self, i: &'s str) -> IResult<&'s str, &'s str, VerboseError<&'s str>> { let mut current_node = self.head.as_ref(); while current_node.is_some() { let current_node_unwrapped = current_node.expect("while loop asserts current_node is some."); match current_node_unwrapped.elem.get_fail_matcher() { ChainBehavior::AndParent(Some(matcher)) => { let local_result = matcher(i); if local_result.is_ok() { return local_result; } } ChainBehavior::AndParent(None) => {} ChainBehavior::IgnoreParent(Some(matcher)) => { let local_result = matcher(i); if local_result.is_ok() { return local_result; } // TODO: Make this a custom error not(take(0usize))(i)?; } ChainBehavior::IgnoreParent(None) => { // TODO: Make this a custom error not(take(0usize))(i)?; } }; current_node = current_node.map(|current_head| current_head.next).flatten(); } // TODO: Make this a custom error not(take(0usize))(i)?; unreachable!() } } impl<'r, T> std::fmt::Debug for ContextTree<'r, T> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "ContextTree") } } impl<'r> ContextElement<'r> { pub fn get_fail_matcher(&self) -> ChainBehavior<'r> { match self { ContextElement::FailMatcherNode(fail_matcher_node) => { fail_matcher_node.fail_matcher.clone() } ContextElement::PreviousElementNode(previous_element_node) => { ChainBehavior::AndParent(None) } } } }