diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 87bf5a7..c18823d 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1,8 +1,7 @@ mod list; -mod new_context; mod nom_context; mod parser_with_context; mod text; mod text_element_parser; pub use text_element_parser::document; -type Context<'r> = &'r new_context::ContextTree<'r>; +type Context<'r> = &'r nom_context::ContextTree<'r>; diff --git a/src/parser/new_context.rs b/src/parser/new_context.rs deleted file mode 100644 index 3e566bf..0000000 --- a/src/parser/new_context.rs +++ /dev/null @@ -1,106 +0,0 @@ -use nom::bytes::complete::take; -use nom::combinator::not; -use nom::error::VerboseError; -use nom::IResult; - -use super::list::List; - -type Matcher = dyn for<'s> Fn(&'s str) -> IResult<&'s str, &'s str, VerboseError<&'s str>>; - -#[derive(Debug, Clone)] -pub struct ContextTree<'r> { - tree: List>, -} - -impl<'r> ContextTree<'r> { - pub fn new() -> Self { - ContextTree { tree: List::new() } - } - - pub fn with_additional_node(&self, data: ContextElement<'r>) -> ContextTree<'r> { - let new_list = self.tree.push_front(data); - ContextTree { tree: new_list } - } - - pub fn check_fail_matcher<'s>( - &'r self, - i: &'s str, - ) -> IResult<&'s str, &'s str, VerboseError<&'s str>> { - // TODO: Can I do this without incrementing reference counters? Perhaps via implementing an iterator over the list? - let mut current_node = self.tree.clone(); - while !current_node.is_empty() { - let context_element = current_node - .get_data() - .expect("While looop proves its Some()"); - match context_element { - ContextElement::FailMatcherNode(fail_matcher) => { - match fail_matcher.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)?; - } - }; - } - ContextElement::PreviousElementNode(_) => todo!(), - }; - - current_node = current_node.without_front(); - } - - // TODO: Make this a custom error - not(take(0usize))(i)?; - unreachable!() - } -} - -#[derive(Debug, Clone)] -pub enum ContextElement<'r> { - FailMatcherNode(FailMatcherNode<'r>), - PreviousElementNode(PreviousElementNode<'r>), -} - -#[derive(Debug, Clone)] -pub struct FailMatcherNode<'r> { - pub fail_matcher: ChainBehavior<'r>, -} - -#[derive(Debug, Clone)] -pub struct PreviousElementNode<'r> { - pub dummy: &'r str, -} - -#[derive(Clone)] -pub enum ChainBehavior<'r> { - AndParent(Option<&'r Matcher>), - IgnoreParent(Option<&'r Matcher>), -} - -impl<'r> std::fmt::Debug for ChainBehavior<'r> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let mut formatter = f.debug_struct("ChainBehavior"); - // match self { - // ChainBehavior::AndParent(_) => { - // formatter = formatter.field("type", &"AndParent"); - // } - // ChainBehavior::IgnoreParent(_) => { - // formatter = formatter.field("type", &"IgnoreParent"); - // } - // }; - formatter.finish() - } -} diff --git a/src/parser/nom_context.rs b/src/parser/nom_context.rs index 5cfdf27..3e566bf 100644 --- a/src/parser/nom_context.rs +++ b/src/parser/nom_context.rs @@ -1,56 +1,85 @@ -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>>; +use super::list::List; + 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>, +#[derive(Debug, Clone)] +pub struct ContextTree<'r> { + tree: List>, } -pub struct ContextTree<'r, T> { - head: Option>, -} - -impl<'r, T> ContextTree<'r, T> { +impl<'r> ContextTree<'r> { pub fn new() -> Self { - ContextTree { head: None } + ContextTree { tree: List::new() } } - pub fn with_additional_node(&'r self, element: T) -> ContextTree<'r, T> { - let new_node = Node { - elem: element, - next: self.head.as_ref(), - }; + pub fn with_additional_node(&self, data: ContextElement<'r>) -> ContextTree<'r> { + let new_list = self.tree.push_front(data); + ContextTree { tree: new_list } + } - ContextTree { - head: Some(new_node), + pub fn check_fail_matcher<'s>( + &'r self, + i: &'s str, + ) -> IResult<&'s str, &'s str, VerboseError<&'s str>> { + // TODO: Can I do this without incrementing reference counters? Perhaps via implementing an iterator over the list? + let mut current_node = self.tree.clone(); + while !current_node.is_empty() { + let context_element = current_node + .get_data() + .expect("While looop proves its Some()"); + match context_element { + ContextElement::FailMatcherNode(fail_matcher) => { + match fail_matcher.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)?; + } + }; + } + ContextElement::PreviousElementNode(_) => todo!(), + }; + + current_node = current_node.without_front(); } + + // TODO: Make this a custom error + not(take(0usize))(i)?; + unreachable!() } } +#[derive(Debug, Clone)] pub enum ContextElement<'r> { FailMatcherNode(FailMatcherNode<'r>), PreviousElementNode(PreviousElementNode<'r>), } +#[derive(Debug, Clone)] pub struct FailMatcherNode<'r> { pub fail_matcher: ChainBehavior<'r>, } +#[derive(Debug, Clone)] pub struct PreviousElementNode<'r> { pub dummy: &'r str, } @@ -61,77 +90,17 @@ pub enum ChainBehavior<'r> { 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> { +impl<'r> std::fmt::Debug for ChainBehavior<'r> { 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) - } - } + let mut formatter = f.debug_struct("ChainBehavior"); + // match self { + // ChainBehavior::AndParent(_) => { + // formatter = formatter.field("type", &"AndParent"); + // } + // ChainBehavior::IgnoreParent(_) => { + // formatter = formatter.field("type", &"IgnoreParent"); + // } + // }; + formatter.finish() } } diff --git a/src/parser/text_element_parser.rs b/src/parser/text_element_parser.rs index af55966..786ad49 100644 --- a/src/parser/text_element_parser.rs +++ b/src/parser/text_element_parser.rs @@ -5,10 +5,10 @@ use std::rc::Rc; use crate::parser::parser_with_context::parser_with_context; use crate::parser::text::paragraph_end; -use super::new_context::ChainBehavior; -use super::new_context::ContextElement; -use super::new_context::ContextTree; -use super::new_context::FailMatcherNode; +use super::nom_context::ChainBehavior; +use super::nom_context::ContextElement; +use super::nom_context::ContextTree; +use super::nom_context::FailMatcherNode; use super::text::bold_end; use super::text::bold_start; use super::text::line_break; @@ -133,12 +133,12 @@ fn recognize_bold_end(input: &str) -> Res<&str, &str> { } fn flat_bold<'s, 'r>(context: Context<'r>, i: &'s str) -> Res<&'s str, Bold<'s>> { - let new_context = + let nom_context = context.with_additional_node(ContextElement::FailMatcherNode(FailMatcherNode { fail_matcher: ChainBehavior::AndParent(Some(&recognize_bold_end)), })); - // let new_context = context.with_additional_fail_matcher(&recognize_bold_end); - let text_element_parser = parser_with_context!(flat_text_element)(new_context); + // let nom_context = context.with_additional_fail_matcher(&recognize_bold_end); + let text_element_parser = parser_with_context!(flat_text_element)(nom_context); let (remaining, captured) = recognize(tuple(( bold_start, many_till(text_element_parser, bold_end), @@ -152,12 +152,12 @@ fn recognize_link_end(input: &str) -> Res<&str, &str> { } fn flat_link<'s, 'r>(context: Context<'r>, i: &'s str) -> Res<&'s str, Link<'s>> { - let new_context = + let nom_context = context.with_additional_node(ContextElement::FailMatcherNode(FailMatcherNode { fail_matcher: ChainBehavior::AndParent(Some(&recognize_link_end)), })); - // let new_context = context.with_additional_fail_matcher(&recognize_link_end); - let text_element_parser = parser_with_context!(flat_text_element)(new_context); + // let nom_context = context.with_additional_fail_matcher(&recognize_link_end); + let text_element_parser = parser_with_context!(flat_text_element)(nom_context); let (remaining, captured) = recognize(tuple(( link_start, many_till(text_element_parser, link_end),