about summary refs log tree commit diff
path: root/users/tazjin/rlox/src/parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'users/tazjin/rlox/src/parser.rs')
-rw-r--r--users/tazjin/rlox/src/parser.rs42
1 files changed, 40 insertions, 2 deletions
diff --git a/users/tazjin/rlox/src/parser.rs b/users/tazjin/rlox/src/parser.rs
index 4be6a6afcc54..ac99f19cb2ee 100644
--- a/users/tazjin/rlox/src/parser.rs
+++ b/users/tazjin/rlox/src/parser.rs
@@ -24,6 +24,13 @@ pub struct Binary<'a> {
 }
 
 #[derive(Debug)]
+pub struct Logical<'a> {
+    pub left: Box<Expr<'a>>,
+    pub operator: Token<'a>,
+    pub right: Box<Expr<'a>>,
+}
+
+#[derive(Debug)]
 pub struct Grouping<'a>(pub Box<Expr<'a>>);
 
 #[derive(Debug, Clone, PartialEq)]
@@ -52,6 +59,7 @@ pub enum Expr<'a> {
     Literal(Literal),
     Unary(Unary<'a>),
     Variable(Variable<'a>),
+    Logical(Logical<'a>),
 }
 
 // Variable assignment. Not to be confused with `Variable`, which is
@@ -102,7 +110,9 @@ printStmt      → "print" expression ";" ;
 
 expression     → assignment ;
 assignment     → IDENTIFIER "=" assignment
-               | equality ;
+               | logic_or ;
+logic_or       → logic_and ( "or" logic_and )* ;
+logic_and      → equality ( "and" equality )* ;
 equality       → comparison ( ( "!=" | "==" ) comparison )* ;
 comparison     → term ( ( ">" | ">=" | "<" | "<=" ) term )* ;
 term           → factor ( ( "-" | "+" ) factor )* ;
@@ -222,7 +232,7 @@ impl<'a> Parser<'a> {
     }
 
     fn assignment(&mut self) -> ExprResult<'a> {
-        let expr = self.equality()?;
+        let expr = self.logic_or()?;
 
         if self.match_token(&[TokenKind::Equal]) {
             let equals = self.previous().clone();
@@ -244,6 +254,34 @@ impl<'a> Parser<'a> {
         Ok(expr)
     }
 
+    fn logic_or(&mut self) -> ExprResult<'a> {
+        let mut expr = self.logic_and()?;
+
+        while self.match_token(&[TokenKind::Or]) {
+            expr = Expr::Logical(Logical {
+                left: Box::new(expr),
+                operator: self.previous().clone(),
+                right: Box::new(self.logic_and()?),
+            })
+        }
+
+        Ok(expr)
+    }
+
+    fn logic_and(&mut self) -> ExprResult<'a> {
+        let mut expr = self.equality()?;
+
+        while self.match_token(&[TokenKind::And]) {
+            expr = Expr::Logical(Logical {
+                left: Box::new(expr),
+                operator: self.previous().clone(),
+                right: Box::new(self.equality()?),
+            })
+        }
+
+        Ok(expr)
+    }
+
     fn equality(&mut self) -> ExprResult<'a> {
         self.binary_operator(
             &[TokenKind::BangEqual, TokenKind::EqualEqual],