Re-work the element parser to handle affiliated keywords before elements that cannot have affiliated keywords.
This commit is contained in:
		
							parent
							
								
									b82d4c0eca
								
							
						
					
					
						commit
						65eda08843
					
				| @ -1,5 +1,10 @@ | ||||
| use nom::branch::alt; | ||||
| use nom::combinator::map; | ||||
| use nom::combinator::opt; | ||||
| use nom::combinator::peek; | ||||
| use nom::sequence::tuple; | ||||
| #[cfg(feature = "tracing")] | ||||
| use tracing::span; | ||||
| 
 | ||||
| use super::clock::clock; | ||||
| use super::comment::comment; | ||||
| @ -75,43 +80,104 @@ fn _element<'b, 'g, 'r, 's>( | ||||
|     let paragraph_matcher = parser_with_context!(paragraph)(context); | ||||
|     let latex_environment_matcher = parser_with_context!(latex_environment)(context); | ||||
| 
 | ||||
|     let (remaining, mut element) = match alt(( | ||||
|         map(plain_list_matcher, Element::PlainList), | ||||
|         greater_block_matcher, | ||||
|         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(latex_environment_matcher, Element::LatexEnvironment), | ||||
|         map(babel_keyword_matcher, Element::BabelCall), | ||||
|         map(keyword_matcher, Element::Keyword), | ||||
|     ))(input) | ||||
|     { | ||||
|         the_ok @ Ok(_) => the_ok, | ||||
|         Err(_) => { | ||||
|             if can_be_paragraph { | ||||
|                 match map(paragraph_matcher, Element::Paragraph)(input) { | ||||
|                     the_ok @ Ok(_) => the_ok, | ||||
|                     Err(_) => { | ||||
|                         // TODO: Because this function expects a single element, if there are multiple affiliated keywords before an element that cannot have affiliated keywords, we end up re-parsing the affiliated keywords many times.
 | ||||
|                         map(affiliated_keyword, Element::Keyword)(input) | ||||
|                     } | ||||
|                 } | ||||
|             } else { | ||||
|                 map(affiliated_keyword, Element::Keyword)(input) | ||||
|             } | ||||
|     let (mut remaining, mut maybe_element) = { | ||||
|         #[cfg(feature = "tracing")] | ||||
|         let span = span!(tracing::Level::DEBUG, "Main element block"); | ||||
|         #[cfg(feature = "tracing")] | ||||
|         let _enter = span.enter(); | ||||
| 
 | ||||
|         opt(alt(( | ||||
|             map(plain_list_matcher, Element::PlainList), | ||||
|             greater_block_matcher, | ||||
|             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(latex_environment_matcher, Element::LatexEnvironment), | ||||
|             map(babel_keyword_matcher, Element::BabelCall), | ||||
|             map(keyword_matcher, Element::Keyword), | ||||
|         )))(input)? | ||||
|     }; | ||||
| 
 | ||||
|     if maybe_element.is_none() && can_be_paragraph { | ||||
|         #[cfg(feature = "tracing")] | ||||
|         let span = span!(tracing::Level::DEBUG, "Paragraph with affiliated keyword."); | ||||
|         #[cfg(feature = "tracing")] | ||||
|         let _enter = span.enter(); | ||||
| 
 | ||||
|         let (remain, paragraph_with_affiliated_keyword) = opt(map( | ||||
|             tuple(( | ||||
|                 peek(affiliated_keyword), | ||||
|                 map(paragraph_matcher, Element::Paragraph), | ||||
|             )), | ||||
|             |(_, paragraph)| paragraph, | ||||
|         ))(remaining)?; | ||||
|         if paragraph_with_affiliated_keyword.is_some() { | ||||
|             remaining = remain; | ||||
|             maybe_element = paragraph_with_affiliated_keyword; | ||||
|         } | ||||
|     }?; | ||||
|     } | ||||
| 
 | ||||
|     // if maybe_element.is_none() {
 | ||||
|     //     #[cfg(feature = "tracing")]
 | ||||
|     //     let span = span!(tracing::Level::DEBUG, "Regular keyword.");
 | ||||
|     //     #[cfg(feature = "tracing")]
 | ||||
|     //     let _enter = span.enter();
 | ||||
| 
 | ||||
|     //     let (remain, kw) = opt(map(keyword_matcher, Element::Keyword))(remaining)?;
 | ||||
|     //     if kw.is_some() {
 | ||||
|     //         maybe_element = kw;
 | ||||
|     //         remaining = remain;
 | ||||
|     //     }
 | ||||
|     // }
 | ||||
| 
 | ||||
|     if maybe_element.is_none() { | ||||
|         #[cfg(feature = "tracing")] | ||||
|         let span = span!( | ||||
|             tracing::Level::DEBUG, | ||||
|             "Affiliated keyword as regular keyword." | ||||
|         ); | ||||
|         #[cfg(feature = "tracing")] | ||||
|         let _enter = span.enter(); | ||||
| 
 | ||||
|         let (remain, kw) = opt(map(affiliated_keyword, Element::Keyword))(remaining)?; | ||||
|         if kw.is_some() { | ||||
|             maybe_element = kw; | ||||
|             remaining = remain; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if maybe_element.is_none() && can_be_paragraph { | ||||
|         #[cfg(feature = "tracing")] | ||||
|         let span = span!( | ||||
|             tracing::Level::DEBUG, | ||||
|             "Paragraph without affiliated keyword." | ||||
|         ); | ||||
|         #[cfg(feature = "tracing")] | ||||
|         let _enter = span.enter(); | ||||
| 
 | ||||
|         let (remain, paragraph_without_affiliated_keyword) = | ||||
|             map(paragraph_matcher, Element::Paragraph)(remaining)?; | ||||
|         remaining = remain; | ||||
|         maybe_element = Some(paragraph_without_affiliated_keyword); | ||||
|     } | ||||
| 
 | ||||
|     if maybe_element.is_none() { | ||||
|         return Err(nom::Err::Error(CustomError::MyError(MyError( | ||||
|             "No element.", | ||||
|         )))); | ||||
|     } | ||||
|     let mut element = maybe_element.expect("The above if-statement ensures this is Some()."); | ||||
| 
 | ||||
|     let (remaining, _trailing_ws) = | ||||
|         maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tom Alexander
						Tom Alexander