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.
This commit is contained in:
Tom Alexander 2023-03-23 16:40:39 -04:00
parent 7402de6a7c
commit 36210c2d7f
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
5 changed files with 24 additions and 14 deletions

View File

@ -96,6 +96,9 @@ fn _preceded_by_whitespace<'r, 's>(context: Context<'r, 's>) -> bool {
} }
ContextElement::Context(_) => {} ContextElement::Context(_) => {}
ContextElement::ListItem(_) => {} ContextElement::ListItem(_) => {}
ContextElement::DocumentRoot(_) => {
return true;
}
} }
} else { } else {
break; break;

View File

@ -43,10 +43,7 @@ where
.into_iter_until(context) .into_iter_until(context)
.filter_map(|context_element| match context_element { .filter_map(|context_element| match context_element {
ContextElement::PreviousElementNode(elem) => Some(elem.element), ContextElement::PreviousElementNode(elem) => Some(elem.element),
ContextElement::ExitMatcherNode(_) => None, _ => None,
ContextElement::Context(_) => None,
ContextElement::StartOfParagraph => None,
ContextElement::ListItem(_) => None,
}) })
.collect(); .collect();
if elements.is_empty() { 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()"); 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; current_context = next_context;
match context_element { match context_element {
ContextElement::ExitMatcherNode(_) => {}
ContextElement::StartOfParagraph => {}
ContextElement::Context(_) => {}
ContextElement::PreviousElementNode(PreviousElementNode { ContextElement::PreviousElementNode(PreviousElementNode {
element: token, element: token,
}) => { }) => {
ret.push(token); ret.push(token);
} }
ContextElement::ListItem(_) => {} _ => {}
}; };
} }
ret.reverse(); ret.reverse();

View File

@ -2,6 +2,7 @@
use super::combinator::context_many1; use super::combinator::context_many1;
use super::error::Res; use super::error::Res;
use super::paragraph::paragraph; use super::paragraph::paragraph;
use super::parser_context::ContextElement;
use super::parser_context::ContextTree; use super::parser_context::ContextTree;
use super::token::Paragraph; use super::token::Paragraph;
use super::token::Token; use super::token::Token;
@ -14,7 +15,9 @@ type UnboundMatcher<'r, 's, I, O, E> = dyn Fn(Context<'r, 's>, I) -> IResult<I,
pub fn document(input: &str) -> Res<&str, Vec<Paragraph>> { pub fn document(input: &str) -> Res<&str, Vec<Paragraph>> {
let initial_context: ContextTree<'_, '_> = ContextTree::new(); 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 let paragraphs = tokens
.into_iter() .into_iter()
.map(|token| match token { .map(|token| match token {

View File

@ -94,6 +94,7 @@ impl<'r, 's> ContextTree<'r, 's> {
#[derive(Debug)] #[derive(Debug)]
pub enum ContextElement<'r, 's> { pub enum ContextElement<'r, 's> {
DocumentRoot(&'s str),
ExitMatcherNode(ExitMatcherNode<'r>), ExitMatcherNode(ExitMatcherNode<'r>),
PreviousElementNode(PreviousElementNode<'s>), PreviousElementNode(PreviousElementNode<'s>),
Context(&'r str), Context(&'r str),

View File

@ -1,15 +1,24 @@
use super::parser_context::ContextElement; use super::parser_context::ContextElement;
use super::Context; 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 { pub fn in_section<'r, 's, 'x>(context: Context<'r, 's>, section_name: &'x str) -> bool {
for thing in context.iter() { for thing in context.iter() {
match thing.get_data() { match thing.get_data() {
ContextElement::ExitMatcherNode(_) => {}
ContextElement::PreviousElementNode(_) => {}
ContextElement::Context(name) if *name == section_name => return true, 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 false