Pass context into fail matchers.

This commit is contained in:
Tom Alexander 2022-12-15 20:32:00 -05:00
parent 23e567ca93
commit b27be8eab1
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
2 changed files with 18 additions and 15 deletions

View File

@ -8,8 +8,12 @@ use nom::IResult;
use super::list::List;
use super::list::Node;
use super::token::Token;
use super::Context;
type Matcher = dyn for<'s> Fn(&'s str) -> IResult<&'s str, &'s str, VerboseError<&'s str>>;
type Matcher = dyn for<'r, 's> Fn(
Context<'r, 's>,
&'s str,
) -> IResult<&'s str, &'s str, VerboseError<&'s str>>;
#[derive(Debug, Clone)]
pub struct ContextTree<'r, 's> {
@ -39,10 +43,10 @@ impl<'r, 's> ContextTree<'r, 's> {
self.tree.iter()
}
pub fn check_fail_matcher<'b>(
pub fn check_fail_matcher(
&'r self,
i: &'b str,
) -> IResult<&'b str, &'b str, VerboseError<&'b str>> {
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() {
@ -53,14 +57,14 @@ impl<'r, 's> ContextTree<'r, 's> {
ContextElement::FailMatcherNode(fail_matcher) => {
match fail_matcher.fail_matcher {
ChainBehavior::AndParent(Some(matcher)) => {
let local_result = matcher(i);
let local_result = matcher(self, i);
if local_result.is_ok() {
return local_result;
}
}
ChainBehavior::AndParent(None) => {}
ChainBehavior::IgnoreParent(Some(matcher)) => {
let local_result = matcher(i);
let local_result = matcher(self, i);
if local_result.is_ok() {
return local_result;
}

View File

@ -127,7 +127,7 @@ fn can_start_bold<'s, 'r>(context: Context<'r, 's>) -> bool {
loop {
if let Some((i, ctx)) = context_iterator.next() {
match ctx.get_data() {
ContextElement::FailMatcherNode(_) => {},
ContextElement::FailMatcherNode(_) => {}
ContextElement::PreviousElementNode(previous_element_node) => {
match &previous_element_node.element {
Token::TextElement(text_element) => {
@ -139,12 +139,12 @@ fn can_start_bold<'s, 'r>(context: Context<'r, 's>) -> bool {
TextElement::Bold(_) => return false,
TextElement::Link(_) => return false,
};
},
}
};
},
}
ContextElement::StartOfParagraph => {
return true;
},
}
}
} else {
break;
@ -173,7 +173,7 @@ pub fn context_bold_end<'s, 'r>(context: Context<'r, 's>, input: &'s str) -> Res
tag(" "),
tag("\t"),
tag("\n"),
|i| context.check_fail_matcher(i)
|i| context.check_fail_matcher(i),
)))(remaining)?;
Ok((remaining, actual_match))
@ -188,7 +188,7 @@ pub fn paragraph<'s, 'r>(
let paragraph_context = context
.with_additional_node(ContextElement::StartOfParagraph)
.with_additional_node(ContextElement::FailMatcherNode(FailMatcherNode {
fail_matcher: ChainBehavior::AndParent(Some(&paragraph_end)),
fail_matcher: ChainBehavior::AndParent(Some(&context_paragraph_end)),
}));
let (remaining, (many, till)) =
context_many_till(&paragraph_context, flat_text_element, context_paragraph_end)(i)?;
@ -222,13 +222,12 @@ fn flat_text_element<'s, 'r>(
))(i)
}
fn recognize_bold_end(input: &str) -> Res<&str, &str> {
fn recognize_bold_end<'s, 'r>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, &'s str> {
recognize(bold_end)(input)
}
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);
// TODO: I need to make the fail matchers take in context so I can use context_bold_end. Otherwise this is ending bolds early just because it hits an asterisk.
let nom_context =
context.with_additional_node(ContextElement::FailMatcherNode(FailMatcherNode {
fail_matcher: ChainBehavior::AndParent(Some(&recognize_bold_end)),
@ -240,7 +239,7 @@ fn flat_bold<'s, 'r>(context: Context<'r, 's>, i: &'s str) -> Res<&'s str, Bold<
Ok((remaining, ret))
}
fn recognize_link_end(input: &str) -> Res<&str, &str> {
fn recognize_link_end<'s, 'r>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, &'s str> {
recognize(link_end)(input)
}