refactor(tazjin/rlox): Add error plumbing in parser functions
Change-Id: I7ae3d721f76d8d69043f5ed077abbc70a18cbd92 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2233 Reviewed-by: tazjin <mail@tazj.in> Tested-by: BuildkiteCI
This commit is contained in:
		
							parent
							
								
									5fcff11eae
								
							
						
					
					
						commit
						28002fcea5
					
				
					 1 changed files with 21 additions and 29 deletions
				
			
		|  | @ -5,6 +5,7 @@ | ||||||
| //
 | //
 | ||||||
| // My Rust implementation skips this step because it's unnecessary, we
 | // My Rust implementation skips this step because it's unnecessary, we
 | ||||||
| // have real types.
 | // have real types.
 | ||||||
|  | use crate::errors::{Error, ErrorKind}; | ||||||
| use crate::scanner::{Token, TokenKind}; | use crate::scanner::{Token, TokenKind}; | ||||||
| 
 | 
 | ||||||
| // AST
 | // AST
 | ||||||
|  | @ -60,22 +61,23 @@ struct Parser<'a> { | ||||||
|     current: usize, |     current: usize, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type ExprResult<'a> = Result<Expr<'a>, Error>; | ||||||
|  | 
 | ||||||
| impl<'a> Parser<'a> { | impl<'a> Parser<'a> { | ||||||
|     // recursive-descent parser functions
 |     // recursive-descent parser functions
 | ||||||
| 
 | 
 | ||||||
|     fn expression(&mut self) -> Expr<'a> { |     fn expression(&mut self) -> ExprResult<'a> { | ||||||
|         self.equality() |         self.equality() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn equality(&mut self) -> Expr<'a> { |     fn equality(&mut self) -> ExprResult<'a> { | ||||||
|         self.binary_operator( |         self.binary_operator( | ||||||
|             &[TokenKind::BangEqual, TokenKind::EqualEqual], |             &[TokenKind::BangEqual, TokenKind::EqualEqual], | ||||||
|             Self::comparison, |             Self::comparison, | ||||||
|             Self::comparison, |  | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn comparison(&mut self) -> Expr<'a> { |     fn comparison(&mut self) -> ExprResult<'a> { | ||||||
|         self.binary_operator( |         self.binary_operator( | ||||||
|             &[ |             &[ | ||||||
|                 TokenKind::Greater, |                 TokenKind::Greater, | ||||||
|  | @ -84,38 +86,29 @@ impl<'a> Parser<'a> { | ||||||
|                 TokenKind::LessEqual, |                 TokenKind::LessEqual, | ||||||
|             ], |             ], | ||||||
|             Self::term, |             Self::term, | ||||||
|             Self::term, |  | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn term(&mut self) -> Expr<'a> { |     fn term(&mut self) -> ExprResult<'a> { | ||||||
|         self.binary_operator( |         self.binary_operator(&[TokenKind::Minus, TokenKind::Plus], Self::factor) | ||||||
|             &[TokenKind::Minus, TokenKind::Plus], |  | ||||||
|             Self::factor, |  | ||||||
|             Self::factor, |  | ||||||
|         ) |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn factor(&mut self) -> Expr<'a> { |     fn factor(&mut self) -> ExprResult<'a> { | ||||||
|         self.binary_operator( |         self.binary_operator(&[TokenKind::Slash, TokenKind::Star], Self::unary) | ||||||
|             &[TokenKind::Slash, TokenKind::Star], |  | ||||||
|             Self::unary, |  | ||||||
|             Self::unary, |  | ||||||
|         ) |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn unary(&mut self) -> Expr<'a> { |     fn unary(&mut self) -> ExprResult<'a> { | ||||||
|         if self.match_token(&[TokenKind::Bang, TokenKind::Minus]) { |         if self.match_token(&[TokenKind::Bang, TokenKind::Minus]) { | ||||||
|             return Expr::Unary(Unary { |             return Ok(Expr::Unary(Unary { | ||||||
|                 operator: self.previous(), |                 operator: self.previous(), | ||||||
|                 right: Box::new(self.unary()), |                 right: Box::new(self.unary()?), | ||||||
|             }); |             })); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return self.primary(); |         return self.primary(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn primary(&mut self) -> Expr<'a> { |     fn primary(&mut self) -> ExprResult<'a> { | ||||||
|         let next = self.advance(); |         let next = self.advance(); | ||||||
|         let literal = match next.kind { |         let literal = match next.kind { | ||||||
|             TokenKind::True => Literal::Boolean(true), |             TokenKind::True => Literal::Boolean(true), | ||||||
|  | @ -132,7 +125,7 @@ impl<'a> Parser<'a> { | ||||||
|             unexpected => panic!("Parser encountered unexpected token '{:?}'", unexpected), |             unexpected => panic!("Parser encountered unexpected token '{:?}'", unexpected), | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         Expr::Literal(literal) |         Ok(Expr::Literal(literal)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // internal helpers
 |     // internal helpers
 | ||||||
|  | @ -178,19 +171,18 @@ impl<'a> Parser<'a> { | ||||||
|     fn binary_operator( |     fn binary_operator( | ||||||
|         &mut self, |         &mut self, | ||||||
|         oneof: &[TokenKind], |         oneof: &[TokenKind], | ||||||
|         left: fn(&mut Parser<'a>) -> Expr<'a>, |         each: fn(&mut Parser<'a>) -> ExprResult<'a>, | ||||||
|         right: fn(&mut Parser<'a>) -> Expr<'a>, |     ) -> ExprResult<'a> { | ||||||
|     ) -> Expr<'a> { |         let mut expr = each(self)?; | ||||||
|         let mut expr = left(self); |  | ||||||
| 
 | 
 | ||||||
|         while self.match_token(oneof) { |         while self.match_token(oneof) { | ||||||
|             expr = Expr::Binary(Binary { |             expr = Expr::Binary(Binary { | ||||||
|                 left: Box::new(expr), |                 left: Box::new(expr), | ||||||
|                 operator: self.previous(), |                 operator: self.previous(), | ||||||
|                 right: Box::new(right(self)), |                 right: Box::new(each(self)?), | ||||||
|             }) |             }) | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return expr; |         return Ok(expr); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue