diff options
author | Vincent Ambo <mail@tazj.in> | 2021-01-03T15·26+0300 |
---|---|---|
committer | tazjin <mail@tazj.in> | 2021-01-06T17·14+0000 |
commit | a89777b34f52ee5af51d93c66e1d9f92e830ca6a (patch) | |
tree | 819c7adf43acd684dc1f0fb87fddc653115beb1b | |
parent | 27a73171cf97c24c7785787eb7661405334329de (diff) |
feat(tazjin/rlox): Parse if statements r/2059
Change-Id: I2352d75a3f02d65a5a2d04fb2cc4daa50f11ca1e Reviewed-on: https://cl.tvl.fyi/c/depot/+/2321 Tested-by: BuildkiteCI Reviewed-by: tazjin <mail@tazj.in>
-rw-r--r-- | users/tazjin/rlox/src/errors.rs | 1 | ||||
-rw-r--r-- | users/tazjin/rlox/src/interpreter.rs | 1 | ||||
-rw-r--r-- | users/tazjin/rlox/src/parser.rs | 44 |
3 files changed, 45 insertions, 1 deletions
diff --git a/users/tazjin/rlox/src/errors.rs b/users/tazjin/rlox/src/errors.rs index 10fc0a352990..64dc7a92072f 100644 --- a/users/tazjin/rlox/src/errors.rs +++ b/users/tazjin/rlox/src/errors.rs @@ -7,6 +7,7 @@ pub enum ErrorKind { ExpectedSemicolon, ExpectedClosingBrace, ExpectedVariableName, + ExpectedToken(&'static str), TypeError(String), UndefinedVariable(String), InternalError(String), diff --git a/users/tazjin/rlox/src/interpreter.rs b/users/tazjin/rlox/src/interpreter.rs index b650a4ee6826..3645e884ddf9 100644 --- a/users/tazjin/rlox/src/interpreter.rs +++ b/users/tazjin/rlox/src/interpreter.rs @@ -127,6 +127,7 @@ impl Interpreter { } Statement::Var(var) => return self.interpret_var(var), Statement::Block(block) => return self.interpret_block(block), + Statement::If(_) => unimplemented!(), } Ok(()) diff --git a/users/tazjin/rlox/src/parser.rs b/users/tazjin/rlox/src/parser.rs index 94ad2f4c474b..4be6a6afcc54 100644 --- a/users/tazjin/rlox/src/parser.rs +++ b/users/tazjin/rlox/src/parser.rs @@ -62,6 +62,13 @@ pub struct Var<'a> { pub initialiser: Option<Expr<'a>>, } +#[derive(Debug)] +pub struct If<'a> { + pub condition: Expr<'a>, + pub then_branch: Box<Statement<'a>>, + pub else_branch: Option<Box<Statement<'a>>>, +} + pub type Block<'a> = Vec<Statement<'a>>; #[derive(Debug)] @@ -70,6 +77,7 @@ pub enum Statement<'a> { Print(Expr<'a>), Var(Var<'a>), Block(Block<'a>), + If(If<'a>), } // Parser @@ -81,9 +89,15 @@ declaration → varDecl | statement ; statement → exprStmt - | printStmt ; + | ifStmt + | printStmt + | block ; exprStmt → expression ";" ; + +ifStmt → "if" "(" expression ")" statement + ( "else" statement )? ; + printStmt → "print" expression ";" ; expression → assignment ; @@ -146,6 +160,8 @@ impl<'a> Parser<'a> { self.print_statement() } else if self.match_token(&[TokenKind::LeftBrace]) { self.block_statement() + } else if self.match_token(&[TokenKind::If]) { + self.if_statement() } else { self.expr_statement() } @@ -169,6 +185,32 @@ impl<'a> Parser<'a> { Ok(Statement::Block(block)) } + fn if_statement(&mut self) -> StmtResult<'a> { + self.consume( + &TokenKind::LeftParen, + ErrorKind::ExpectedToken("Expected '(' after 'if'"), + )?; + let condition = self.expression()?; + self.consume( + &TokenKind::RightParen, + ErrorKind::ExpectedToken("Expected ')' after condition"), + )?; + + let then_branch = Box::new(self.statement()?); + + let mut stmt = If { + condition, + then_branch, + else_branch: Option::None, + }; + + if self.match_token(&[TokenKind::Else]) { + stmt.else_branch = Some(Box::new(self.statement()?)); + } + + Ok(Statement::If(stmt)) + } + fn expr_statement(&mut self) -> StmtResult<'a> { let expr = self.expression()?; self.consume(&TokenKind::Semicolon, ErrorKind::ExpectedSemicolon)?; |