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::branch::alt;
|
||||||
use nom::combinator::map;
|
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::clock::clock;
|
||||||
use super::comment::comment;
|
use super::comment::comment;
|
||||||
@ -75,43 +80,104 @@ fn _element<'b, 'g, 'r, 's>(
|
|||||||
let paragraph_matcher = parser_with_context!(paragraph)(context);
|
let paragraph_matcher = parser_with_context!(paragraph)(context);
|
||||||
let latex_environment_matcher = parser_with_context!(latex_environment)(context);
|
let latex_environment_matcher = parser_with_context!(latex_environment)(context);
|
||||||
|
|
||||||
let (remaining, mut element) = match alt((
|
let (mut remaining, mut maybe_element) = {
|
||||||
map(plain_list_matcher, Element::PlainList),
|
#[cfg(feature = "tracing")]
|
||||||
greater_block_matcher,
|
let span = span!(tracing::Level::DEBUG, "Main element block");
|
||||||
map(dynamic_block_matcher, Element::DynamicBlock),
|
#[cfg(feature = "tracing")]
|
||||||
map(footnote_definition_matcher, Element::FootnoteDefinition),
|
let _enter = span.enter();
|
||||||
map(comment_matcher, Element::Comment),
|
|
||||||
map(drawer_matcher, Element::Drawer),
|
opt(alt((
|
||||||
map(table_matcher, Element::Table),
|
map(plain_list_matcher, Element::PlainList),
|
||||||
map(verse_block_matcher, Element::VerseBlock),
|
greater_block_matcher,
|
||||||
map(comment_block_matcher, Element::CommentBlock),
|
map(dynamic_block_matcher, Element::DynamicBlock),
|
||||||
map(example_block_matcher, Element::ExampleBlock),
|
map(footnote_definition_matcher, Element::FootnoteDefinition),
|
||||||
map(export_block_matcher, Element::ExportBlock),
|
map(comment_matcher, Element::Comment),
|
||||||
map(src_block_matcher, Element::SrcBlock),
|
map(drawer_matcher, Element::Drawer),
|
||||||
map(clock_matcher, Element::Clock),
|
map(table_matcher, Element::Table),
|
||||||
map(diary_sexp_matcher, Element::DiarySexp),
|
map(verse_block_matcher, Element::VerseBlock),
|
||||||
map(fixed_width_area_matcher, Element::FixedWidthArea),
|
map(comment_block_matcher, Element::CommentBlock),
|
||||||
map(horizontal_rule_matcher, Element::HorizontalRule),
|
map(example_block_matcher, Element::ExampleBlock),
|
||||||
map(latex_environment_matcher, Element::LatexEnvironment),
|
map(export_block_matcher, Element::ExportBlock),
|
||||||
map(babel_keyword_matcher, Element::BabelCall),
|
map(src_block_matcher, Element::SrcBlock),
|
||||||
map(keyword_matcher, Element::Keyword),
|
map(clock_matcher, Element::Clock),
|
||||||
))(input)
|
map(diary_sexp_matcher, Element::DiarySexp),
|
||||||
{
|
map(fixed_width_area_matcher, Element::FixedWidthArea),
|
||||||
the_ok @ Ok(_) => the_ok,
|
map(horizontal_rule_matcher, Element::HorizontalRule),
|
||||||
Err(_) => {
|
map(latex_environment_matcher, Element::LatexEnvironment),
|
||||||
if can_be_paragraph {
|
map(babel_keyword_matcher, Element::BabelCall),
|
||||||
match map(paragraph_matcher, Element::Paragraph)(input) {
|
map(keyword_matcher, Element::Keyword),
|
||||||
the_ok @ Ok(_) => the_ok,
|
)))(input)?
|
||||||
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)
|
if maybe_element.is_none() && can_be_paragraph {
|
||||||
}
|
#[cfg(feature = "tracing")]
|
||||||
}
|
let span = span!(tracing::Level::DEBUG, "Paragraph with affiliated keyword.");
|
||||||
} else {
|
#[cfg(feature = "tracing")]
|
||||||
map(affiliated_keyword, Element::Keyword)(input)
|
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;
|
||||||
}
|
}
|
||||||
}?;
|
}
|
||||||
|
|
||||||
|
// 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) =
|
let (remaining, _trailing_ws) =
|
||||||
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
|
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
|
||||||
|
Loading…
Reference in New Issue
Block a user