From 70f2747291ce24e3664ff6250156b913eb92cd46 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Thu, 27 Jul 2023 18:59:22 -0400 Subject: [PATCH] Implement parser for diary timestamps. --- src/parser/timestamp.rs | 45 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/src/parser/timestamp.rs b/src/parser/timestamp.rs index 3aed253..6e83eae 100644 --- a/src/parser/timestamp.rs +++ b/src/parser/timestamp.rs @@ -1,8 +1,20 @@ use nom::branch::alt; +use nom::bytes::complete::tag; +use nom::character::complete::anychar; +use nom::character::complete::one_of; +use nom::character::complete::space0; +use nom::combinator::recognize; +use nom::combinator::verify; +use nom::multi::many_till; 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::util::exit_matcher_parser; +use crate::parser::util::get_consumed; use crate::parser::util::not_yet_implemented; use crate::parser::Timestamp; @@ -26,8 +38,37 @@ fn diary_timestamp<'r, 's>( context: Context<'r, 's>, input: &'s str, ) -> Res<&'s str, Timestamp<'s>> { - not_yet_implemented()?; - todo!() + let (remaining, _) = tag("<%%(")(input)?; + let (remaining, _body) = sexp(context, remaining)?; + let (remaining, _) = tag(")>")(remaining)?; + let (remaining, _) = space0(remaining)?; + let source = get_consumed(input, remaining); + + Ok((remaining, Timestamp { source })) +} + +#[tracing::instrument(ret, level = "debug")] +fn sexp<'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, + exit_matcher: &sexp_end, + })); + + let (remaining, body) = recognize(verify( + many_till( + anychar, + parser_with_context!(exit_matcher_parser)(&parser_context), + ), + |(body, _end_contents)| !body.is_empty(), + ))(input)?; + + Ok((remaining, body)) +} + +#[tracing::instrument(ret, level = "debug")] +fn sexp_end<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, &'s str> { + alt((tag(")>"), recognize(one_of(">\n"))))(input) } #[tracing::instrument(ret, level = "debug")]