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::branch::alt; | ||||||
| use nom::combinator::map; | 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::clock::clock; | ||||||
| use super::comment::comment; | use super::comment::comment; | ||||||
| @ -75,7 +80,13 @@ fn _element<'b, 'g, 'r, 's>( | |||||||
|     let paragraph_matcher = parser_with_context!(paragraph)(context); |     let paragraph_matcher = parser_with_context!(paragraph)(context); | ||||||
|     let latex_environment_matcher = parser_with_context!(latex_environment)(context); |     let latex_environment_matcher = parser_with_context!(latex_environment)(context); | ||||||
| 
 | 
 | ||||||
|     let (remaining, mut element) = match alt(( |     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), |             map(plain_list_matcher, Element::PlainList), | ||||||
|             greater_block_matcher, |             greater_block_matcher, | ||||||
|             map(dynamic_block_matcher, Element::DynamicBlock), |             map(dynamic_block_matcher, Element::DynamicBlock), | ||||||
| @ -95,23 +106,78 @@ fn _element<'b, 'g, 'r, 's>( | |||||||
|             map(latex_environment_matcher, Element::LatexEnvironment), |             map(latex_environment_matcher, Element::LatexEnvironment), | ||||||
|             map(babel_keyword_matcher, Element::BabelCall), |             map(babel_keyword_matcher, Element::BabelCall), | ||||||
|             map(keyword_matcher, Element::Keyword), |             map(keyword_matcher, Element::Keyword), | ||||||
|     ))(input) |         )))(input)? | ||||||
|     { |     }; | ||||||
|         the_ok @ Ok(_) => the_ok, | 
 | ||||||
|         Err(_) => { |     if maybe_element.is_none() && can_be_paragraph { | ||||||
|             if can_be_paragraph { |         #[cfg(feature = "tracing")] | ||||||
|                 match map(paragraph_matcher, Element::Paragraph)(input) { |         let span = span!(tracing::Level::DEBUG, "Paragraph with affiliated keyword."); | ||||||
|                     the_ok @ Ok(_) => the_ok, |         #[cfg(feature = "tracing")] | ||||||
|                     Err(_) => { |         let _enter = span.enter(); | ||||||
|                         // 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) |         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; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|             } else { | 
 | ||||||
|                 map(affiliated_keyword, Element::Keyword)(input) |     // 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) = |     let (remaining, _trailing_ws) = | ||||||
|         maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; |         maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tom Alexander
						Tom Alexander