feat(tazjin/rlox): Parse if statements
Change-Id: I2352d75a3f02d65a5a2d04fb2cc4daa50f11ca1e Reviewed-on: https://cl.tvl.fyi/c/depot/+/2321 Tested-by: BuildkiteCI Reviewed-by: tazjin <mail@tazj.in>
This commit is contained in:
		
							parent
							
								
									27a73171cf
								
							
						
					
					
						commit
						a89777b34f
					
				
					 3 changed files with 45 additions and 1 deletions
				
			
		|  | @ -7,6 +7,7 @@ pub enum ErrorKind { | |||
|     ExpectedSemicolon, | ||||
|     ExpectedClosingBrace, | ||||
|     ExpectedVariableName, | ||||
|     ExpectedToken(&'static str), | ||||
|     TypeError(String), | ||||
|     UndefinedVariable(String), | ||||
|     InternalError(String), | ||||
|  |  | |||
|  | @ -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(()) | ||||
|  |  | |||
|  | @ -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)?; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue