Accounting for the blank lines at the head of documents and comments plus property drawer at the head of the zeroth section.

This commit is contained in:
Tom Alexander 2023-04-19 18:37:39 -04:00
parent 1deb53f1a3
commit b557b9ca5d
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
4 changed files with 62 additions and 6 deletions

View File

@ -3,7 +3,6 @@ name = "toy"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
license = "0BSD" license = "0BSD"
default-run = "toy"
[lib] [lib]
name = "organic" name = "organic"

View File

@ -6,3 +6,20 @@
:PROPERTIES: :PROPERTIES:
:FOO: bar :FOO: bar
:END: :END:
* Spaces turn property drawers into regular drawers
:PROPERTIES:
:FOO: bar
:END:
* Comments turn property drawers into regular drawers
# Comment
:PROPERTIES:
:FOO: bar
:END:
* Baseline
:PROPERTIES:
:FOO: bar
:END:

View File

@ -1,3 +1,4 @@
use crate::parser::property_drawer::property_drawer;
use nom::branch::alt; use nom::branch::alt;
use nom::bytes::complete::tag; use nom::bytes::complete::tag;
use nom::character::complete::line_ending; use nom::character::complete::line_ending;
@ -13,12 +14,14 @@ use nom::multi::many1_count;
use nom::multi::many_till; use nom::multi::many_till;
use nom::sequence::tuple; use nom::sequence::tuple;
use crate::parser::comment::comment;
use crate::parser::element::element; use crate::parser::element::element;
use crate::parser::exiting::ExitClass; use crate::parser::exiting::ExitClass;
use crate::parser::object::standard_set_object; use crate::parser::object::standard_set_object;
use crate::parser::parser_context::ContextElement; use crate::parser::parser_context::ContextElement;
use crate::parser::parser_context::ContextTree; use crate::parser::parser_context::ContextTree;
use crate::parser::parser_context::ExitMatcherNode; use crate::parser::parser_context::ExitMatcherNode;
use crate::parser::util::blank_line;
use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting; use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting;
use super::element::Element; use super::element::Element;
@ -92,9 +95,10 @@ pub fn document(input: &str) -> Res<&str, Document> {
let initial_context: ContextTree<'_, '_> = ContextTree::new(); let initial_context: ContextTree<'_, '_> = ContextTree::new();
let document_context = let document_context =
initial_context.with_additional_node(ContextElement::DocumentRoot(input)); initial_context.with_additional_node(ContextElement::DocumentRoot(input));
let section_matcher = parser_with_context!(section)(&document_context); let zeroth_section_matcher = parser_with_context!(zeroth_section)(&document_context);
let heading_matcher = parser_with_context!(heading)(&document_context); let heading_matcher = parser_with_context!(heading)(&document_context);
let (remaining, zeroth_section) = opt(section_matcher)(input)?; let (remaining, _blank_lines) = many0(blank_line)(input)?;
let (remaining, zeroth_section) = opt(zeroth_section_matcher)(remaining)?;
let (remaining, children) = many0(heading_matcher)(remaining)?; let (remaining, children) = many0(heading_matcher)(remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
@ -107,6 +111,39 @@ pub fn document(input: &str) -> Res<&str, Document> {
)) ))
} }
#[tracing::instrument(ret, level = "debug")]
fn zeroth_section<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, Section<'s>> {
// TODO: The zeroth section is specialized so it probably needs its own parser
let parser_context = context
.with_additional_node(ContextElement::ConsumeTrailingWhitespace(true))
.with_additional_node(ContextElement::Context("section"))
.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Document,
exit_matcher: &section_end,
}));
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)),
))(input)?;
let (remaining, (mut children, _exit_contents)) = verify(
many_till(element_matcher, exit_matcher),
|(children, _exit_contents)| !children.is_empty(),
)(remaining)?;
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) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
Ok((remaining, Section { source, children }))
}
#[tracing::instrument(ret, level = "debug")] #[tracing::instrument(ret, level = "debug")]
fn section<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, Section<'s>> { fn section<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, Section<'s>> {
// TODO: The zeroth section is specialized so it probably needs its own parser // TODO: The zeroth section is specialized so it probably needs its own parser

View File

@ -1,5 +1,8 @@
foo
:drawername:
:end:
# Blank lines and comments can come before property drawers in the zeroth section
:PROPERTIES:
:FOO: bar
:END: