From 33bc1af17d47b9b9e9a9c7b30370eb3070690fc0 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 15 Apr 2023 16:53:58 -0400 Subject: [PATCH] First stab at implementing comments. --- src/compare/diff.rs | 44 ++++++++++++++++++++++++++++++++++++++++++- src/parser/comment.rs | 27 +++++++++++++++++++++++--- src/parser/element.rs | 3 +++ 3 files changed, 70 insertions(+), 4 deletions(-) diff --git a/src/compare/diff.rs b/src/compare/diff.rs index 51d5100..89f600a 100644 --- a/src/compare/diff.rs +++ b/src/compare/diff.rs @@ -1,5 +1,6 @@ use super::sexp::Token; use crate::compare::util::get_offsets; +use crate::parser::Comment; use crate::parser::Document; use crate::parser::DocumentElement; use crate::parser::Element; @@ -216,7 +217,7 @@ fn compare_element<'s>( Element::PlainList(obj) => compare_plain_list(source, emacs, obj), Element::GreaterBlock(obj) => compare_greater_block(source, emacs, obj), Element::FootnoteDefinition(obj) => compare_footnote_definition(source, emacs, obj), - Element::Comment(obj) => todo!(), + Element::Comment(obj) => compare_comment(source, emacs, obj), } } @@ -454,3 +455,44 @@ fn compare_footnote_definition<'s>( children: child_status, }) } + +fn compare_comment<'s>( + source: &'s str, + emacs: &'s Token<'s>, + rust: &'s Comment<'s>, +) -> Result> { + let children = emacs.as_list()?; + let first_child = children + .first() + .ok_or("Should have at least one child.")? + .as_atom()?; + if first_child != "comment" { + return Err("Comment should correspond to a comment cell.".into()); + } + let mut child_status = Vec::new(); + let mut this_status = DiffStatus::Good; + + let attributes_child = children + .iter() + .nth(1) + .ok_or("Should have an attributes child.")?; + let attributes_map = attributes_child.as_map()?; + let begin = attributes_map + .get(":begin") + .ok_or("Missing :begin attribute.")? + .as_atom()?; + let end = attributes_map + .get(":end") + .ok_or("Missing :end attribute.")? + .as_atom()?; + let (rust_begin, rust_end) = get_offsets(source, rust); + if (rust_begin + 1).to_string() != begin || (rust_end + 1).to_string() != end { + this_status = DiffStatus::Bad; + } + + Ok(DiffResult { + status: this_status, + name: "comment".to_owned(), + children: child_status, + }) +} diff --git a/src/parser/comment.rs b/src/parser/comment.rs index 21ad4ab..d674c9b 100644 --- a/src/parser/comment.rs +++ b/src/parser/comment.rs @@ -1,15 +1,36 @@ +use nom::bytes::complete::is_not; +use nom::bytes::complete::tag; +use nom::character::complete::space0; +use nom::combinator::not; +use nom::multi::many0; +use nom::sequence::preceded; +use nom::sequence::tuple; + +use super::util::get_consumed; use super::Context; use crate::parser::error::Res; +use crate::parser::parser_with_context::parser_with_context; +use crate::parser::util::exit_matcher_parser; use crate::parser::util::start_of_line; use crate::parser::Comment; #[tracing::instrument(ret, level = "debug")] pub fn comment<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, Comment<'s>> { - start_of_line(context, input)?; - todo!() + let comment_line_matcher = parser_with_context!(comment_line)(context); + let exit_matcher = parser_with_context!(exit_matcher_parser)(context); + let (remaining, first_line) = comment_line_matcher(input)?; + let (remaining, remaining_lines) = + many0(preceded(not(exit_matcher), comment_line_matcher))(remaining)?; + let source = get_consumed(input, remaining); + Ok((remaining, Comment { source })) } +#[tracing::instrument(ret, level = "debug")] fn comment_line<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, &'s str> { start_of_line(context, input)?; - todo!() + let (remaining, _indent) = space0(input)?; + let (remaining, (_hash, _leading_whitespace, content)) = + tuple((tag("#"), space0, is_not("\r\n")))(remaining)?; + let source = get_consumed(input, remaining); + Ok((remaining, source)) } diff --git a/src/parser/element.rs b/src/parser/element.rs index 24ece5b..cb7cf19 100644 --- a/src/parser/element.rs +++ b/src/parser/element.rs @@ -1,3 +1,4 @@ +use super::comment::comment; use super::error::Res; use super::footnote_definition::footnote_definition; use super::greater_block::greater_block; @@ -90,9 +91,11 @@ pub fn non_paragraph_element<'r, 's>( let plain_list_matcher = parser_with_context!(plain_list)(context); let greater_block_matcher = parser_with_context!(greater_block)(context); let footnote_definition_matcher = parser_with_context!(footnote_definition)(context); + let comment_matcher = parser_with_context!(comment)(context); alt(( map(plain_list_matcher, Element::PlainList), map(greater_block_matcher, Element::GreaterBlock), map(footnote_definition_matcher, Element::FootnoteDefinition), + map(comment_matcher, Element::Comment), ))(input) }