From 1d06d95bb1a788c086a47c5225165cd6212327f8 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Tue, 29 Aug 2023 13:48:10 -0400 Subject: [PATCH] Add a minimum stars figure to heading parser to reduce re-parses. --- src/parser/document.rs | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/parser/document.rs b/src/parser/document.rs index 4d84e5c2..efb85d51 100644 --- a/src/parser/document.rs +++ b/src/parser/document.rs @@ -139,7 +139,7 @@ fn _document<'r, 's>( input: OrgSource<'s>, ) -> Res, Document<'s>> { let zeroth_section_matcher = parser_with_context!(zeroth_section)(context); - let heading_matcher = parser_with_context!(heading)(context); + let heading_matcher = parser_with_context!(heading(0))(context); let (remaining, _blank_lines) = many0(blank_line)(input)?; let (remaining, zeroth_section) = opt(zeroth_section_matcher)(remaining)?; let (remaining, children) = many0(heading_matcher)(remaining)?; @@ -266,21 +266,25 @@ fn section_end<'r, 's>( recognize(detect_headline)(input) } +const fn heading( + parent_stars: usize, +) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, Heading<'s>> { + move |context: Context, input: OrgSource<'_>| _heading(context, input, parent_stars) +} + #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn heading<'r, 's>( +fn _heading<'r, 's>( context: Context<'r, 's>, input: OrgSource<'s>, + parent_stars: usize, ) -> Res, Heading<'s>> { not(|i| context.check_exit_matcher(i))(input)?; let (remaining, (star_count, _ws, maybe_todo_keyword, title, heading_tags)) = - headline(context, input)?; + headline(context, input, parent_stars)?; let section_matcher = parser_with_context!(section)(context); - let heading_matcher = parser_with_context!(heading)(context); + let heading_matcher = parser_with_context!(heading(star_count))(context); let (remaining, children) = many0(alt(( - map( - verify(heading_matcher, |h| h.stars > star_count), - DocumentElement::Heading, - ), + map(heading_matcher, DocumentElement::Heading), map(section_matcher, DocumentElement::Section), )))(remaining)?; let source = get_consumed(input, remaining); @@ -308,6 +312,7 @@ fn detect_headline<'s>(input: OrgSource<'s>) -> Res, ()> { fn headline<'r, 's>( context: Context<'r, 's>, input: OrgSource<'s>, + parent_stars: usize, ) -> Res< OrgSource<'s>, ( @@ -330,7 +335,9 @@ fn headline<'r, 's>( (_sol, star_count, ws, maybe_todo_keyword, title, maybe_tags, _ws, _line_ending), ) = tuple(( start_of_line, - many1_count(tag("*")), + verify(many1_count(tag("*")), |star_count| { + *star_count > parent_stars + }), space1, opt(tuple((heading_keyword, space1))), many1(standard_set_object_matcher),