From cf6c4bc122c7acae81356f062e2a4365822c4b5c Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Fri, 21 Apr 2023 17:32:53 -0400 Subject: [PATCH] Write a parser specifically for comment lesser blocks. --- src/parser/lesser_block.rs | 61 ++++++++++++++++++++++++++++++++++++ src/parser/lesser_element.rs | 8 +++++ 2 files changed, 69 insertions(+) diff --git a/src/parser/lesser_block.rs b/src/parser/lesser_block.rs index fdef894..509889a 100644 --- a/src/parser/lesser_block.rs +++ b/src/parser/lesser_block.rs @@ -6,6 +6,7 @@ use nom::character::complete::space0; use nom::character::complete::space1; use nom::combinator::consumed; use nom::combinator::eof; +use nom::combinator::map; use nom::combinator::opt; use nom::combinator::verify; use nom::multi::many_till; @@ -15,10 +16,12 @@ use super::error::Res; use super::Context; use crate::parser::exiting::ExitClass; use crate::parser::lesser_element::LesserBlock; +use crate::parser::lesser_element::LesserBlockComment; use crate::parser::object_parser::standard_set_object; use crate::parser::parser_context::ContextElement; use crate::parser::parser_context::ExitMatcherNode; use crate::parser::parser_with_context::parser_with_context; +use crate::parser::plain_text::plain_text; use crate::parser::util::blank_line; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; @@ -83,6 +86,47 @@ pub fn lesser_block<'r, 's>( )) } +#[tracing::instrument(ret, level = "debug")] +pub fn lesser_block_comment<'r, 's>( + context: Context<'r, 's>, + input: &'s str, +) -> Res<&'s str, LesserBlockComment<'s>> { + let (remaining, name) = lesser_block_begin("comment")(context, input)?; + let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?; + let (remaining, _nl) = line_ending(remaining)?; + let lesser_block_end_specialized = lesser_block_end("comment"); + let parser_context = context + .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) + .with_additional_node(ContextElement::Context("lesser block")) + .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Beta, + exit_matcher: &lesser_block_end_specialized, + })); + let parameters = match parameters { + Some((_ws, parameters)) => Some(parameters), + None => None, + }; + + let (remaining, contents) = map(parser_with_context!(plain_text)(&parser_context), |obj| { + obj.source + })(remaining)?; + let (remaining, _end) = lesser_block_end_specialized(&parser_context, remaining)?; + + let (remaining, _trailing_ws) = + maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; + + let source = get_consumed(input, remaining); + Ok(( + remaining, + LesserBlockComment { + source, + name, + data: parameters, + contents, + }, + )) +} + #[tracing::instrument(ret, level = "debug")] fn name<'s>(input: &'s str) -> Res<&'s str, &'s str> { is_not(" \t\r\n")(input) @@ -109,3 +153,20 @@ fn lesser_block_end( Ok((remaining, source)) } } + +fn lesser_block_begin( + current_name: &str, +) -> impl for<'r, 's> Fn(Context<'r, 's>, &'s str) -> Res<&'s str, &'s str> { + let current_name_lower = current_name.to_lowercase(); + move |context: Context, input: &str| { + start_of_line(context, input)?; + let (remaining, _leading_whitespace) = space0(input)?; + let (remaining, (_begin, name)) = tuple(( + tag_no_case("#+begin_"), + verify(name, |name: &str| { + name.to_lowercase().as_str() == current_name_lower + }), + ))(remaining)?; + Ok((remaining, name)) + } +} diff --git a/src/parser/lesser_element.rs b/src/parser/lesser_element.rs index fa7905a..7da000b 100644 --- a/src/parser/lesser_element.rs +++ b/src/parser/lesser_element.rs @@ -27,6 +27,14 @@ pub struct LesserBlock<'s> { pub children: Vec>, } +#[derive(Debug)] +pub struct LesserBlockComment<'s> { + pub source: &'s str, + pub name: &'s str, + pub data: Option<&'s str>, + pub contents: &'s str, +} + impl<'s> Paragraph<'s> { pub fn of_text(input: &'s str) -> Self { let mut objects = Vec::with_capacity(1);