Re-work the element parser to handle affiliated keywords before elements that cannot have affiliated keywords.
This commit is contained in:
parent
b82d4c0eca
commit
65eda08843
@ -1,5 +1,10 @@
|
||||
use nom::branch::alt;
|
||||
use nom::combinator::map;
|
||||
use nom::combinator::opt;
|
||||
use nom::combinator::peek;
|
||||
use nom::sequence::tuple;
|
||||
#[cfg(feature = "tracing")]
|
||||
use tracing::span;
|
||||
|
||||
use super::clock::clock;
|
||||
use super::comment::comment;
|
||||
@ -75,7 +80,13 @@ fn _element<'b, 'g, 'r, 's>(
|
||||
let paragraph_matcher = parser_with_context!(paragraph)(context);
|
||||
let latex_environment_matcher = parser_with_context!(latex_environment)(context);
|
||||
|
||||
let (remaining, mut element) = match alt((
|
||||
let (mut remaining, mut maybe_element) = {
|
||||
#[cfg(feature = "tracing")]
|
||||
let span = span!(tracing::Level::DEBUG, "Main element block");
|
||||
#[cfg(feature = "tracing")]
|
||||
let _enter = span.enter();
|
||||
|
||||
opt(alt((
|
||||
map(plain_list_matcher, Element::PlainList),
|
||||
greater_block_matcher,
|
||||
map(dynamic_block_matcher, Element::DynamicBlock),
|
||||
@ -95,23 +106,78 @@ fn _element<'b, 'g, 'r, 's>(
|
||||
map(latex_environment_matcher, Element::LatexEnvironment),
|
||||
map(babel_keyword_matcher, Element::BabelCall),
|
||||
map(keyword_matcher, Element::Keyword),
|
||||
))(input)
|
||||
{
|
||||
the_ok @ Ok(_) => the_ok,
|
||||
Err(_) => {
|
||||
if can_be_paragraph {
|
||||
match map(paragraph_matcher, Element::Paragraph)(input) {
|
||||
the_ok @ Ok(_) => the_ok,
|
||||
Err(_) => {
|
||||
// TODO: Because this function expects a single element, if there are multiple affiliated keywords before an element that cannot have affiliated keywords, we end up re-parsing the affiliated keywords many times.
|
||||
map(affiliated_keyword, Element::Keyword)(input)
|
||||
)))(input)?
|
||||
};
|
||||
|
||||
if maybe_element.is_none() && can_be_paragraph {
|
||||
#[cfg(feature = "tracing")]
|
||||
let span = span!(tracing::Level::DEBUG, "Paragraph with affiliated keyword.");
|
||||
#[cfg(feature = "tracing")]
|
||||
let _enter = span.enter();
|
||||
|
||||
let (remain, paragraph_with_affiliated_keyword) = opt(map(
|
||||
tuple((
|
||||
peek(affiliated_keyword),
|
||||
map(paragraph_matcher, Element::Paragraph),
|
||||
)),
|
||||
|(_, paragraph)| paragraph,
|
||||
))(remaining)?;
|
||||
if paragraph_with_affiliated_keyword.is_some() {
|
||||
remaining = remain;
|
||||
maybe_element = paragraph_with_affiliated_keyword;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
map(affiliated_keyword, Element::Keyword)(input)
|
||||
|
||||
// if maybe_element.is_none() {
|
||||
// #[cfg(feature = "tracing")]
|
||||
// let span = span!(tracing::Level::DEBUG, "Regular keyword.");
|
||||
// #[cfg(feature = "tracing")]
|
||||
// let _enter = span.enter();
|
||||
|
||||
// let (remain, kw) = opt(map(keyword_matcher, Element::Keyword))(remaining)?;
|
||||
// if kw.is_some() {
|
||||
// maybe_element = kw;
|
||||
// remaining = remain;
|
||||
// }
|
||||
// }
|
||||
|
||||
if maybe_element.is_none() {
|
||||
#[cfg(feature = "tracing")]
|
||||
let span = span!(
|
||||
tracing::Level::DEBUG,
|
||||
"Affiliated keyword as regular keyword."
|
||||
);
|
||||
#[cfg(feature = "tracing")]
|
||||
let _enter = span.enter();
|
||||
|
||||
let (remain, kw) = opt(map(affiliated_keyword, Element::Keyword))(remaining)?;
|
||||
if kw.is_some() {
|
||||
maybe_element = kw;
|
||||
remaining = remain;
|
||||
}
|
||||
}
|
||||
}?;
|
||||
|
||||
if maybe_element.is_none() && can_be_paragraph {
|
||||
#[cfg(feature = "tracing")]
|
||||
let span = span!(
|
||||
tracing::Level::DEBUG,
|
||||
"Paragraph without affiliated keyword."
|
||||
);
|
||||
#[cfg(feature = "tracing")]
|
||||
let _enter = span.enter();
|
||||
|
||||
let (remain, paragraph_without_affiliated_keyword) =
|
||||
map(paragraph_matcher, Element::Paragraph)(remaining)?;
|
||||
remaining = remain;
|
||||
maybe_element = Some(paragraph_without_affiliated_keyword);
|
||||
}
|
||||
|
||||
if maybe_element.is_none() {
|
||||
return Err(nom::Err::Error(CustomError::MyError(MyError(
|
||||
"No element.",
|
||||
))));
|
||||
}
|
||||
let mut element = maybe_element.expect("The above if-statement ensures this is Some().");
|
||||
|
||||
let (remaining, _trailing_ws) =
|
||||
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
|
||||
|
Loading…
Reference in New Issue
Block a user