diff --git a/src/parser/document.rs b/src/parser/document.rs index 309e2ae..77ed1a0 100644 --- a/src/parser/document.rs +++ b/src/parser/document.rs @@ -121,20 +121,33 @@ fn zeroth_section<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s s class: ExitClass::Document, exit_matcher: §ion_end, })); + let without_consuming_whitespace_context = + parser_context.with_additional_node(ContextElement::ConsumeTrailingWhitespace(false)); + let element_matcher = parser_with_context!(element)(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); let (remaining, (comment_element, property_drawer_element)) = tuple(( - opt(parser_with_context!(comment)(&parser_context)), - opt(parser_with_context!(property_drawer)(&parser_context)), + opt(parser_with_context!(comment)( + &without_consuming_whitespace_context, + )), + opt(parser_with_context!(property_drawer)( + &without_consuming_whitespace_context, + )), ))(input)?; let (remaining, (mut children, _exit_contents)) = verify( many_till(element_matcher, exit_matcher), - |(children, _exit_contents)| !children.is_empty(), + |(children, _exit_contents)| { + !children.is_empty() || property_drawer_element.is_some() || comment_element.is_some() + }, )(remaining)?; - property_drawer_element.map(Element::PropertyDrawer).map(|ele| children.insert(0, ele)); - comment_element.map(Element::Comment).map(|ele| children.insert(0, ele)); + property_drawer_element + .map(Element::PropertyDrawer) + .map(|ele| children.insert(0, ele)); + comment_element + .map(Element::Comment) + .map(|ele| children.insert(0, ele)); // children.insert(0, item) let (remaining, _trailing_ws) = @@ -156,10 +169,15 @@ fn section<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, Sec })); let element_matcher = parser_with_context!(element)(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); - let (remaining, (children, _exit_contents)) = verify( + let (remaining, property_drawer_element) = + opt(parser_with_context!(property_drawer)(&parser_context))(input)?; + let (remaining, (mut children, _exit_contents)) = verify( many_till(element_matcher, exit_matcher), - |(children, _exit_contents)| !children.is_empty(), - )(input)?; + |(children, _exit_contents)| !children.is_empty() || property_drawer_element.is_some(), + )(remaining)?; + property_drawer_element + .map(Element::PropertyDrawer) + .map(|ele| children.insert(0, ele)); let (remaining, _trailing_ws) = maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; diff --git a/src/parser/element.rs b/src/parser/element.rs index 2938884..e3a2c4e 100644 --- a/src/parser/element.rs +++ b/src/parser/element.rs @@ -13,7 +13,6 @@ use super::lesser_element::Comment; use super::lesser_element::Paragraph; use super::paragraph::paragraph; use super::plain_list::plain_list; -use super::property_drawer::property_drawer; use super::source::Source; use super::Context; use super::Drawer; @@ -123,7 +122,6 @@ pub fn non_paragraph_element<'r, 's>( let dynamic_block_matcher = parser_with_context!(dynamic_block)(context); let footnote_definition_matcher = parser_with_context!(footnote_definition)(context); let comment_matcher = parser_with_context!(comment)(context); - let property_drawer_matcher = parser_with_context!(property_drawer)(context); let drawer_matcher = parser_with_context!(drawer)(context); alt(( map(plain_list_matcher, Element::PlainList), @@ -131,7 +129,6 @@ pub fn non_paragraph_element<'r, 's>( map(dynamic_block_matcher, Element::DynamicBlock), map(footnote_definition_matcher, Element::FootnoteDefinition), map(comment_matcher, Element::Comment), - map(property_drawer_matcher, Element::PropertyDrawer), map(drawer_matcher, Element::Drawer), ))(input) } diff --git a/src/parser/property_drawer.rs b/src/parser/property_drawer.rs index c6ad8f5..f8283c6 100644 --- a/src/parser/property_drawer.rs +++ b/src/parser/property_drawer.rs @@ -76,13 +76,14 @@ fn property_drawer_end<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res< recognize(tuple(( parser_with_context!(start_of_line)(context), space0, - tag(":end:"), + tag_no_case(":end:"), space0, alt((line_ending, eof)), )))(input) } -pub fn node_property<'r, 's>( +#[tracing::instrument(ret, level = "debug")] +fn node_property<'r, 's>( context: Context<'r, 's>, input: &'s str, ) -> Res<&'s str, NodeProperty<'s>> { @@ -106,7 +107,8 @@ pub fn node_property<'r, 's>( )) } Err(_) => { - let (remaining, (_ws, value)) = tuple((space1, is_not("\r\n")))(remaining)?; + let (remaining, (_ws, value, _line_ending)) = + tuple((space1, is_not("\r\n"), line_ending))(remaining)?; let source = get_consumed(input, remaining); Ok(( remaining, @@ -120,10 +122,7 @@ pub fn node_property<'r, 's>( } #[tracing::instrument(ret, level = "debug")] -pub fn node_property_name<'r, 's>( - context: Context<'r, 's>, - input: &'s str, -) -> Res<&'s str, &'s str> { +fn node_property_name<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, &'s str> { let parser_context = context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { class: ExitClass::Beta, @@ -140,7 +139,7 @@ pub fn node_property_name<'r, 's>( } #[tracing::instrument(ret, level = "debug")] -pub fn node_property_name_end<'r, 's>( +fn node_property_name_end<'r, 's>( context: Context<'r, 's>, input: &'s str, ) -> Res<&'s str, &'s str> { diff --git a/toy_language.txt b/toy_language.txt index ccdae6f..e432ad0 100644 --- a/toy_language.txt +++ b/toy_language.txt @@ -3,6 +3,10 @@ # Blank lines and comments can come before property drawers in the zeroth section + + + + :PROPERTIES: :FOO: bar :END: