From 6f19d38bf04ffb59b183e7f0b627c9b0c3ead231 Mon Sep 17 00:00:00 2001 From: Jooris Hadeler Date: Thu, 15 Jan 2026 21:38:07 +0100 Subject: [PATCH] feat: Add support for `if` and compound statements. --- src/ast.rs | 10 ++++++++++ src/main.rs | 2 +- src/parser.rs | 37 +++++++++++++++++++++++++++++++++++++ src/token.rs | 2 ++ 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/ast.rs b/src/ast.rs index bc0c7f8..f2eca64 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -67,5 +67,15 @@ pub enum Statement { value: Option, }, + If { + condition: Expression, + then: Box, + elze: Option>, + }, + + Compound { + body: Vec, + }, + Expr(Expression), } diff --git a/src/main.rs b/src/main.rs index 243a3fb..2f95dc8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ pub mod parser; pub mod token; fn main() { - let mut parser = Parser::new("let index = 12 + 3;"); + let mut parser = Parser::new("if a < 12 { let b = 10; } else { let c = 20; }"); println!("{:#?}", parser.parse_statement()); } diff --git a/src/parser.rs b/src/parser.rs index 6051c1a..5b9afdc 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -59,6 +59,7 @@ impl<'src> Parser<'src> { pub fn parse_statement(&mut self) -> ParserResult { match self.peek_no_eof()?.kind { TokenKind::KwLet => self.parse_let_statement(), + TokenKind::KwIf => self.parse_if_statement(), _ => { let expr = self.parse_expression(0)?; @@ -68,6 +69,42 @@ impl<'src> Parser<'src> { } } + fn parse_if_statement(&mut self) -> ParserResult { + self.expect(&[TokenKind::KwIf])?; + + let condition = self.parse_expression(0)?; + let then = Box::new(self.parse_compound_statement()?); + let elze = if self.is_peek(TokenKind::KwElse) { + self.consume(); + + Some(Box::new(if self.is_peek(TokenKind::KwIf) { + self.parse_if_statement()? + } else { + self.parse_compound_statement()? + })) + } else { + None + }; + + Ok(Statement::If { + condition, + then, + elze, + }) + } + + fn parse_compound_statement(&mut self) -> ParserResult { + let mut body = Vec::new(); + self.expect(&[TokenKind::LeftBrace])?; + + while !self.is_peek(TokenKind::RightBrace) { + body.push(self.parse_statement()?); + } + + self.expect(&[TokenKind::RightBrace])?; + Ok(Statement::Compound { body }) + } + fn parse_let_statement(&mut self) -> ParserResult { self.expect(&[TokenKind::KwLet])?; diff --git a/src/token.rs b/src/token.rs index 5df54c6..989d1a9 100644 --- a/src/token.rs +++ b/src/token.rs @@ -42,6 +42,7 @@ pub enum TokenKind { KwFn, KwIf, KwLet, + KwElse, KwLoop, KwWhile, KwBreak, @@ -183,6 +184,7 @@ impl<'src> Tokenizer<'src> { "fn" => TokenKind::KwFn, "if" => TokenKind::KwIf, "let" => TokenKind::KwLet, + "else" => TokenKind::KwElse, "loop" => TokenKind::KwLoop, "while" => TokenKind::KwWhile, "break" => TokenKind::KwBreak,