diff --git a/build.rs b/build.rs index 012312e..615d8a7 100644 --- a/build.rs +++ b/build.rs @@ -72,7 +72,6 @@ fn is_expect_fail(name: &str) -> Option<&str> { match name { "drawer_drawer_with_headline_inside" => Some("Apparently lines with :end: become their own paragraph. This odd behavior needs to be investigated more."), "element_container_priority_footnote_definition_dynamic_block" => Some("Apparently broken begin lines become their own paragraph."), - "keyword_affiliated_keyword" => Some("Affiliated keywords would have to be implemented first."), _ => None, } } diff --git a/src/parser/clock.rs b/src/parser/clock.rs index d15e69a..22d2e2c 100644 --- a/src/parser/clock.rs +++ b/src/parser/clock.rs @@ -15,7 +15,7 @@ use super::Context; use crate::error::Res; use crate::parser::parser_with_context::parser_with_context; use crate::parser::util::get_consumed; -use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting; + use crate::parser::util::start_of_line; use crate::parser::Clock; @@ -31,9 +31,6 @@ pub fn clock<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, C parser_with_context!(inactive_timestamp)(context), ))(remaining)?; - let (remaining, _trailing_ws) = - maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; - let source = get_consumed(input, remaining); Ok((remaining, Clock { source })) } diff --git a/src/parser/comment.rs b/src/parser/comment.rs index 80d5651..15a5abc 100644 --- a/src/parser/comment.rs +++ b/src/parser/comment.rs @@ -20,7 +20,7 @@ use crate::parser::parser_context::ContextElement; use crate::parser::parser_with_context::parser_with_context; use crate::parser::util::exit_matcher_parser; use crate::parser::util::immediate_in_section; -use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting; + use crate::parser::util::start_of_line; use crate::parser::Comment; @@ -38,9 +38,6 @@ pub fn comment<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, let (remaining, _remaining_lines) = many0(preceded(not(exit_matcher), comment_line_matcher))(remaining)?; - let (remaining, _trailing_ws) = - maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; - let source = get_consumed(input, remaining); Ok((remaining, Comment { source })) } diff --git a/src/parser/diary_sexp.rs b/src/parser/diary_sexp.rs index 3cf0c43..856648b 100644 --- a/src/parser/diary_sexp.rs +++ b/src/parser/diary_sexp.rs @@ -10,7 +10,7 @@ use super::sexp::sexp; use super::Context; use crate::error::Res; use crate::parser::util::get_consumed; -use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting; + use crate::parser::util::start_of_line; use crate::parser::DiarySexp; @@ -24,9 +24,6 @@ pub fn diary_sexp<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s s let (remaining, _trailing_whitespace) = recognize(tuple((space0, alt((line_ending, eof)))))(remaining)?; - let (remaining, _trailing_ws) = - maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; - let source = get_consumed(input, remaining); Ok((remaining, DiarySexp { source })) } diff --git a/src/parser/document.rs b/src/parser/document.rs index 9020903..853db11 100644 --- a/src/parser/document.rs +++ b/src/parser/document.rs @@ -124,7 +124,7 @@ fn zeroth_section<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s s let without_consuming_whitespace_context = parser_context.with_additional_node(ContextElement::ConsumeTrailingWhitespace(false)); - let element_matcher = parser_with_context!(element)(&parser_context); + let element_matcher = parser_with_context!(element(true))(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); let (remaining, comment_and_property_drawer_element) = opt(tuple(( @@ -166,9 +166,8 @@ fn section<'r, 's>(context: Context<'r, 's>, mut input: &'s str) -> Res<&'s str, class: ExitClass::Document, exit_matcher: §ion_end, })); - let element_matcher = parser_with_context!(element)(&parser_context); + let element_matcher = parser_with_context!(element(true))(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); - // TODO: Match whatever a planning is. let (mut remaining, (planning_element, property_drawer_element)) = tuple(( opt(parser_with_context!(planning)(&parser_context)), opt(parser_with_context!(property_drawer)(&parser_context)), diff --git a/src/parser/drawer.rs b/src/parser/drawer.rs index fa5db04..9c93a94 100644 --- a/src/parser/drawer.rs +++ b/src/parser/drawer.rs @@ -23,7 +23,7 @@ use crate::parser::util::blank_line; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; use crate::parser::util::immediate_in_section; -use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting; + use crate::parser::util::start_of_line; use crate::parser::util::WORD_CONSTITUENT_CHARACTERS; use crate::parser::Drawer; @@ -54,7 +54,7 @@ pub fn drawer<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, exit_matcher: &drawer_end, })); - let element_matcher = parser_with_context!(element)(&parser_context); + let element_matcher = parser_with_context!(element(true))(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); let (remaining, children) = match consumed(many_till(blank_line, exit_matcher))(remaining) { Ok((remaining, (whitespace, (_children, _exit_contents)))) => ( @@ -69,8 +69,6 @@ pub fn drawer<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, }; let (remaining, _end) = drawer_end(&parser_context, remaining)?; - let (remaining, _trailing_ws) = - maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; let source = get_consumed(input, remaining); Ok(( diff --git a/src/parser/dynamic_block.rs b/src/parser/dynamic_block.rs index 1cbe4b4..d523920 100644 --- a/src/parser/dynamic_block.rs +++ b/src/parser/dynamic_block.rs @@ -13,7 +13,7 @@ use crate::parser::util::blank_line; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; use crate::parser::util::immediate_in_section; -use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting; + use crate::parser::util::start_of_line; use crate::parser::Element; use nom::branch::alt; @@ -59,7 +59,7 @@ pub fn dynamic_block<'r, 's>( Some((_ws, parameters)) => Some(parameters), None => None, }; - let element_matcher = parser_with_context!(element)(&parser_context); + let element_matcher = parser_with_context!(element(true))(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); let (remaining, children) = match consumed(many_till(blank_line, exit_matcher))(remaining) { Ok((remaining, (whitespace, (_children, _exit_contents)))) => ( @@ -74,9 +74,6 @@ pub fn dynamic_block<'r, 's>( }; let (remaining, _end) = dynamic_block_end(&parser_context, remaining)?; - let (remaining, _trailing_ws) = - maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; - let source = get_consumed(input, remaining); Ok(( remaining, diff --git a/src/parser/element.rs b/src/parser/element.rs index f245744..233068e 100644 --- a/src/parser/element.rs +++ b/src/parser/element.rs @@ -17,6 +17,7 @@ use super::lesser_element::Paragraph; use super::lesser_element::Planning; use super::lesser_element::SrcBlock; use super::lesser_element::VerseBlock; +use super::source::SetSource; use super::source::Source; use super::Drawer; @@ -70,3 +71,31 @@ impl<'s> Source<'s> for Element<'s> { } } } + +impl<'s> SetSource<'s> for Element<'s> { + #[tracing::instrument(ret, level = "debug")] + fn set_source(&mut self, source: &'s str) { + match self { + Element::Paragraph(obj) => obj.source = source, + Element::PlainList(obj) => obj.source = source, + Element::GreaterBlock(obj) => obj.source = source, + Element::DynamicBlock(obj) => obj.source = source, + Element::FootnoteDefinition(obj) => obj.source = source, + Element::Comment(obj) => obj.source = source, + Element::Drawer(obj) => obj.source = source, + Element::PropertyDrawer(obj) => obj.source = source, + Element::Table(obj) => obj.source = source, + Element::VerseBlock(obj) => obj.source = source, + Element::CommentBlock(obj) => obj.source = source, + Element::ExampleBlock(obj) => obj.source = source, + Element::ExportBlock(obj) => obj.source = source, + Element::SrcBlock(obj) => obj.source = source, + Element::Clock(obj) => obj.source = source, + Element::DiarySexp(obj) => obj.source = source, + Element::Planning(obj) => obj.source = source, + Element::FixedWidthArea(obj) => obj.source = source, + Element::HorizontalRule(obj) => obj.source = source, + Element::Keyword(obj) => obj.source = source, + } + } +} diff --git a/src/parser/element_parser.rs b/src/parser/element_parser.rs index e2ccc9b..e435dae 100644 --- a/src/parser/element_parser.rs +++ b/src/parser/element_parser.rs @@ -16,6 +16,10 @@ use super::lesser_block::src_block; use super::lesser_block::verse_block; use super::paragraph::paragraph; use super::plain_list::plain_list; +use super::source::SetSource; +use super::util::get_consumed; +use super::util::maybe_consume_trailing_whitespace_if_not_exiting; + use super::Context; use crate::error::Res; use crate::parser::parser_with_context::parser_with_context; @@ -23,55 +27,73 @@ use crate::parser::table::org_mode_table; use nom::branch::alt; use nom::combinator::map; -#[tracing::instrument(ret, level = "debug")] -pub fn element<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, Element<'s>> { - let non_paragraph_matcher = parser_with_context!(non_paragraph_element)(context); - let paragraph_matcher = parser_with_context!(paragraph)(context); +use nom::multi::many0; - alt(( - non_paragraph_matcher, - map(paragraph_matcher, Element::Paragraph), - ))(input) -} +pub fn element( + can_be_paragraph: bool, +) -> impl for<'r, 's> Fn(Context<'r, 's>, &'s str) -> Res<&'s str, Element<'s>> { + move |context: Context, input: &str| { + let plain_list_matcher = parser_with_context!(plain_list)(context); + let greater_block_matcher = parser_with_context!(greater_block)(context); + let dynamic_block_matcher = parser_with_context!(dynamic_block)(context); + let footnote_definition_matcher = parser_with_context!(footnote_definition)(context); + let comment_matcher = parser_with_context!(comment)(context); + let drawer_matcher = parser_with_context!(drawer)(context); + let table_matcher = parser_with_context!(org_mode_table)(context); + let verse_block_matcher = parser_with_context!(verse_block)(context); + let comment_block_matcher = parser_with_context!(comment_block)(context); + let example_block_matcher = parser_with_context!(example_block)(context); + let export_block_matcher = parser_with_context!(export_block)(context); + let src_block_matcher = parser_with_context!(src_block)(context); + let clock_matcher = parser_with_context!(clock)(context); + let diary_sexp_matcher = parser_with_context!(diary_sexp)(context); + let fixed_width_area_matcher = parser_with_context!(fixed_width_area)(context); + let horizontal_rule_matcher = parser_with_context!(horizontal_rule)(context); + let keyword_matcher = parser_with_context!(keyword)(context); + let paragraph_matcher = parser_with_context!(paragraph)(context); + let (remaining, mut affiliated_keywords) = many0(keyword_matcher)(input)?; + let (remaining, mut element) = match alt(( + map(plain_list_matcher, Element::PlainList), + map(greater_block_matcher, Element::GreaterBlock), + map(dynamic_block_matcher, Element::DynamicBlock), + map(footnote_definition_matcher, Element::FootnoteDefinition), + map(comment_matcher, Element::Comment), + map(drawer_matcher, Element::Drawer), + map(table_matcher, Element::Table), + map(verse_block_matcher, Element::VerseBlock), + map(comment_block_matcher, Element::CommentBlock), + map(example_block_matcher, Element::ExampleBlock), + map(export_block_matcher, Element::ExportBlock), + map(src_block_matcher, Element::SrcBlock), + map(clock_matcher, Element::Clock), + map(diary_sexp_matcher, Element::DiarySexp), + map(fixed_width_area_matcher, Element::FixedWidthArea), + map(horizontal_rule_matcher, Element::HorizontalRule), + ))(remaining) + { + the_ok @ Ok(_) => the_ok, + Err(_) => { + if can_be_paragraph { + match map(paragraph_matcher, Element::Paragraph)(remaining) { + the_ok @ Ok(_) => the_ok, + Err(_) => { + affiliated_keywords.clear(); + map(keyword_matcher, Element::Keyword)(input) + } + } + } else { + affiliated_keywords.clear(); + map(keyword_matcher, Element::Keyword)(input) + } + } + }?; -pub fn non_paragraph_element<'r, 's>( - context: Context<'r, 's>, - input: &'s str, -) -> Res<&'s str, Element<'s>> { - let plain_list_matcher = parser_with_context!(plain_list)(context); - let greater_block_matcher = parser_with_context!(greater_block)(context); - let dynamic_block_matcher = parser_with_context!(dynamic_block)(context); - let footnote_definition_matcher = parser_with_context!(footnote_definition)(context); - let comment_matcher = parser_with_context!(comment)(context); - let drawer_matcher = parser_with_context!(drawer)(context); - let table_matcher = parser_with_context!(org_mode_table)(context); - let verse_block_matcher = parser_with_context!(verse_block)(context); - let comment_block_matcher = parser_with_context!(comment_block)(context); - let example_block_matcher = parser_with_context!(example_block)(context); - let export_block_matcher = parser_with_context!(export_block)(context); - let src_block_matcher = parser_with_context!(src_block)(context); - let clock_matcher = parser_with_context!(clock)(context); - let diary_sexp_matcher = parser_with_context!(diary_sexp)(context); - let fixed_width_area_matcher = parser_with_context!(fixed_width_area)(context); - let horizontal_rule_matcher = parser_with_context!(horizontal_rule)(context); - let keyword_matcher = parser_with_context!(keyword)(context); - alt(( - map(plain_list_matcher, Element::PlainList), - map(greater_block_matcher, Element::GreaterBlock), - map(dynamic_block_matcher, Element::DynamicBlock), - map(footnote_definition_matcher, Element::FootnoteDefinition), - map(comment_matcher, Element::Comment), - map(drawer_matcher, Element::Drawer), - map(table_matcher, Element::Table), - map(verse_block_matcher, Element::VerseBlock), - map(comment_block_matcher, Element::CommentBlock), - map(example_block_matcher, Element::ExampleBlock), - map(export_block_matcher, Element::ExportBlock), - map(src_block_matcher, Element::SrcBlock), - map(clock_matcher, Element::Clock), - map(diary_sexp_matcher, Element::DiarySexp), - map(fixed_width_area_matcher, Element::FixedWidthArea), - map(horizontal_rule_matcher, Element::HorizontalRule), - map(keyword_matcher, Element::Keyword), - ))(input) + let (remaining, _trailing_ws) = + maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; + + let source = get_consumed(input, remaining); + element.set_source(source); + + Ok((remaining, element)) + } } diff --git a/src/parser/fixed_width_area.rs b/src/parser/fixed_width_area.rs index 3a4f28c..147ef87 100644 --- a/src/parser/fixed_width_area.rs +++ b/src/parser/fixed_width_area.rs @@ -16,7 +16,7 @@ use crate::error::Res; 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::maybe_consume_trailing_whitespace_if_not_exiting; + use crate::parser::util::start_of_line; use crate::parser::FixedWidthArea; @@ -31,9 +31,6 @@ pub fn fixed_width_area<'r, 's>( let (remaining, _remaining_lines) = many0(preceded(not(exit_matcher), fixed_width_area_line_matcher))(remaining)?; - let (remaining, _trailing_ws) = - maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; - let source = get_consumed(input, remaining); Ok((remaining, FixedWidthArea { source })) } diff --git a/src/parser/footnote_definition.rs b/src/parser/footnote_definition.rs index c401b40..00f1077 100644 --- a/src/parser/footnote_definition.rs +++ b/src/parser/footnote_definition.rs @@ -14,7 +14,7 @@ use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; use crate::parser::util::immediate_in_section; use crate::parser::util::maybe_consume_trailing_whitespace; -use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting; + use crate::parser::util::start_of_line; use nom::branch::alt; use nom::bytes::complete::tag; @@ -50,14 +50,11 @@ pub fn footnote_definition<'r, 's>( exit_matcher: &footnote_definition_end, })); // TODO: The problem is we are not accounting for trailing whitespace like we do in section. Maybe it would be easier if we passed down whether or not to parse trailing whitespace into the element matcher similar to how tag takes in parameters. - let element_matcher = parser_with_context!(element)(&parser_context); + let element_matcher = parser_with_context!(element(true))(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); let (remaining, (children, _exit_contents)) = many_till(element_matcher, exit_matcher)(remaining)?; - let (remaining, _trailing_ws) = - maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; - let source = get_consumed(input, remaining); Ok(( remaining, @@ -113,6 +110,7 @@ mod tests { use crate::parser::parser_context::ContextElement; use crate::parser::parser_context::ContextTree; use crate::parser::parser_with_context::parser_with_context; + use crate::parser::Source; use super::*; @@ -126,21 +124,20 @@ line footnote."; let initial_context: ContextTree<'_, '_> = ContextTree::new(); let document_context = initial_context.with_additional_node(ContextElement::DocumentRoot(input)); - let footnote_definition_matcher = - parser_with_context!(footnote_definition)(&document_context); + let footnote_definition_matcher = parser_with_context!(element(true))(&document_context); let (remaining, first_footnote_definition) = footnote_definition_matcher(input).expect("Parse first footnote_definition"); let (remaining, second_footnote_definition) = footnote_definition_matcher(remaining).expect("Parse second footnote_definition."); assert_eq!(remaining, ""); assert_eq!( - first_footnote_definition.source, + first_footnote_definition.get_source(), "[fn:1] A footnote. " ); assert_eq!( - second_footnote_definition.source, + second_footnote_definition.get_source(), "[fn:2] A multi- line footnote." @@ -158,13 +155,12 @@ not in the footnote."; let initial_context: ContextTree<'_, '_> = ContextTree::new(); let document_context = initial_context.with_additional_node(ContextElement::DocumentRoot(input)); - let footnote_definition_matcher = - parser_with_context!(footnote_definition)(&document_context); + let footnote_definition_matcher = parser_with_context!(element(true))(&document_context); let (remaining, first_footnote_definition) = footnote_definition_matcher(input).expect("Parse first footnote_definition"); assert_eq!(remaining, "not in the footnote."); assert_eq!( - first_footnote_definition.source, + first_footnote_definition.get_source(), "[fn:2] A multi- line footnote. diff --git a/src/parser/greater_block.rs b/src/parser/greater_block.rs index 4a8f896..8ca1fe1 100644 --- a/src/parser/greater_block.rs +++ b/src/parser/greater_block.rs @@ -1,7 +1,7 @@ +use super::Context; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; -use super::Context; use crate::parser::element_parser::element; use crate::parser::exiting::ExitClass; use crate::parser::greater_element::GreaterBlock; @@ -12,7 +12,7 @@ use crate::parser::util::blank_line; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; use crate::parser::util::immediate_in_section; -use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting; + use crate::parser::util::start_of_line; use crate::parser::Element; use crate::parser::Paragraph; @@ -69,7 +69,7 @@ pub fn greater_block<'r, 's>( None => None, }; - let element_matcher = parser_with_context!(element)(&parser_context); + let element_matcher = parser_with_context!(element(true))(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); // Check for a completely empty block let (remaining, children) = match consumed(many_till(blank_line, exit_matcher))(remaining) { @@ -87,9 +87,6 @@ pub fn greater_block<'r, 's>( // Not checking if parent exit matcher is causing exit because the greater_block_end matcher asserts we matched a full greater block - let (remaining, _trailing_ws) = - maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; - let source = get_consumed(input, remaining); Ok(( remaining, diff --git a/src/parser/lesser_block.rs b/src/parser/lesser_block.rs index 7bbdacc..764a556 100644 --- a/src/parser/lesser_block.rs +++ b/src/parser/lesser_block.rs @@ -30,7 +30,7 @@ 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; -use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting; + use crate::parser::util::start_of_line; #[tracing::instrument(ret, level = "debug")] @@ -70,9 +70,6 @@ pub fn verse_block<'r, 's>( }; 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, @@ -111,9 +108,6 @@ pub fn comment_block<'r, 's>( })(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, @@ -152,9 +146,6 @@ pub fn example_block<'r, 's>( })(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, @@ -194,9 +185,6 @@ pub fn export_block<'r, 's>( })(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, @@ -233,9 +221,6 @@ pub fn src_block<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s st })(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, diff --git a/src/parser/paragraph.rs b/src/parser/paragraph.rs index b722856..ba9c557 100644 --- a/src/parser/paragraph.rs +++ b/src/parser/paragraph.rs @@ -1,4 +1,5 @@ use crate::error::Res; +use crate::parser::element_parser::element; use nom::branch::alt; use nom::combinator::eof; use nom::combinator::recognize; @@ -13,10 +14,9 @@ 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::maybe_consume_trailing_whitespace_if_not_exiting; + use crate::parser::util::start_of_line; -use super::element_parser::non_paragraph_element; use super::lesser_element::Paragraph; use super::util::blank_line; use super::util::get_consumed; @@ -39,9 +39,6 @@ pub fn paragraph<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s st // Not checking parent exit matcher because if there are any children matched then we have a valid paragraph. - let (remaining, _trailing_ws) = - maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; - let source = get_consumed(input, remaining); Ok((remaining, Paragraph { source, children })) @@ -49,7 +46,7 @@ pub fn paragraph<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s st #[tracing::instrument(ret, level = "debug")] fn paragraph_end<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, &'s str> { - let non_paragraph_element_matcher = parser_with_context!(non_paragraph_element)(context); + let non_paragraph_element_matcher = parser_with_context!(element(false))(context); let start_of_line_matcher = parser_with_context!(start_of_line)(&context); alt(( recognize(tuple((start_of_line_matcher, many1(blank_line)))), @@ -60,11 +57,11 @@ fn paragraph_end<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s st #[cfg(test)] mod tests { + use crate::parser::element_parser::element; use crate::parser::parser_context::ContextElement; use crate::parser::parser_context::ContextTree; use crate::parser::parser_with_context::parser_with_context; - - use super::*; + use crate::parser::source::Source; #[test] fn two_paragraphs() { @@ -72,12 +69,12 @@ mod tests { let initial_context: ContextTree<'_, '_> = ContextTree::new(); let document_context = initial_context.with_additional_node(ContextElement::DocumentRoot(input)); - let paragraph_matcher = parser_with_context!(paragraph)(&document_context); + let paragraph_matcher = parser_with_context!(element(true))(&document_context); let (remaining, first_paragraph) = paragraph_matcher(input).expect("Parse first paragraph"); let (remaining, second_paragraph) = paragraph_matcher(remaining).expect("Parse second paragraph."); assert_eq!(remaining, ""); - assert_eq!(first_paragraph.source, "foo bar baz\n\n"); - assert_eq!(second_paragraph.source, "lorem ipsum"); + assert_eq!(first_paragraph.get_source(), "foo bar baz\n\n"); + assert_eq!(second_paragraph.get_source(), "lorem ipsum"); } } diff --git a/src/parser/parser_with_context.rs b/src/parser/parser_with_context.rs index e5d6086..6705d47 100644 --- a/src/parser/parser_with_context.rs +++ b/src/parser/parser_with_context.rs @@ -1,5 +1,5 @@ macro_rules! parser_with_context { - ($target:ident) => { + ($target:expr) => { move |context| move |i| $target(context, i) }; } diff --git a/src/parser/plain_list.rs b/src/parser/plain_list.rs index 9f15933..d84b04a 100644 --- a/src/parser/plain_list.rs +++ b/src/parser/plain_list.rs @@ -1,7 +1,7 @@ use super::greater_element::PlainList; use super::greater_element::PlainListItem; use super::parser_with_context::parser_with_context; -use super::util::maybe_consume_trailing_whitespace_if_not_exiting; + use super::util::non_whitespace_character; use super::Context; use crate::error::CustomError; @@ -134,9 +134,6 @@ pub fn plain_list<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s s )))); } - let (remaining, _trailing_ws) = - maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; - let source = get_consumed(input, remaining); Ok((remaining, PlainList { source, children })) } @@ -164,8 +161,8 @@ pub fn plain_list_item<'r, 's>( exit_matcher: &plain_list_item_end, })); - let with_consume_matcher = parser_with_context!(element)(&with_consume_context); - let without_consume_matcher = parser_with_context!(element)(&without_consume_context); + let with_consume_matcher = parser_with_context!(element(true))(&with_consume_context); + let without_consume_matcher = parser_with_context!(element(true))(&without_consume_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&with_consume_context); let (remaining, bull) = verify(bullet, |bull: &str| bull != "*" || indent_level > 0)(remaining)?; @@ -187,12 +184,12 @@ pub fn plain_list_item<'r, 's>( Err(_) => { let (remaining, _ws) = space1(remaining)?; let (remaining, (mut contents, final_element)) = many_till( - with_consume_matcher, + &with_consume_matcher, alt(( - terminated(without_consume_matcher, exit_matcher), + terminated(&without_consume_matcher, exit_matcher), preceded( - peek(tuple((with_consume_matcher, exit_matcher))), - without_consume_matcher, + peek(tuple((&with_consume_matcher, exit_matcher))), + &without_consume_matcher, ), )), )(remaining)?; @@ -373,7 +370,7 @@ mod tests { let initial_context: ContextTree<'_, '_> = ContextTree::new(); let document_context = initial_context.with_additional_node(ContextElement::DocumentRoot(input)); - let plain_list_matcher = parser_with_context!(plain_list)(&document_context); + let plain_list_matcher = parser_with_context!(element(true))(&document_context); let (remaining, result) = plain_list_matcher(input).expect("Should parse the plain list successfully."); assert_eq!(remaining, " ipsum\n"); @@ -399,7 +396,7 @@ baz"#; let initial_context: ContextTree<'_, '_> = ContextTree::new(); let document_context = initial_context.with_additional_node(ContextElement::DocumentRoot(input)); - let plain_list_matcher = parser_with_context!(plain_list)(&document_context); + let plain_list_matcher = parser_with_context!(element(true))(&document_context); let (remaining, result) = plain_list_matcher(input).expect("Should parse the plain list successfully."); assert_eq!(remaining, "baz"); @@ -430,7 +427,7 @@ dolar"#; let initial_context: ContextTree<'_, '_> = ContextTree::new(); let document_context = initial_context.with_additional_node(ContextElement::DocumentRoot(input)); - let plain_list_matcher = parser_with_context!(plain_list)(&document_context); + let plain_list_matcher = parser_with_context!(element(true))(&document_context); let (remaining, result) = plain_list_matcher(input).expect("Should parse the plain list successfully."); assert_eq!(remaining, "dolar"); diff --git a/src/parser/source.rs b/src/parser/source.rs index c8e5417..5e0b8c4 100644 --- a/src/parser/source.rs +++ b/src/parser/source.rs @@ -1,3 +1,6 @@ pub trait Source<'s> { fn get_source(&'s self) -> &'s str; } +pub trait SetSource<'s> { + fn set_source(&mut self, source: &'s str); +} diff --git a/src/parser/table.rs b/src/parser/table.rs index 0ac55f3..275e754 100644 --- a/src/parser/table.rs +++ b/src/parser/table.rs @@ -24,7 +24,7 @@ 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::maybe_consume_trailing_whitespace_if_not_exiting; + use crate::parser::util::start_of_line; use crate::parser::Table; @@ -51,8 +51,6 @@ pub fn org_mode_table<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<& many_till(org_mode_table_row_matcher, exit_matcher)(input)?; // TODO: Consume trailing formulas - let (remaining, _trailing_ws) = - maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; let source = get_consumed(input, remaining); Ok((remaining, Table { source, children })) diff --git a/toy_language.txt b/toy_language.txt index 7de30a5..2323b99 100644 --- a/toy_language.txt +++ b/toy_language.txt @@ -1 +1,8 @@ -%%(foo) +#+name: foo +#+caption: bar +#+caption: baz +[[file:lorem/ipsum.png]] + +#+name: cat +#+caption: dog +[[file:lorem/ipsum.png]]