Fix handling affiliated keywords before invalid paragraphs.

This commit is contained in:
Tom Alexander
2023-10-04 23:40:38 -04:00
parent 65eda08843
commit 1351577c5a
5 changed files with 62 additions and 10 deletions

View File

@@ -14,7 +14,7 @@ use crate::error::MyError;
pub(crate) type BracketDepth = i16;
#[derive(Copy, Clone)]
#[derive(Copy, Clone, PartialEq)]
pub(crate) struct OrgSource<'s> {
full_source: &'s str,
start: usize,

View File

@@ -12,12 +12,16 @@ use super::keyword::affiliated_keyword;
use super::org_source::OrgSource;
use super::util::blank_line;
use super::util::get_consumed;
use super::util::get_has_affiliated_keyword;
use super::util::get_name;
use crate::context::parser_with_context;
use crate::context::ContextElement;
use crate::context::ExitClass;
use crate::context::ExitMatcherNode;
use crate::context::HasAffiliatedKeywordInner;
use crate::context::RefContext;
use crate::error::CustomError;
use crate::error::MyError;
use crate::error::Res;
use crate::parser::object_parser::standard_set_object;
use crate::parser::util::exit_matcher_parser;
@@ -30,12 +34,18 @@ pub(crate) fn paragraph<'b, 'g, 'r, 's>(
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Paragraph<'s>> {
let (input, affiliated_keywords) = many0(affiliated_keyword)(input)?;
let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Gamma,
exit_matcher: &paragraph_end,
});
let parser_context = context.with_additional_node(&parser_context);
let contexts = [
ContextElement::HasAffiliatedKeyword(HasAffiliatedKeywordInner {
start_after_affiliated_keywords: input,
keywords: &affiliated_keywords,
}),
ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Gamma,
exit_matcher: &paragraph_end,
}),
];
let parser_context = context.with_additional_node(&contexts[0]);
let parser_context = parser_context.with_additional_node(&contexts[1]);
let standard_set_object_matcher = parser_with_context!(standard_set_object)(&parser_context);
let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context);
@@ -63,10 +73,21 @@ fn paragraph_end<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
let non_paragraph_element_matcher = parser_with_context!(detect_element(false))(context);
let regular_end = recognize(tuple((start_of_line, many1(blank_line))))(input);
if regular_end.is_ok() {
return regular_end;
}
match get_has_affiliated_keyword(context) {
Some(start_post_affiliated_keywords) if input == start_post_affiliated_keywords => {
return Err(nom::Err::Error(CustomError::MyError(MyError(
"No exit due to affiliated keywords.",
))));
}
_ => {}
}
// Check to see if input is the start of a HasAffiliatedKeyword
alt((
recognize(tuple((start_of_line, many1(blank_line)))),
recognize(non_paragraph_element_matcher),
recognize(parser_with_context!(detect_element(false))(context)),
eof,
))(input)
}

View File

@@ -284,3 +284,21 @@ pub(crate) fn get_name<'s>(affiliated_keywords: &Vec<Keyword<'s>>) -> Option<&'s
.last();
name_keyword.map(|kw| kw.value)
}
pub(crate) fn get_has_affiliated_keyword<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
) -> Option<OrgSource<'s>> {
for context in context.iter() {
match context {
ContextElement::HasAffiliatedKeyword(inner) => {
if !inner.keywords.is_empty() {
return Some(inner.start_after_affiliated_keywords);
} else {
return None;
}
}
_ => {}
}
}
None
}