From 36210c2d7f9e5a23f392aaf6a3a98fe6b81ace0d Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Thu, 23 Mar 2023 16:40:39 -0400 Subject: [PATCH] Add a DocumentRoot context element storing the original full document. This might be used for look-behind instead of storing previous element nodes in the context tree. --- src/parser/bold.rs | 3 +++ src/parser/combinator.rs | 10 ++-------- src/parser/document.rs | 5 ++++- src/parser/parser_context.rs | 1 + src/parser/util.rs | 19 ++++++++++++++----- 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/parser/bold.rs b/src/parser/bold.rs index a8dc00a..004e7f0 100644 --- a/src/parser/bold.rs +++ b/src/parser/bold.rs @@ -96,6 +96,9 @@ fn _preceded_by_whitespace<'r, 's>(context: Context<'r, 's>) -> bool { } ContextElement::Context(_) => {} ContextElement::ListItem(_) => {} + ContextElement::DocumentRoot(_) => { + return true; + } } } else { break; diff --git a/src/parser/combinator.rs b/src/parser/combinator.rs index 4b99f84..5cb3102 100644 --- a/src/parser/combinator.rs +++ b/src/parser/combinator.rs @@ -43,10 +43,7 @@ where .into_iter_until(context) .filter_map(|context_element| match context_element { ContextElement::PreviousElementNode(elem) => Some(elem.element), - ContextElement::ExitMatcherNode(_) => None, - ContextElement::Context(_) => None, - ContextElement::StartOfParagraph => None, - ContextElement::ListItem(_) => None, + _ => None, }) .collect(); if elements.is_empty() { @@ -86,15 +83,12 @@ where let context_element = context_element.expect("We only pop off context elements created in this function, so they are all Some()"); current_context = next_context; match context_element { - ContextElement::ExitMatcherNode(_) => {} - ContextElement::StartOfParagraph => {} - ContextElement::Context(_) => {} ContextElement::PreviousElementNode(PreviousElementNode { element: token, }) => { ret.push(token); } - ContextElement::ListItem(_) => {} + _ => {} }; } ret.reverse(); diff --git a/src/parser/document.rs b/src/parser/document.rs index d9571a8..1c8dd04 100644 --- a/src/parser/document.rs +++ b/src/parser/document.rs @@ -2,6 +2,7 @@ use super::combinator::context_many1; use super::error::Res; use super::paragraph::paragraph; +use super::parser_context::ContextElement; use super::parser_context::ContextTree; use super::token::Paragraph; use super::token::Token; @@ -14,7 +15,9 @@ type UnboundMatcher<'r, 's, I, O, E> = dyn Fn(Context<'r, 's>, I) -> IResult Res<&str, Vec> { let initial_context: ContextTree<'_, '_> = ContextTree::new(); - let (remaining, tokens) = context_many1(&initial_context, paragraph)(input)?; + let document_context = + initial_context.with_additional_node(ContextElement::DocumentRoot(input)); + let (remaining, tokens) = context_many1(&document_context, paragraph)(input)?; let paragraphs = tokens .into_iter() .map(|token| match token { diff --git a/src/parser/parser_context.rs b/src/parser/parser_context.rs index 44fc9e1..1ffe709 100644 --- a/src/parser/parser_context.rs +++ b/src/parser/parser_context.rs @@ -94,6 +94,7 @@ impl<'r, 's> ContextTree<'r, 's> { #[derive(Debug)] pub enum ContextElement<'r, 's> { + DocumentRoot(&'s str), ExitMatcherNode(ExitMatcherNode<'r>), PreviousElementNode(PreviousElementNode<'s>), Context(&'r str), diff --git a/src/parser/util.rs b/src/parser/util.rs index 3600c13..7cee250 100644 --- a/src/parser/util.rs +++ b/src/parser/util.rs @@ -1,15 +1,24 @@ use super::parser_context::ContextElement; use super::Context; +/// Check if we are below a section of the given section type regardless of depth pub fn in_section<'r, 's, '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 - ContextElement::ListItem(_) => {} + _ => {} + } + } + false +} + +/// Checks if we are currently an immediate child of the given section type +pub fn immediate_in_section<'r, 's, 'x>(context: Context<'r, 's>, section_name: &'x str) -> bool { + for thing in context.iter() { + match thing.get_data() { + ContextElement::Context(name) if *name == section_name => return true, + ContextElement::Context(name) if *name != section_name => return false, + _ => {} } } false