From a89777b34f52ee5af51d93c66e1d9f92e830ca6a Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Sun, 3 Jan 2021 18:26:26 +0300 Subject: feat(tazjin/rlox): Parse if statements Change-Id: I2352d75a3f02d65a5a2d04fb2cc4daa50f11ca1e Reviewed-on: https://cl.tvl.fyi/c/depot/+/2321 Tested-by: BuildkiteCI Reviewed-by: tazjin --- users/tazjin/rlox/src/errors.rs | 1 + users/tazjin/rlox/src/interpreter.rs | 1 + users/tazjin/rlox/src/parser.rs | 44 +++++++++++++++++++++++++++++++++++- 3 files changed, 45 insertions(+), 1 deletion(-) (limited to 'users/tazjin/rlox') 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>, } +#[derive(Debug)] +pub struct If<'a> { + pub condition: Expr<'a>, + pub then_branch: Box>, + pub else_branch: Option>>, +} + pub type Block<'a> = Vec>; #[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)?; -- cgit 1.4.1