Implement logic for checking the fail matchers without keeping mutable borrows open for longer than the execution of that function.
This commit is contained in:
		
							parent
							
								
									6b93e1c007
								
							
						
					
					
						commit
						30d6648590
					
				
							
								
								
									
										1
									
								
								language_rules.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								language_rules.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| Two line breaks to end paragraph except in code blocks | ||||
| @ -6,53 +6,69 @@ use nom::error::VerboseError; | ||||
| use nom::IResult; | ||||
| use nom::Parser; | ||||
| 
 | ||||
| pub type MatcherInner = Rc<RefCell<dyn FnMut(&str) -> IResult<&str, &str, VerboseError<&str>>>>; | ||||
| type MatcherRef = Rc<RefCell<dyn FnMut(&str) -> IResult<&str, &str, VerboseError<&str>>>>; | ||||
| 
 | ||||
| struct MatcherRef(MatcherInner); | ||||
| struct FailChecker<'a>(&'a NomContext<'a>); | ||||
| 
 | ||||
| impl MatcherRef { | ||||
|     pub fn new(func: MatcherInner) -> Self { | ||||
| impl<'a> FailChecker<'a> { | ||||
|     fn new(func: &'a NomContext<'a>) -> Self { | ||||
|         Self(func) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // type MatcherRef = Rc<RefCell<dyn FnMut(&str) -> IResult<&str, &str, VerboseError<&str>>>>;
 | ||||
| 
 | ||||
| enum ChainBehavior { | ||||
|     AndParent(Option<MatcherRef>), | ||||
|     IgnoreParent(Option<MatcherRef>), | ||||
| } | ||||
| 
 | ||||
| pub struct NomContext<'a> { | ||||
|     pub parent: Option<&'a Self>, | ||||
|     parent: Option<&'a Self>, | ||||
|     fail_matcher: ChainBehavior, | ||||
|     /// You can't have nested bolds or links in org-mode
 | ||||
|     pub can_match_bold: bool, | ||||
|     pub can_match_link: bool, | ||||
|     can_match_bold: bool, | ||||
|     can_match_link: bool, | ||||
| } | ||||
| 
 | ||||
| impl<'a> NomContext<'a> { | ||||
|     pub fn new(fail_matcher: MatcherInner) -> Self { | ||||
|     pub fn new(fail_matcher: MatcherRef) -> Self { | ||||
|         NomContext { | ||||
|             parent: None, | ||||
|             fail_matcher: ChainBehavior::IgnoreParent(Some(MatcherRef::new(fail_matcher))), | ||||
|             fail_matcher: ChainBehavior::IgnoreParent(Some(fail_matcher)), | ||||
|             can_match_bold: true, | ||||
|             can_match_link: true, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn with_additional_fail_matcher(&self, other: MatcherInner) -> NomContext { | ||||
|     pub fn with_additional_fail_matcher(&self, other: MatcherRef) -> NomContext { | ||||
|         NomContext { | ||||
|             parent: Some(&self), | ||||
|             fail_matcher: ChainBehavior::AndParent(Some(MatcherRef::new(other))), | ||||
|             fail_matcher: ChainBehavior::AndParent(Some(other)), | ||||
|             can_match_bold: self.can_match_bold, | ||||
|             can_match_link: self.can_match_link, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Parser<&str, &str, VerboseError<&str>> for MatcherRef { | ||||
|     fn parse(&mut self, i: &str) -> IResult<&str, &str, VerboseError<&str>> { | ||||
|         (&mut *self.0.borrow_mut())(i) | ||||
| impl<'a, 'b> Parser<&'b str, &'b str, VerboseError<&'b str>> for FailChecker<'a> { | ||||
|     fn parse(&mut self, i: &'b str) -> IResult<&'b str, &'b str, VerboseError<&'b str>> { | ||||
|         let fail_func = match &self.0.fail_matcher { | ||||
|             ChainBehavior::AndParent(inner) => inner, | ||||
|             ChainBehavior::IgnoreParent(inner) => inner, | ||||
|         }; | ||||
|         if let Some(inner) = fail_func { | ||||
|             let parsed = (&mut *inner.borrow_mut())(i); | ||||
|             if parsed.is_ok() { | ||||
|                 return parsed; | ||||
|             } | ||||
|         } | ||||
|         match (self.0.parent, &self.0.fail_matcher) { | ||||
|             (None, _) | (_, ChainBehavior::IgnoreParent(_)) => Err(nom::Err::Error( | ||||
|                 nom::error::make_error(i, nom::error::ErrorKind::Alt), | ||||
|             )), | ||||
|             (Some(parent), ChainBehavior::AndParent(_)) => { | ||||
|                 let mut parent_fail_checker = FailChecker::new(parent); | ||||
|                 parent_fail_checker.parse(i) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tom Alexander
						Tom Alexander