Implement the second parsing pass.
This commit is contained in:
		
							parent
							
								
									ef2c351696
								
							
						
					
					
						commit
						bd04451d58
					
				| @ -96,8 +96,35 @@ pub fn document(input: &str) -> Res<&str, Document> { | ||||
|     let initial_context: ContextTree<'_, '_> = ContextTree::new(); | ||||
|     let document_context = | ||||
|         initial_context.with_additional_node(ContextElement::DocumentRoot(input)); | ||||
|     let zeroth_section_matcher = parser_with_context!(zeroth_section)(&document_context); | ||||
|     let heading_matcher = parser_with_context!(heading)(&document_context); | ||||
|     let (remaining, document) = _document(&document_context, input)?; | ||||
|     { | ||||
|         // If there are radio targets in this document then we need to parse the entire document again with the knowledge of the radio targets.
 | ||||
|         let all_radio_targets: Vec<&Vec<Object<'_>>> = document | ||||
|             .iter_tokens() | ||||
|             .filter_map(|tkn| match tkn { | ||||
|                 Token::Object(obj) => Some(obj), | ||||
|                 _ => None, | ||||
|             }) | ||||
|             .filter_map(|obj| match obj { | ||||
|                 Object::RadioTarget(rt) => Some(rt), | ||||
|                 _ => None, | ||||
|             }) | ||||
|             .map(|rt| &rt.children) | ||||
|             .collect(); | ||||
|         if !all_radio_targets.is_empty() { | ||||
|             let document_context = document_context | ||||
|                 .with_additional_node(ContextElement::RadioTarget(all_radio_targets)); | ||||
|             let (remaining, document) = _document(&document_context, input)?; | ||||
|             return Ok((remaining, document)); | ||||
|         } | ||||
|     } | ||||
|     Ok((remaining, document)) | ||||
| } | ||||
| 
 | ||||
| #[tracing::instrument(ret, level = "debug")] | ||||
| pub fn _document<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, Document<'s>> { | ||||
|     let zeroth_section_matcher = parser_with_context!(zeroth_section)(context); | ||||
|     let heading_matcher = parser_with_context!(heading)(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)?; | ||||
| @ -268,14 +295,13 @@ impl<'s> Document<'s> { | ||||
| 
 | ||||
| impl<'s> Heading<'s> { | ||||
|     pub fn iter_tokens<'r>(&'r self) -> impl Iterator<Item = Token<'r, 's>> { | ||||
|         self.title.iter().map(Token::Object).chain(self.children.iter().map( | ||||
|             |de| { | ||||
|                 match de { | ||||
|                     DocumentElement::Heading(obj) => Token::Heading(obj), | ||||
|                     DocumentElement::Section(obj) => Token::Section(obj), | ||||
|                 } | ||||
|             } | ||||
|         )) | ||||
|         self.title | ||||
|             .iter() | ||||
|             .map(Token::Object) | ||||
|             .chain(self.children.iter().map(|de| match de { | ||||
|                 DocumentElement::Heading(obj) => Token::Heading(obj), | ||||
|                 DocumentElement::Section(obj) => Token::Section(obj), | ||||
|             })) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -140,7 +140,7 @@ pub enum ContextElement<'r, 's> { | ||||
|     /// If any are found, this will force a 2nd parse through the
 | ||||
|     /// org-mode document since text needs to be re-parsed to look for
 | ||||
|     /// radio links matching the contents of radio targets.
 | ||||
|     RadioTarget(Vec<Vec<Object<'s>>>), | ||||
|     RadioTarget(Vec<&'r Vec<Object<'s>>>), | ||||
| } | ||||
| 
 | ||||
| pub struct ExitMatcherNode<'r> { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tom Alexander
						Tom Alexander