Implement check_exit_matcher.

This commit is contained in:
Tom Alexander
2023-09-03 00:05:47 -04:00
parent 8502a8830d
commit 15e8d1ab77
5 changed files with 191 additions and 73 deletions

View File

@@ -17,8 +17,6 @@ use nom::multi::many_till;
use nom::multi::separated_list1;
use nom::sequence::tuple;
use super::element::Element;
use super::object::Object;
use super::org_source::convert_error;
use super::org_source::OrgSource;
use super::token::AllTokensIterator;
@@ -26,6 +24,14 @@ use super::token::Token;
use super::util::exit_matcher_parser;
use super::util::get_consumed;
use super::util::start_of_line;
use crate::context::parser_with_context;
use crate::context::Context;
use crate::context::ContextElement;
use crate::context::ExitClass;
use crate::context::ExitMatcherNode;
use crate::context::GlobalSettings;
use crate::context::List;
use crate::context::RefContext;
use crate::error::Res;
use crate::parser::comment::comment;
use crate::parser::element_parser::element;
@@ -34,11 +40,19 @@ use crate::parser::planning::planning;
use crate::parser::property_drawer::property_drawer;
use crate::parser::util::blank_line;
use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::types::Document;
use crate::types::DocumentElement;
use crate::types::Element;
use crate::types::Heading;
use crate::types::Object;
use crate::types::Section;
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
#[allow(dead_code)]
pub fn document(input: &str) -> Res<&str, Document> {
let initial_context = Context::default();
let global_settings = GlobalSettings::default();
let initial_context = ContextElement::document_context();
let initial_context = Context::new(&global_settings, List::new(&initial_context));
let wrapped_input = OrgSource::new(input);
let (remaining, document) = _document(&initial_context, wrapped_input)
.map(|(rem, out)| (Into::<&str>::into(rem), out))
@@ -58,9 +72,9 @@ pub fn document(input: &str) -> Res<&str, Document> {
.map(|rt| &rt.children)
.collect();
if !all_radio_targets.is_empty() {
let initial_context = initial_context
.with_additional_node(ContextElement::RadioTarget(all_radio_targets));
let (remaining, document) = _document(&initial_context, wrapped_input)
let parser_context = ContextElement::RadioTarget(all_radio_targets);
let parser_context = initial_context.with_additional_node(&parser_context);
let (remaining, document) = _document(&parser_context, wrapped_input)
.map(|(rem, out)| (Into::<&str>::into(rem), out))
.map_err(convert_error)?;
return Ok((remaining.into(), document));
@@ -96,15 +110,21 @@ fn zeroth_section<'r, 's>(
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, 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 {
let contexts = [
ContextElement::ConsumeTrailingWhitespace(true),
ContextElement::Context("section"),
ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Document,
exit_matcher: &section_end,
}));
}),
];
let parser_context = context
.with_additional_node(&contexts[0])
.with_additional_node(&contexts[1])
.with_additional_node(&contexts[2]);
let without_consuming_whitespace_context = ContextElement::ConsumeTrailingWhitespace(false);
let without_consuming_whitespace_context =
parser_context.with_additional_node(ContextElement::ConsumeTrailingWhitespace(false));
parser_context.with_additional_node(&without_consuming_whitespace_context);
let element_matcher = parser_with_context!(element(true))(&parser_context);
let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context);
@@ -150,13 +170,18 @@ fn section<'r, 's>(
mut input: OrgSource<'s>,
) -> Res<OrgSource<'s>, 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 {
let contexts = [
ContextElement::ConsumeTrailingWhitespace(true),
ContextElement::Context("section"),
ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Document,
exit_matcher: &section_end,
}));
}),
];
let parser_context = context
.with_additional_node(&contexts[0])
.with_additional_node(&contexts[1])
.with_additional_node(&contexts[2]);
let element_matcher = parser_with_context!(element(true))(&parser_context);
let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context);
let (mut remaining, (planning_element, property_drawer_element)) = tuple((
@@ -204,8 +229,9 @@ fn section_end<'r, 's>(
const fn heading(
parent_stars: usize,
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, Heading<'s>> {
move |context: Context, input: OrgSource<'_>| _heading(context, input, parent_stars)
) -> impl for<'b, 'r, 's> Fn(RefContext<'b, 'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, Heading<'s>>
{
move |context, input: OrgSource<'_>| _heading(context, input, parent_stars)
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
@@ -270,11 +296,11 @@ fn headline<'r, 's>(
Vec<&'s str>,
),
> {
let parser_context =
context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Document,
exit_matcher: &headline_title_end,
}));
let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Document,
exit_matcher: &headline_title_end,
});
let parser_context = context.with_additional_node(&parser_context);
let standard_set_object_matcher = parser_with_context!(standard_set_object)(&parser_context);
let (