diff options
author | Vincent Ambo <mail@tazj.in> | 2021-01-06T17·35+0300 |
---|---|---|
committer | tazjin <mail@tazj.in> | 2021-01-06T23·02+0000 |
commit | 0a0335ae6cd957f48086a41832cef794998f7271 (patch) | |
tree | 54e59e6c3b88989f7d913aa7aaf8e4cb3a750a69 /users/tazjin/rlox/src/parser.rs | |
parent | 93122a212e1f27cb0a941b11e342458fef97ed25 (diff) |
feat(tazjin/rlox): Parse & interpret logical operators r/2061
Change-Id: I1a7d0eda61f7f077b820dc0d2c2516e204966962 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2324 Reviewed-by: tazjin <mail@tazj.in> Tested-by: BuildkiteCI
Diffstat (limited to 'users/tazjin/rlox/src/parser.rs')
-rw-r--r-- | users/tazjin/rlox/src/parser.rs | 42 |
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], |