diff --git a/src/context/context.rs b/src/context/context.rs index b49d76ed..ba2befb5 100644 --- a/src/context/context.rs +++ b/src/context/context.rs @@ -22,9 +22,6 @@ pub(crate) enum ContextElement<'r, 's> { /// Stores the name of the current element to prevent directly nesting elements of the same type. 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. ConsumeTrailingWhitespace(bool), diff --git a/src/parser/text_markup.rs b/src/parser/text_markup.rs index caa6b5f2..c771ba9c 100644 --- a/src/parser/text_markup.rs +++ b/src/parser/text_markup.rs @@ -4,11 +4,14 @@ use nom::character::complete::anychar; use nom::character::complete::multispace1; use nom::character::complete::one_of; use nom::character::complete::space0; +use nom::combinator::all_consuming; use nom::combinator::map; +use nom::combinator::map_parser; use nom::combinator::not; use nom::combinator::peek; use nom::combinator::recognize; use nom::combinator::verify; +use nom::multi::many1; use nom::multi::many_till; use nom::sequence::terminated; #[cfg(feature = "tracing")] @@ -17,15 +20,18 @@ use tracing::span; use super::object_parser::standard_set_object; use super::org_source::OrgSource; use super::radio_link::RematchObject; -use super::util::in_object_section; +use super::util::confine_context; use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting; use super::util::org_line_ending; use super::util::start_of_line; +use super::util::text_until_exit; use crate::context::parser_with_context; +use crate::context::Context; use crate::context::ContextElement; use crate::context::ContextMatcher; use crate::context::ExitClass; use crate::context::ExitMatcherNode; +use crate::context::List; use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; @@ -196,33 +202,30 @@ fn _text_markup_object<'b, 'g, 'r, 's, 'c>( input: OrgSource<'s>, marker_symbol: &'c str, ) -> Res, Vec>> { - 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, open) = tag(marker_symbol)(remaining)?; let (remaining, _peek_not_whitespace) = peek(verify(anychar, |c| !c.is_whitespace() && *c != '\u{200B}'))(remaining)?; let text_markup_end_specialized = text_markup_end(open.into(), remaining.get_byte_offset()); - let contexts = [ - ContextElement::ContextObject(marker_symbol), - ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &text_markup_end_specialized, - }), - ]; + let contexts = [ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + 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( - many_till( - parser_with_context!(standard_set_object)(&parser_context), - parser_with_context!(exit_matcher_parser)(&parser_context), + let initial_context = ContextElement::document_context(); + let initial_context = Context::new(context.get_global_settings(), List::new(&initial_context)); + + let (remaining, children) = map_parser( + verify( + parser_with_context!(text_until_exit)(&parser_context), + |text| text.len() > 0, ), - |(children, _exit_contents)| !children.is_empty(), + confine_context(|i| { + all_consuming(many1(parser_with_context!(standard_set_object)( + &initial_context, + )))(i) + }), )(remaining)?; { @@ -262,25 +265,16 @@ fn _text_markup_string<'b, 'g, 'r, 's, 'c>( input: OrgSource<'s>, marker_symbol: &'c str, ) -> Res, 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, open) = tag(marker_symbol)(remaining)?; let (remaining, _peek_not_whitespace) = peek(verify(anychar, |c| !c.is_whitespace() && *c != '\u{200B}'))(remaining)?; let text_markup_end_specialized = text_markup_end(open.into(), remaining.get_byte_offset()); - let contexts = [ - ContextElement::ContextObject(marker_symbol), - ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &text_markup_end_specialized, - }), - ]; + let contexts = [ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + 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( many_till( diff --git a/src/parser/util.rs b/src/parser/util.rs index b3d05d6f..14388ad0 100644 --- a/src/parser/util.rs +++ b/src/parser/util.rs @@ -57,20 +57,6 @@ pub(crate) fn immediate_in_section<'b, 'g, 'r, 's, 'x>( false } -/// Check if we are below a section of the given section type regardless of depth -pub(crate) 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. pub(crate) fn get_consumed<'s>(input: OrgSource<'s>, remaining: OrgSource<'s>) -> OrgSource<'s> { input.get_until(remaining)