From 4c09c390fa04e01efc68ed966c127cc5b466728d Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Thu, 15 Dec 2022 21:57:21 -0500 Subject: [PATCH] Prevent bold inside bold. --- src/parser/nom_context.rs | 2 ++ src/parser/text_element_parser.rs | 27 ++++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/parser/nom_context.rs b/src/parser/nom_context.rs index 98220791..add8ad95 100644 --- a/src/parser/nom_context.rs +++ b/src/parser/nom_context.rs @@ -75,6 +75,7 @@ impl<'r, 's> ContextTree<'r, 's> { } ContextElement::PreviousElementNode(_) => {} ContextElement::StartOfParagraph => {} + ContextElement::Context(_) => {} }; } // TODO: Make this a custom error @@ -87,6 +88,7 @@ impl<'r, 's> ContextTree<'r, 's> { pub enum ContextElement<'r, 's> { ExitMatcherNode(ExitMatcherNode<'r>), PreviousElementNode(PreviousElementNode<'s>), + Context(&'r str), StartOfParagraph, } diff --git a/src/parser/text_element_parser.rs b/src/parser/text_element_parser.rs index 569e3474..876ef3ef 100644 --- a/src/parser/text_element_parser.rs +++ b/src/parser/text_element_parser.rs @@ -53,6 +53,7 @@ where O: Into>, { move |mut i: I| { + // TODO: Can I eliminate the clone? let mut current_context = context.clone(); // Despite the clone, the Rc should still point to the same value, otherwise we'll get stuck in an endless loop. assert!(current_context.ptr_eq(context)); @@ -68,6 +69,7 @@ where match context_element { ContextElement::ExitMatcherNode(_) => {} ContextElement::StartOfParagraph => {} + ContextElement::Context(_) => {} ContextElement::PreviousElementNode(PreviousElementNode { element: token, }) => { @@ -123,6 +125,23 @@ pub fn context_paragraph_end<'s, 'r>( } fn can_start_bold<'s, 'r>(context: Context<'r, 's>) -> bool { + _preceded_by_whitespace(context) && !_in_section(context, "bold") +} + +fn _in_section<'s, 'r, 'x>(context: Context<'r, 's>, section_name: &'x str) -> bool { + for thing in context.iter() { + match thing.get_data() { + ContextElement::ExitMatcherNode(_) => {} + ContextElement::PreviousElementNode(_) => {} + ContextElement::Context(name) if *name == section_name => return true, + ContextElement::Context(_) => {} + ContextElement::StartOfParagraph => {} // TODO: If we specialize this to bold then this would be a good spot to stop scanning + } + } + false +} + +fn _preceded_by_whitespace<'s, 'r>(context: Context<'r, 's>) -> bool { let mut context_iterator = context.iter().enumerate(); loop { if let Some((i, ctx)) = context_iterator.next() { @@ -145,6 +164,7 @@ fn can_start_bold<'s, 'r>(context: Context<'r, 's>) -> bool { ContextElement::StartOfParagraph => { return true; } + ContextElement::Context(_) => {} } } else { break; @@ -224,10 +244,11 @@ fn flat_text_element<'s, 'r>( fn flat_bold<'s, 'r>(context: Context<'r, 's>, i: &'s str) -> Res<&'s str, Bold<'s>> { let bold_start = parser_with_context!(context_bold_start)(&context); - let nom_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { + let nom_context = context + .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { exit_matcher: ChainBehavior::AndParent(Some(&context_bold_end)), - })); + })) + .with_additional_node(ContextElement::Context("bold")); let (remaining, captured) = recognize(tuple((bold_start, |i| { context_many_till(&nom_context, flat_text_element, context_bold_end)(i) })))(i)?;