Implement a function to detect the end of a footnote reference definition with balanced brackets.
This commit is contained in:
		
							parent
							
								
									9c2eb3b122
								
							
						
					
					
						commit
						5fb66a586d
					
				| @ -67,7 +67,7 @@ pub fn footnote_definition<'r, 's>( | ||||
| } | ||||
| 
 | ||||
| #[tracing::instrument(ret, level = "debug")] | ||||
| fn label<'s>(input: &'s str) -> Res<&'s str, &'s str> { | ||||
| pub fn label<'s>(input: &'s str) -> Res<&'s str, &'s str> { | ||||
|     alt(( | ||||
|         digit1, | ||||
|         take_while(|c| WORD_CONSTITUENT_CHARACTERS.contains(c) || "-_".contains(c)), | ||||
|  | ||||
| @ -1,13 +1,79 @@ | ||||
| use nom::branch::alt; | ||||
| use nom::bytes::complete::tag; | ||||
| use nom::bytes::complete::tag_no_case; | ||||
| 
 | ||||
| use super::parser_context::ContextElement; | ||||
| use super::Context; | ||||
| use crate::error::CustomError; | ||||
| use crate::error::MyError; | ||||
| use crate::error::Res; | ||||
| use crate::parser::FootnoteReference; | ||||
| use crate::parser::parser_context::FootnoteReferenceDefinition; | ||||
| use crate::parser::parser_with_context::parser_with_context; | ||||
| use crate::parser::util::get_consumed; | ||||
| use crate::parser::util::not_yet_implemented; | ||||
| use crate::parser::FootnoteReference; | ||||
| use crate::parser::Object; | ||||
| 
 | ||||
| #[tracing::instrument(ret, level = "debug")] | ||||
| pub fn footnote_reference<'r, 's>( | ||||
|     context: Context<'r, 's>, | ||||
|     input: &'s str, | ||||
| ) -> Res<&'s str, FootnoteReference<'s>> { | ||||
|     alt((parser_with_context!(anonymous_footnote)(context),))(input) | ||||
| } | ||||
| 
 | ||||
| #[tracing::instrument(ret, level = "debug")] | ||||
| pub fn anonymous_footnote<'r, 's>( | ||||
|     context: Context<'r, 's>, | ||||
|     input: &'s str, | ||||
| ) -> Res<&'s str, FootnoteReference<'s>> { | ||||
|     let (remaining, _) = tag_no_case("[fn::")(input)?; | ||||
| 
 | ||||
|     not_yet_implemented()?; | ||||
|     todo!() | ||||
| } | ||||
| 
 | ||||
| #[tracing::instrument(ret, level = "debug")] | ||||
| fn definition<'s>(input: &'s str) -> Res<&'s str, Vec<Object<'s>>> { | ||||
|     Ok((input, vec![])) | ||||
| } | ||||
| 
 | ||||
| #[tracing::instrument(ret, level = "debug")] | ||||
| fn footnote_definition_end<'r, 's>( | ||||
|     context: Context<'r, 's>, | ||||
|     input: &'s str, | ||||
| ) -> Res<&'s str, &'s str> { | ||||
|     let context_depth = get_bracket_depth(context).expect("This function should only be called from inside a footnote definition."); | ||||
|     let text_since_context_entry = get_consumed(context_depth.position, input); | ||||
|     let mut current_depth = context_depth.depth; | ||||
|     for c in text_since_context_entry.chars() { | ||||
|         match c { | ||||
|             '[' => {current_depth += 1;}, | ||||
|             ']' if current_depth == 0 => { | ||||
|                 panic!("Exceeded footnote reference definition bracket depth.") | ||||
|             }, | ||||
|             ']' if current_depth > 0 => { | ||||
|                 current_depth -= 1; | ||||
|             }, | ||||
|             _ => {} | ||||
|         } | ||||
|     } | ||||
|     if current_depth > 0 { | ||||
|         // Its impossible for the next character to end the footnote reference definition if we're any amount of brackets deep
 | ||||
|         return Err(nom::Err::Error(CustomError::MyError(MyError("NoFootnoteReferenceDefinitionEnd")))); | ||||
|     } | ||||
|     tag("]")(input) | ||||
| } | ||||
| 
 | ||||
| #[tracing::instrument(ret, level = "debug")] | ||||
| fn get_bracket_depth<'r, 's>( | ||||
|     context: Context<'r, 's>, | ||||
| ) -> Option<&'r FootnoteReferenceDefinition<'s>> { | ||||
|     for node in context.iter() { | ||||
|         match node.get_data() { | ||||
|             ContextElement::FootnoteReferenceDefinition(depth) => return Some(depth), | ||||
|             _ => {} | ||||
|         } | ||||
|     } | ||||
|     None | ||||
| } | ||||
|  | ||||
| @ -141,6 +141,18 @@ pub enum ContextElement<'r, 's> { | ||||
|     /// org-mode document since text needs to be re-parsed to look for
 | ||||
|     /// radio links matching the contents of radio targets.
 | ||||
|     RadioTarget(Vec<&'r Vec<Object<'s>>>), | ||||
| 
 | ||||
|     /// Stores the current bracket depth inside a footnote reference's definition.
 | ||||
|     ///
 | ||||
|     /// The definition inside a footnote reference must have balanced
 | ||||
|     /// brackets [] inside the definition, so this stores the amount
 | ||||
|     /// of opening brackets subtracted by the amount of closing
 | ||||
|     /// brackets within the definition.
 | ||||
|     ///
 | ||||
|     /// A reference to the position in the string is also included so
 | ||||
|     /// unbalanced brackets can be detected in the middle of an
 | ||||
|     /// object.
 | ||||
|     FootnoteReferenceDefinition(FootnoteReferenceDefinition<'s>), | ||||
| } | ||||
| 
 | ||||
| pub struct ExitMatcherNode<'r> { | ||||
| @ -148,6 +160,12 @@ pub struct ExitMatcherNode<'r> { | ||||
|     pub class: ExitClass, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct FootnoteReferenceDefinition<'s> { | ||||
|     pub position: &'s str, | ||||
|     pub depth: usize, | ||||
| } | ||||
| 
 | ||||
| impl<'r> std::fmt::Debug for ExitMatcherNode<'r> { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         let mut formatter = f.debug_struct("ExitMatcherNode"); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tom Alexander
						Tom Alexander