diff options
author | Vincent Ambo <mail@tazj.in> | 2020-12-06T13·43+0100 |
---|---|---|
committer | tazjin <mail@tazj.in> | 2020-12-06T14·30+0000 |
commit | 28002fcea50c028bcd136f321d3bbad6f141b212 (patch) | |
tree | 522e1c9f77738892cb770de6f76b3042453b1e27 | |
parent | 5fcff11eae107b76177a581dc604ac0408213b02 (diff) |
refactor(tazjin/rlox): Add error plumbing in parser functions r/1988
Change-Id: I7ae3d721f76d8d69043f5ed077abbc70a18cbd92 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2233 Reviewed-by: tazjin <mail@tazj.in> Tested-by: BuildkiteCI
-rw-r--r-- | users/tazjin/rlox/src/parser.rs | 50 |
1 files changed, 21 insertions, 29 deletions
diff --git a/users/tazjin/rlox/src/parser.rs b/users/tazjin/rlox/src/parser.rs index bc253971eba3..62a8b5fe4d47 100644 --- a/users/tazjin/rlox/src/parser.rs +++ b/users/tazjin/rlox/src/parser.rs @@ -5,6 +5,7 @@ // // My Rust implementation skips this step because it's unnecessary, we // have real types. +use crate::errors::{Error, ErrorKind}; use crate::scanner::{Token, TokenKind}; // AST @@ -60,22 +61,23 @@ struct Parser<'a> { current: usize, } +type ExprResult<'a> = Result<Expr<'a>, Error>; + impl<'a> Parser<'a> { // recursive-descent parser functions - fn expression(&mut self) -> Expr<'a> { + fn expression(&mut self) -> ExprResult<'a> { self.equality() } - fn equality(&mut self) -> Expr<'a> { + fn equality(&mut self) -> ExprResult<'a> { self.binary_operator( &[TokenKind::BangEqual, TokenKind::EqualEqual], Self::comparison, - Self::comparison, ) } - fn comparison(&mut self) -> Expr<'a> { + fn comparison(&mut self) -> ExprResult<'a> { self.binary_operator( &[ TokenKind::Greater, @@ -84,38 +86,29 @@ impl<'a> Parser<'a> { TokenKind::LessEqual, ], Self::term, - Self::term, ) } - fn term(&mut self) -> Expr<'a> { - self.binary_operator( - &[TokenKind::Minus, TokenKind::Plus], - Self::factor, - Self::factor, - ) + fn term(&mut self) -> ExprResult<'a> { + self.binary_operator(&[TokenKind::Minus, TokenKind::Plus], Self::factor) } - fn factor(&mut self) -> Expr<'a> { - self.binary_operator( - &[TokenKind::Slash, TokenKind::Star], - Self::unary, - Self::unary, - ) + fn factor(&mut self) -> ExprResult<'a> { + self.binary_operator(&[TokenKind::Slash, TokenKind::Star], Self::unary) } - fn unary(&mut self) -> Expr<'a> { + fn unary(&mut self) -> ExprResult<'a> { if self.match_token(&[TokenKind::Bang, TokenKind::Minus]) { - return Expr::Unary(Unary { + return Ok(Expr::Unary(Unary { operator: self.previous(), - right: Box::new(self.unary()), - }); + right: Box::new(self.unary()?), + })); } return self.primary(); } - fn primary(&mut self) -> Expr<'a> { + fn primary(&mut self) -> ExprResult<'a> { let next = self.advance(); let literal = match next.kind { TokenKind::True => Literal::Boolean(true), @@ -132,7 +125,7 @@ impl<'a> Parser<'a> { unexpected => panic!("Parser encountered unexpected token '{:?}'", unexpected), }; - Expr::Literal(literal) + Ok(Expr::Literal(literal)) } // internal helpers @@ -178,19 +171,18 @@ impl<'a> Parser<'a> { fn binary_operator( &mut self, oneof: &[TokenKind], - left: fn(&mut Parser<'a>) -> Expr<'a>, - right: fn(&mut Parser<'a>) -> Expr<'a>, - ) -> Expr<'a> { - let mut expr = left(self); + each: fn(&mut Parser<'a>) -> ExprResult<'a>, + ) -> ExprResult<'a> { + let mut expr = each(self)?; while self.match_token(oneof) { expr = Expr::Binary(Binary { left: Box::new(expr), operator: self.previous(), - right: Box::new(right(self)), + right: Box::new(each(self)?), }) } - return expr; + return Ok(expr); } } |