diff --git a/src/parser/babel_call.rs b/src/parser/babel_call.rs index eaeae758..629113c9 100644 --- a/src/parser/babel_call.rs +++ b/src/parser/babel_call.rs @@ -28,17 +28,21 @@ use crate::error::Res; use crate::parser::util::get_consumed; use crate::parser::util::org_line_ending; use crate::types::BabelCall; +use crate::types::Keyword; #[cfg_attr( feature = "tracing", tracing::instrument(ret, level = "debug", skip(context)) )] -pub(crate) fn babel_call<'b, 'g, 'r, 's>( +pub(crate) fn babel_call<'b, 'g, 'r, 's, AK>( + affiliated_keywords: AK, + remaining: OrgSource<'s>, context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, -) -> Res, BabelCall<'s>> { - let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?; - +) -> Res, BabelCall<'s>> +where + AK: IntoIterator>, +{ start_of_line(remaining)?; let (remaining, _) = tuple((space0, tag("#+"), tag_no_case("call"), tag(":")))(remaining)?; diff --git a/src/parser/diary_sexp.rs b/src/parser/diary_sexp.rs index 698b30f0..5b2cbfe5 100644 --- a/src/parser/diary_sexp.rs +++ b/src/parser/diary_sexp.rs @@ -14,16 +14,21 @@ use crate::error::Res; use crate::parser::util::get_consumed; use crate::parser::util::start_of_line; use crate::types::DiarySexp; +use crate::types::Keyword; #[cfg_attr( feature = "tracing", tracing::instrument(ret, level = "debug", skip(context)) )] -pub(crate) fn diary_sexp<'b, 'g, 'r, 's>( +pub(crate) fn diary_sexp<'b, 'g, 'r, 's, AK>( + affiliated_keywords: AK, + remaining: OrgSource<'s>, context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, -) -> Res, DiarySexp<'s>> { - let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?; +) -> Res, DiarySexp<'s>> +where + AK: IntoIterator>, +{ start_of_line(remaining)?; let (remaining, value) = recognize(tuple((tag("%%("), is_not("\r\n"))))(remaining)?; let (remaining, _eol) = org_line_ending(remaining)?; diff --git a/src/parser/drawer.rs b/src/parser/drawer.rs index 438a0074..0123e13c 100644 --- a/src/parser/drawer.rs +++ b/src/parser/drawer.rs @@ -32,6 +32,7 @@ use crate::parser::util::start_of_line; use crate::parser::util::WORD_CONSTITUENT_CHARACTERS; use crate::types::Drawer; use crate::types::Element; +use crate::types::Keyword; use crate::types::Paragraph; use crate::types::SetSource; @@ -39,16 +40,20 @@ use crate::types::SetSource; feature = "tracing", tracing::instrument(ret, level = "debug", skip(context)) )] -pub(crate) fn drawer<'b, 'g, 'r, 's>( +pub(crate) fn drawer<'b, 'g, 'r, 's, AK>( + affiliated_keywords: AK, + remaining: OrgSource<'s>, context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, -) -> Res, Drawer<'s>> { +) -> Res, Drawer<'s>> +where + AK: IntoIterator>, +{ if immediate_in_section(context, "drawer") { return Err(nom::Err::Error(CustomError::MyError(MyError( "Cannot nest objects of the same element".into(), )))); } - let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?; start_of_line(remaining)?; let (remaining, _leading_whitespace) = space0(remaining)?; let (remaining, (_open_colon, drawer_name, _close_colon, _new_line)) = tuple(( diff --git a/src/parser/element_parser.rs b/src/parser/element_parser.rs index 141c295b..4a830eb1 100644 --- a/src/parser/element_parser.rs +++ b/src/parser/element_parser.rs @@ -101,44 +101,124 @@ fn _element<'b, 'g, 'r, 's>( element!(comment, context, input, Element::Comment); - 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 babel_keyword_matcher = parser_with_context!(babel_call)(context); - let latex_environment_matcher = parser_with_context!(latex_environment)(context); + ak_element!( + drawer, + &mut affiliated_keywords, + post_affiliated_keywords_input, + context, + input, + Element::Drawer + ); - let (remaining, maybe_element) = { - #[cfg(feature = "tracing")] - let span = span!(tracing::Level::DEBUG, "Main element block"); - #[cfg(feature = "tracing")] - let _enter = span.enter(); + ak_element!( + org_mode_table, + &mut affiliated_keywords, + post_affiliated_keywords_input, + context, + input, + Element::Table + ); - opt(alt(( - 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(latex_environment_matcher, Element::LatexEnvironment), - map(babel_keyword_matcher, Element::BabelCall), - map(keyword_matcher, Element::Keyword), - )))(input)? - }; + ak_element!( + verse_block, + &mut affiliated_keywords, + post_affiliated_keywords_input, + context, + input, + Element::VerseBlock + ); + + ak_element!( + comment_block, + &mut affiliated_keywords, + post_affiliated_keywords_input, + context, + input, + Element::CommentBlock + ); + + ak_element!( + example_block, + &mut affiliated_keywords, + post_affiliated_keywords_input, + context, + input, + Element::ExampleBlock + ); + + ak_element!( + export_block, + &mut affiliated_keywords, + post_affiliated_keywords_input, + context, + input, + Element::ExportBlock + ); + + ak_element!( + src_block, + &mut affiliated_keywords, + post_affiliated_keywords_input, + context, + input, + Element::SrcBlock + ); + + element!(clock, context, input, Element::Clock); + + ak_element!( + diary_sexp, + &mut affiliated_keywords, + post_affiliated_keywords_input, + context, + input, + Element::DiarySexp + ); + + ak_element!( + fixed_width_area, + &mut affiliated_keywords, + post_affiliated_keywords_input, + context, + input, + Element::FixedWidthArea + ); + + ak_element!( + horizontal_rule, + &mut affiliated_keywords, + post_affiliated_keywords_input, + context, + input, + Element::HorizontalRule + ); + + ak_element!( + latex_environment, + &mut affiliated_keywords, + post_affiliated_keywords_input, + context, + input, + Element::LatexEnvironment + ); + + ak_element!( + babel_call, + &mut affiliated_keywords, + post_affiliated_keywords_input, + context, + input, + Element::BabelCall + ); + + ak_element!( + keyword, + &mut affiliated_keywords, + post_affiliated_keywords_input, + context, + input, + Element::Keyword + ); if can_be_paragraph { // Paragraph with affiliated keyword @@ -162,14 +242,9 @@ fn _element<'b, 'g, 'r, 's>( ); } - if maybe_element.is_none() { - return Err(nom::Err::Error(CustomError::MyError(MyError( - "No element.", - )))); - } - let element = maybe_element.expect("The above if-statement ensures this is Some()."); - - Ok((remaining, element)) + Err(nom::Err::Error(CustomError::MyError(MyError( + "No element.", + )))) } pub(crate) const fn detect_element( diff --git a/src/parser/fixed_width_area.rs b/src/parser/fixed_width_area.rs index 0260784d..642e824d 100644 --- a/src/parser/fixed_width_area.rs +++ b/src/parser/fixed_width_area.rs @@ -21,16 +21,21 @@ use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; use crate::parser::util::start_of_line; use crate::types::FixedWidthArea; +use crate::types::Keyword; #[cfg_attr( feature = "tracing", tracing::instrument(ret, level = "debug", skip(context)) )] -pub(crate) fn fixed_width_area<'b, 'g, 'r, 's>( +pub(crate) fn fixed_width_area<'b, 'g, 'r, 's, AK>( + affiliated_keywords: AK, + remaining: OrgSource<'s>, context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, -) -> Res, FixedWidthArea<'s>> { - let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?; +) -> Res, FixedWidthArea<'s>> +where + AK: IntoIterator>, +{ let fixed_width_area_line_matcher = parser_with_context!(fixed_width_area_line)(context); let exit_matcher = parser_with_context!(exit_matcher_parser)(context); let (remaining, first_line) = fixed_width_area_line_matcher(remaining)?; diff --git a/src/parser/horizontal_rule.rs b/src/parser/horizontal_rule.rs index d331f91b..a51bb9a5 100644 --- a/src/parser/horizontal_rule.rs +++ b/src/parser/horizontal_rule.rs @@ -18,16 +18,21 @@ use crate::context::RefContext; use crate::error::Res; use crate::parser::util::start_of_line; use crate::types::HorizontalRule; +use crate::types::Keyword; #[cfg_attr( feature = "tracing", tracing::instrument(ret, level = "debug", skip(context)) )] -pub(crate) fn horizontal_rule<'b, 'g, 'r, 's>( +pub(crate) fn horizontal_rule<'b, 'g, 'r, 's, AK>( + affiliated_keywords: AK, + remaining: OrgSource<'s>, context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, -) -> Res, HorizontalRule<'s>> { - let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?; +) -> Res, HorizontalRule<'s>> +where + AK: IntoIterator>, +{ start_of_line(remaining)?; let (remaining, _rule) = recognize(tuple(( space0, diff --git a/src/parser/keyword.rs b/src/parser/keyword.rs index 4e5eb1b9..5f457f63 100644 --- a/src/parser/keyword.rs +++ b/src/parser/keyword.rs @@ -94,11 +94,15 @@ fn _filtered_keyword<'s, F: Matcher>( feature = "tracing", tracing::instrument(ret, level = "debug", skip(context)) )] -pub(crate) fn keyword<'b, 'g, 'r, 's>( +pub(crate) fn keyword<'b, 'g, 'r, 's, AK>( + affiliated_keywords: AK, + remaining: OrgSource<'s>, context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, -) -> Res, Keyword<'s>> { - let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?; +) -> Res, Keyword<'s>> +where + AK: IntoIterator>, +{ let (remaining, mut kw) = filtered_keyword(regular_keyword_key)(remaining)?; let (remaining, _trailing_ws) = maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; diff --git a/src/parser/latex_environment.rs b/src/parser/latex_environment.rs index 44002f51..f9d6c163 100644 --- a/src/parser/latex_environment.rs +++ b/src/parser/latex_environment.rs @@ -26,17 +26,22 @@ use crate::context::RefContext; use crate::error::Res; use crate::parser::util::exit_matcher_parser; use crate::parser::util::start_of_line; +use crate::types::Keyword; use crate::types::LatexEnvironment; #[cfg_attr( feature = "tracing", tracing::instrument(ret, level = "debug", skip(context)) )] -pub(crate) fn latex_environment<'b, 'g, 'r, 's>( +pub(crate) fn latex_environment<'b, 'g, 'r, 's, AK>( + affiliated_keywords: AK, + remaining: OrgSource<'s>, context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, -) -> Res, LatexEnvironment<'s>> { - let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?; +) -> Res, LatexEnvironment<'s>> +where + AK: IntoIterator>, +{ let value_start = remaining; start_of_line(remaining)?; let (remaining, _leading_whitespace) = space0(remaining)?; diff --git a/src/parser/lesser_block.rs b/src/parser/lesser_block.rs index 2870c82c..e7a3b3c3 100644 --- a/src/parser/lesser_block.rs +++ b/src/parser/lesser_block.rs @@ -41,6 +41,7 @@ use crate::types::CharOffsetInLine; use crate::types::CommentBlock; use crate::types::ExampleBlock; use crate::types::ExportBlock; +use crate::types::Keyword; use crate::types::LineNumber; use crate::types::Object; use crate::types::PlainText; @@ -53,11 +54,15 @@ use crate::types::VerseBlock; feature = "tracing", tracing::instrument(ret, level = "debug", skip(context)) )] -pub(crate) fn verse_block<'b, 'g, 'r, 's>( +pub(crate) fn verse_block<'b, 'g, 'r, 's, AK>( + affiliated_keywords: AK, + remaining: OrgSource<'s>, context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, -) -> Res, VerseBlock<'s>> { - let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?; +) -> Res, VerseBlock<'s>> +where + AK: IntoIterator>, +{ let (remaining, _) = lesser_block_begin("verse")(context, remaining)?; let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?; let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?; @@ -117,11 +122,15 @@ pub(crate) fn verse_block<'b, 'g, 'r, 's>( feature = "tracing", tracing::instrument(ret, level = "debug", skip(context)) )] -pub(crate) fn comment_block<'b, 'g, 'r, 's>( +pub(crate) fn comment_block<'b, 'g, 'r, 's, AK>( + affiliated_keywords: AK, + remaining: OrgSource<'s>, context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, -) -> Res, CommentBlock<'s>> { - let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?; +) -> Res, CommentBlock<'s>> +where + AK: IntoIterator>, +{ let (remaining, _) = lesser_block_begin("comment")(context, remaining)?; let (remaining, _parameters) = opt(tuple((space1, data)))(remaining)?; let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?; @@ -161,11 +170,15 @@ pub(crate) fn comment_block<'b, 'g, 'r, 's>( feature = "tracing", tracing::instrument(ret, level = "debug", skip(context)) )] -pub(crate) fn example_block<'b, 'g, 'r, 's>( +pub(crate) fn example_block<'b, 'g, 'r, 's, AK>( + affiliated_keywords: AK, + remaining: OrgSource<'s>, context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, -) -> Res, ExampleBlock<'s>> { - let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?; +) -> Res, ExampleBlock<'s>> +where + AK: IntoIterator>, +{ let (remaining, _) = lesser_block_begin("example")(context, remaining)?; let (remaining, parameters) = opt(alt(( map(tuple((space1, example_switches)), |(_, switches)| switches), @@ -238,11 +251,15 @@ pub(crate) fn example_block<'b, 'g, 'r, 's>( feature = "tracing", tracing::instrument(ret, level = "debug", skip(context)) )] -pub(crate) fn export_block<'b, 'g, 'r, 's>( +pub(crate) fn export_block<'b, 'g, 'r, 's, AK>( + affiliated_keywords: AK, + remaining: OrgSource<'s>, context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, -) -> Res, ExportBlock<'s>> { - let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?; +) -> Res, ExportBlock<'s>> +where + AK: IntoIterator>, +{ let (remaining, _) = lesser_block_begin("export")(context, remaining)?; // https://orgmode.org/worg/org-syntax.html#Blocks claims that export blocks must have a single word for data but testing shows no data and multi-word data still parses as an export block. let (remaining, export_type) = opt(map( @@ -290,11 +307,15 @@ pub(crate) fn export_block<'b, 'g, 'r, 's>( feature = "tracing", tracing::instrument(ret, level = "debug", skip(context)) )] -pub(crate) fn src_block<'b, 'g, 'r, 's>( +pub(crate) fn src_block<'b, 'g, 'r, 's, AK>( + affiliated_keywords: AK, + remaining: OrgSource<'s>, context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, -) -> Res, SrcBlock<'s>> { - let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?; +) -> Res, SrcBlock<'s>> +where + AK: IntoIterator>, +{ let (remaining, _) = lesser_block_begin("src")(context, remaining)?; // https://orgmode.org/worg/org-syntax.html#Blocks claims that data is mandatory and must follow the LANGUAGE SWITCHES ARGUMENTS pattern but testing has shown that no data and incorrect data here will still parse to a src block. let (remaining, language) = diff --git a/src/parser/table.rs b/src/parser/table.rs index 857a55de..e8f615da 100644 --- a/src/parser/table.rs +++ b/src/parser/table.rs @@ -29,6 +29,7 @@ use crate::context::RefContext; use crate::error::Res; use crate::parser::util::get_consumed; use crate::parser::util::start_of_line; +use crate::types::Keyword; use crate::types::Table; use crate::types::TableCell; use crate::types::TableRow; @@ -40,11 +41,15 @@ use crate::types::TableRow; feature = "tracing", tracing::instrument(ret, level = "debug", skip(context)) )] -pub(crate) fn org_mode_table<'b, 'g, 'r, 's>( +pub(crate) fn org_mode_table<'b, 'g, 'r, 's, AK>( + affiliated_keywords: AK, + remaining: OrgSource<'s>, context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, -) -> Res, Table<'s>> { - let (remaining, affiliated_keywords) = many0(affiliated_keyword)(input)?; +) -> Res, Table<'s>> +where + AK: IntoIterator>, +{ start_of_line(remaining)?; peek(tuple((space0, tag("|"))))(remaining)?;