From 35eff51d1b1224f6158742020e1c1f8a6e529cff Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Tue, 18 Apr 2023 20:33:01 -0400 Subject: [PATCH] First implementation moving over to the new exit matcher class system. --- src/parser/document.rs | 10 ++++--- src/parser/drawer.rs | 4 ++- src/parser/exiting.rs | 7 ++--- src/parser/footnote_definition.rs | 4 ++- src/parser/greater_block.rs | 4 ++- src/parser/paragraph.rs | 4 ++- src/parser/parser_context.rs | 45 +++++++++++-------------------- src/parser/plain_list.rs | 10 ++++--- 8 files changed, 46 insertions(+), 42 deletions(-) diff --git a/src/parser/document.rs b/src/parser/document.rs index cf5adddb..06ca8af8 100644 --- a/src/parser/document.rs +++ b/src/parser/document.rs @@ -14,6 +14,7 @@ use nom::multi::many_till; use nom::sequence::tuple; use crate::parser::element::element; +use crate::parser::exiting::ExitClass; use crate::parser::object::standard_set_object; use crate::parser::parser_context::ChainBehavior; use crate::parser::parser_context::ContextElement; @@ -114,7 +115,8 @@ fn section<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, Sec .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) .with_additional_node(ContextElement::Context("section")) .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - exit_matcher: ChainBehavior::AndParent(Some(§ion_end)), + class: ExitClass::Document, + exit_matcher: §ion_end, })); let element_matcher = parser_with_context!(element)(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); @@ -123,7 +125,8 @@ fn section<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, Sec |(children, _exit_contents)| !children.is_empty(), )(input)?; - let (remaining, _trailing_ws) = maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; + let (remaining, _trailing_ws) = + maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; let source = get_consumed(input, remaining); Ok((remaining, Section { source, children })) @@ -167,7 +170,8 @@ fn headline<'r, 's>( ) -> Res<&'s str, (usize, &'s str, Vec>, &'s str)> { let parser_context = context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - exit_matcher: ChainBehavior::AndParent(Some(&headline_end)), + class: ExitClass::Document, + exit_matcher: &headline_end, })); let standard_set_object_matcher = parser_with_context!(standard_set_object)(&parser_context); let start_of_line_matcher = parser_with_context!(start_of_line)(&parser_context); diff --git a/src/parser/drawer.rs b/src/parser/drawer.rs index 2c417e86..358f3506 100644 --- a/src/parser/drawer.rs +++ b/src/parser/drawer.rs @@ -11,6 +11,7 @@ use nom::sequence::tuple; use super::Context; use crate::parser::element::element; use crate::parser::error::Res; +use crate::parser::exiting::ExitClass; use crate::parser::parser_context::ChainBehavior; use crate::parser::parser_context::ContextElement; use crate::parser::parser_context::ExitMatcherNode; @@ -36,7 +37,8 @@ pub fn drawer<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, let parser_context = context .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - exit_matcher: ChainBehavior::AndParent(Some(&drawer_end)), + class: ExitClass::Alpha, + exit_matcher: &drawer_end, })); let element_matcher = parser_with_context!(element)(&parser_context); diff --git a/src/parser/exiting.rs b/src/parser/exiting.rs index e75b1050..c09b3e27 100644 --- a/src/parser/exiting.rs +++ b/src/parser/exiting.rs @@ -1,10 +1,11 @@ +#[derive(Debug, Copy, Clone)] pub enum ExitClass { /// Headlines and sections. - Document, + Document = 1, /// Elements who take priority over beta elements when matching. - Alpha, + Alpha = 20, /// Elements who cede priority to alpha elements when matching. - Beta, + Beta = 300, } diff --git a/src/parser/footnote_definition.rs b/src/parser/footnote_definition.rs index bc019393..7518a4e5 100644 --- a/src/parser/footnote_definition.rs +++ b/src/parser/footnote_definition.rs @@ -2,6 +2,7 @@ use super::error::Res; use super::util::WORD_CONSTITUENT_CHARACTERS; use super::Context; use crate::parser::element::element; +use crate::parser::exiting::ExitClass; use crate::parser::greater_element::FootnoteDefinition; use crate::parser::parser_context::ChainBehavior; use crate::parser::parser_context::ContextElement; @@ -37,7 +38,8 @@ pub fn footnote_definition<'r, 's>( let parser_context = context .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - exit_matcher: ChainBehavior::IgnoreParent(Some(&footnote_definition_end)), + class: ExitClass::Alpha, + exit_matcher: &footnote_definition_end, })); // TODO: The problem is we are not accounting for trailing whitespace like we do in section. Maybe it would be easier if we passed down whether or not to parse trailing whitespace into the element matcher similar to how tag takes in parameters. let element_matcher = parser_with_context!(element)(&parser_context); diff --git a/src/parser/greater_block.rs b/src/parser/greater_block.rs index 1524b978..e3f4f973 100644 --- a/src/parser/greater_block.rs +++ b/src/parser/greater_block.rs @@ -3,6 +3,7 @@ use super::Context; use crate::parser::element::element; use crate::parser::error::CustomError; use crate::parser::error::MyError; +use crate::parser::exiting::ExitClass; use crate::parser::greater_element::GreaterBlock; use crate::parser::parser_context::ChainBehavior; use crate::parser::parser_context::ContextElement; @@ -45,7 +46,8 @@ pub fn greater_block<'r, 's>( .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) .with_additional_node(ContextElement::GreaterBlock(name)) .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - exit_matcher: ChainBehavior::IgnoreParent(Some(&greater_block_end)), + class: ExitClass::Alpha, + exit_matcher: &greater_block_end, })); let element_matcher = parser_with_context!(element)(&parser_context); diff --git a/src/parser/paragraph.rs b/src/parser/paragraph.rs index 3881fe82..861fef12 100644 --- a/src/parser/paragraph.rs +++ b/src/parser/paragraph.rs @@ -6,6 +6,7 @@ use nom::multi::many1; use nom::multi::many_till; use nom::sequence::tuple; +use crate::parser::exiting::ExitClass; use crate::parser::object::standard_set_object; use crate::parser::parser_context::ChainBehavior; use crate::parser::parser_context::ContextElement; @@ -26,7 +27,8 @@ use super::Context; pub fn paragraph<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, Paragraph<'s>> { let parser_context = context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - exit_matcher: ChainBehavior::AndParent(Some(¶graph_end)), + class: ExitClass::Beta, + exit_matcher: ¶graph_end, })); let standard_set_object_matcher = parser_with_context!(standard_set_object)(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); diff --git a/src/parser/parser_context.rs b/src/parser/parser_context.rs index 9f578f94..7e247a02 100644 --- a/src/parser/parser_context.rs +++ b/src/parser/parser_context.rs @@ -1,14 +1,14 @@ use std::rc::Rc; -use nom::combinator::eof; -use nom::IResult; - use super::error::CustomError; use super::error::MyError; use super::error::Res; use super::list::List; use super::list::Node; use super::Context; +use crate::parser::exiting::ExitClass; +use nom::combinator::eof; +use nom::IResult; type Matcher = dyn for<'r, 's> Fn(Context<'r, 's>, &'s str) -> Res<&'s str, &'s str>; @@ -76,33 +76,20 @@ impl<'r, 's> ContextTree<'r, 's> { // exit_matcher: ChainBehavior::IgnoreParent(Some(&always_fail)), // })); + let mut current_class_filter = ExitClass::Beta; for current_node in self.iter() { let context_element = current_node.get_data(); match context_element { ContextElement::ExitMatcherNode(exit_matcher) => { - match exit_matcher.exit_matcher { - ChainBehavior::AndParent(Some(matcher)) => { - let local_context = ContextTree::branch_from(current_node); - let local_result = matcher(&local_context, i); - if local_result.is_ok() { - return local_result; - } + if exit_matcher.class as u32 <= current_class_filter as u32 { + current_class_filter = exit_matcher.class; + let local_context = ContextTree::branch_from(current_node); + let local_result = (exit_matcher.exit_matcher)(&local_context, i); + if local_result.is_ok() { + return local_result; } - ChainBehavior::AndParent(None) => {} - ChainBehavior::IgnoreParent(Some(matcher)) => { - let local_context = ContextTree::branch_from(current_node); - let local_result = matcher(&local_context, i); - if local_result.is_ok() { - return local_result; - } - // TODO: Make this a specific error instead of just a generic MyError - return Err(nom::Err::Error(CustomError::MyError(MyError("NoExit")))); - } - ChainBehavior::IgnoreParent(None) => { - // TODO: Make this a specific error instead of just a generic MyError - return Err(nom::Err::Error(CustomError::MyError(MyError("NoExit")))); - } - }; + } + } _ => {} }; @@ -166,9 +153,9 @@ pub enum ContextElement<'r, 's> { ConsumeTrailingWhitespace(bool), } -#[derive(Debug)] pub struct ExitMatcherNode<'r> { - pub exit_matcher: ChainBehavior<'r>, + pub exit_matcher: &'r Matcher, + pub class: ExitClass, } #[derive(Clone)] @@ -177,9 +164,9 @@ pub enum ChainBehavior<'r> { IgnoreParent(Option<&'r Matcher>), } -impl<'r> std::fmt::Debug for ChainBehavior<'r> { +impl<'r> std::fmt::Debug for ExitMatcherNode<'r> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let mut formatter = f.debug_struct("ChainBehavior"); + let mut formatter = f.debug_struct("ExitMatcherNode"); // match self { // ChainBehavior::AndParent(_) => { // formatter = formatter.field("type", &"AndParent"); diff --git a/src/parser/plain_list.rs b/src/parser/plain_list.rs index 133015c9..a030905c 100644 --- a/src/parser/plain_list.rs +++ b/src/parser/plain_list.rs @@ -8,6 +8,7 @@ use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use super::util::non_whitespace_character; use super::Context; use crate::parser::element::element; +use crate::parser::exiting::ExitClass; use crate::parser::parser_context::ChainBehavior; use crate::parser::parser_context::ContextElement; use crate::parser::parser_context::ExitMatcherNode; @@ -37,7 +38,8 @@ use tracing::span; pub fn plain_list<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, PlainList<'s>> { let parser_context = context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - exit_matcher: ChainBehavior::AndParent(Some(&plain_list_end)), + class: ExitClass::Beta, + exit_matcher: &plain_list_end, })); let without_consume_context = parser_context.with_additional_node(ContextElement::ConsumeTrailingWhitespace(false)); @@ -152,12 +154,14 @@ pub fn plain_list_item<'r, 's>( .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) .with_additional_node(ContextElement::ListItem(indent_level)) .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - exit_matcher: ChainBehavior::AndParent(Some(&plain_list_item_end)), + class: ExitClass::Beta, + exit_matcher: &plain_list_item_end, })); let without_consume_context = context .with_additional_node(ContextElement::ListItem(indent_level)) .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - exit_matcher: ChainBehavior::AndParent(Some(&plain_list_item_end)), + class: ExitClass::Beta, + exit_matcher: &plain_list_item_end, })); let with_consume_matcher = parser_with_context!(element)(&with_consume_context);