From e7a08775ebb6fc7fde9261c94a9874d2b7b55111 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 22 Apr 2023 17:12:49 -0400 Subject: [PATCH] First stab at latex environment parser. --- src/parser/latex_environment.rs | 66 ++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/src/parser/latex_environment.rs b/src/parser/latex_environment.rs index c6cbb426..78d02099 100644 --- a/src/parser/latex_environment.rs +++ b/src/parser/latex_environment.rs @@ -1,5 +1,22 @@ +use nom::branch::alt; +use nom::bytes::complete::tag; +use nom::bytes::complete::tag_no_case; +use nom::bytes::complete::take_while1; +use nom::character::complete::line_ending; +use nom::character::complete::space0; +use nom::combinator::eof; +use nom::combinator::map; +use nom::sequence::tuple; + +use super::util::get_consumed; use super::Context; use crate::error::Res; +use crate::parser::exiting::ExitClass; +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::start_of_line; use crate::parser::LatexEnvironment; #[tracing::instrument(ret, level = "debug")] @@ -7,5 +24,52 @@ pub fn latex_environment<'r, 's>( context: Context<'r, 's>, input: &'s str, ) -> Res<&'s str, LatexEnvironment<'s>> { - todo!() + start_of_line(context, input)?; + let (remaining, _leading_whitespace) = space0(input)?; + let (remaining, (_opening, name, _open_close_brace, _ws, _line_ending)) = tuple(( + tag_no_case(r#"\begin{"#), + name, + tag("}"), + space0, + line_ending, + ))(remaining)?; + + let latex_environment_end_specialized = latex_environment_end(name); + let parser_context = + context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Beta, + exit_matcher: &latex_environment_end_specialized, + })); + + let (remaining, _contents) = map(parser_with_context!(plain_text)(&parser_context), |obj| { + obj.source + })(remaining)?; + let (remaining, _end) = latex_environment_end_specialized(&parser_context, remaining)?; + + let source = get_consumed(input, remaining); + Ok((remaining, LatexEnvironment { source })) +} + +#[tracing::instrument(ret, level = "debug")] +fn name<'s>(input: &'s str) -> Res<&'s str, &'s str> { + take_while1(|c: char| c.is_alphanumeric() || c == '*')(input) +} + +fn latex_environment_end( + 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, _close_brace, _ws, _line_ending)) = tuple(( + tag_no_case(r#"\end{"#), + tag_no_case(current_name_lower.as_str()), + tag("}"), + space0, + alt((eof, line_ending)), + ))(remaining)?; + let source = get_consumed(input, remaining); + Ok((remaining, source)) + } }