about summary refs log tree commit diff
path: root/users/tazjin/rlox
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2020-12-06T13·43+0100
committertazjin <mail@tazj.in>2020-12-06T14·30+0000
commit28002fcea50c028bcd136f321d3bbad6f141b212 (patch)
tree522e1c9f77738892cb770de6f76b3042453b1e27 /users/tazjin/rlox
parent5fcff11eae107b76177a581dc604ac0408213b02 (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
Diffstat (limited to 'users/tazjin/rlox')
-rw-r--r--users/tazjin/rlox/src/parser.rs50
1 files changed, 21 insertions, 29 deletions
diff --git a/users/tazjin/rlox/src/parser.rs b/users/tazjin/rlox/src/parser.rs
index bc253971eb..62a8b5fe4d 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);
     }
 }