From 0a0335ae6cd957f48086a41832cef794998f7271 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Wed, 6 Jan 2021 20:35:05 +0300 Subject: feat(tazjin/rlox): Parse & interpret logical operators Change-Id: I1a7d0eda61f7f077b820dc0d2c2516e204966962 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2324 Reviewed-by: tazjin Tested-by: BuildkiteCI --- users/tazjin/rlox/src/parser.rs | 42 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'users/tazjin/rlox/src/parser.rs') 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 @@ -23,6 +23,13 @@ pub struct Binary<'a> { pub right: Box>, } +#[derive(Debug)] +pub struct Logical<'a> { + pub left: Box>, + pub operator: Token<'a>, + pub right: Box>, +} + #[derive(Debug)] pub struct Grouping<'a>(pub Box>); @@ -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], -- cgit 1.4.1