Prevent nesting of text markup of the same type.
This greatly reduces the amount of detect element calls that are occurring.
This commit is contained in:
parent
6676012eb1
commit
6b82b46e09
@ -21,6 +21,9 @@ pub enum ContextElement<'r, 's> {
|
|||||||
/// Stores the name of the current element to prevent directly nesting elements of the same type.
|
/// Stores the name of the current element to prevent directly nesting elements of the same type.
|
||||||
Context(&'r str),
|
Context(&'r str),
|
||||||
|
|
||||||
|
/// Stores the name of the current object to prevent directly nesting elements of the same type.
|
||||||
|
ContextObject(&'r str),
|
||||||
|
|
||||||
/// Indicates if elements should consume the whitespace after them.
|
/// Indicates if elements should consume the whitespace after them.
|
||||||
ConsumeTrailingWhitespace(bool),
|
ConsumeTrailingWhitespace(bool),
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ use tracing::span;
|
|||||||
use super::object_parser::standard_set_object;
|
use super::object_parser::standard_set_object;
|
||||||
use super::org_source::OrgSource;
|
use super::org_source::OrgSource;
|
||||||
use super::radio_link::RematchObject;
|
use super::radio_link::RematchObject;
|
||||||
|
use super::util::in_object_section;
|
||||||
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
|
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
|
||||||
use crate::context::parser_with_context;
|
use crate::context::parser_with_context;
|
||||||
use crate::context::ContextElement;
|
use crate::context::ContextElement;
|
||||||
@ -177,16 +178,26 @@ fn _text_markup_object<'b, 'g, 'r, 's, 'c>(
|
|||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
marker_symbol: &'c str,
|
marker_symbol: &'c str,
|
||||||
) -> Res<OrgSource<'s>, Vec<Object<'s>>> {
|
) -> Res<OrgSource<'s>, Vec<Object<'s>>> {
|
||||||
|
if in_object_section(context, marker_symbol) {
|
||||||
|
return Err(nom::Err::Error(CustomError::MyError(MyError(
|
||||||
|
"Cannot nest objects of the same type".into(),
|
||||||
|
))));
|
||||||
|
}
|
||||||
|
|
||||||
let (remaining, _) = pre(context, input)?;
|
let (remaining, _) = pre(context, input)?;
|
||||||
let (remaining, open) = tag(marker_symbol)(remaining)?;
|
let (remaining, open) = tag(marker_symbol)(remaining)?;
|
||||||
let (remaining, _peek_not_whitespace) =
|
let (remaining, _peek_not_whitespace) =
|
||||||
peek(verify(anychar, |c| !c.is_whitespace() && *c != '\u{200B}'))(remaining)?;
|
peek(verify(anychar, |c| !c.is_whitespace() && *c != '\u{200B}'))(remaining)?;
|
||||||
let text_markup_end_specialized = text_markup_end(open.into());
|
let text_markup_end_specialized = text_markup_end(open.into());
|
||||||
let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
|
let contexts = [
|
||||||
class: ExitClass::Gamma,
|
ContextElement::ContextObject(marker_symbol),
|
||||||
exit_matcher: &text_markup_end_specialized,
|
ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||||
});
|
class: ExitClass::Gamma,
|
||||||
let parser_context = context.with_additional_node(&parser_context);
|
exit_matcher: &text_markup_end_specialized,
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
let parser_context = context.with_additional_node(&contexts[0]);
|
||||||
|
let parser_context = parser_context.with_additional_node(&contexts[1]);
|
||||||
|
|
||||||
let (remaining, (children, _exit_contents)) = verify(
|
let (remaining, (children, _exit_contents)) = verify(
|
||||||
many_till(
|
many_till(
|
||||||
@ -230,16 +241,25 @@ fn _text_markup_string<'b, 'g, 'r, 's, 'c>(
|
|||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
marker_symbol: &'c str,
|
marker_symbol: &'c str,
|
||||||
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||||
|
if in_object_section(context, marker_symbol) {
|
||||||
|
return Err(nom::Err::Error(CustomError::MyError(MyError(
|
||||||
|
"Cannot nest objects of the same type".into(),
|
||||||
|
))));
|
||||||
|
}
|
||||||
let (remaining, _) = pre(context, input)?;
|
let (remaining, _) = pre(context, input)?;
|
||||||
let (remaining, open) = tag(marker_symbol)(remaining)?;
|
let (remaining, open) = tag(marker_symbol)(remaining)?;
|
||||||
let (remaining, _peek_not_whitespace) =
|
let (remaining, _peek_not_whitespace) =
|
||||||
peek(verify(anychar, |c| !c.is_whitespace() && *c != '\u{200B}'))(remaining)?;
|
peek(verify(anychar, |c| !c.is_whitespace() && *c != '\u{200B}'))(remaining)?;
|
||||||
let text_markup_end_specialized = text_markup_end(open.into());
|
let text_markup_end_specialized = text_markup_end(open.into());
|
||||||
let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
|
let contexts = [
|
||||||
class: ExitClass::Gamma,
|
ContextElement::ContextObject(marker_symbol),
|
||||||
exit_matcher: &text_markup_end_specialized,
|
ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||||
});
|
class: ExitClass::Gamma,
|
||||||
let parser_context = context.with_additional_node(&parser_context);
|
exit_matcher: &text_markup_end_specialized,
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
let parser_context = context.with_additional_node(&contexts[0]);
|
||||||
|
let parser_context = parser_context.with_additional_node(&contexts[1]);
|
||||||
|
|
||||||
let (remaining, contents) = recognize(verify(
|
let (remaining, contents) = recognize(verify(
|
||||||
many_till(
|
many_till(
|
||||||
|
@ -24,7 +24,6 @@ pub const WORD_CONSTITUENT_CHARACTERS: &str =
|
|||||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||||
|
|
||||||
/// Check if we are below a section of the given section type regardless of depth
|
/// Check if we are below a section of the given section type regardless of depth
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn in_section<'b, 'g, 'r, 's, 'x>(
|
pub fn in_section<'b, 'g, 'r, 's, 'x>(
|
||||||
context: RefContext<'b, 'g, 'r, 's>,
|
context: RefContext<'b, 'g, 'r, 's>,
|
||||||
section_name: &'x str,
|
section_name: &'x str,
|
||||||
@ -53,6 +52,20 @@ pub fn immediate_in_section<'b, 'g, 'r, 's, 'x>(
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if we are below a section of the given section type regardless of depth
|
||||||
|
pub fn in_object_section<'b, 'g, 'r, 's, 'x>(
|
||||||
|
context: RefContext<'b, 'g, 'r, 's>,
|
||||||
|
section_name: &'x str,
|
||||||
|
) -> bool {
|
||||||
|
for thing in context.iter() {
|
||||||
|
match thing {
|
||||||
|
ContextElement::ContextObject(name) if *name == section_name => return true,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a slice of the string that was consumed in a parser using the original input to the parser and the remaining input after the parser.
|
/// Get a slice of the string that was consumed in a parser using the original input to the parser and the remaining input after the parser.
|
||||||
pub fn get_consumed<'s>(input: OrgSource<'s>, remaining: OrgSource<'s>) -> OrgSource<'s> {
|
pub fn get_consumed<'s>(input: OrgSource<'s>, remaining: OrgSource<'s>) -> OrgSource<'s> {
|
||||||
input.get_until(remaining)
|
input.get_until(remaining)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user