From bc4391c57c6bf4ebe8f2a0101f99617264b39e4d Mon Sep 17 00:00:00 2001 From: ghostlyzsh Date: Thu, 1 Aug 2024 19:41:03 -0500 Subject: [PATCH] while and loop statements --- kabel/grammar.ebnf | 6 ++-- kabel/src/parser.rs | 85 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 79 insertions(+), 12 deletions(-) diff --git a/kabel/grammar.ebnf b/kabel/grammar.ebnf index 99d3143806298470108356e22d6aafe18dc9c31b..79aae95d9ca3cc59aee9dab77b5f48eb1a150ac8 100644 --- a/kabel/grammar.ebnf +++ b/kabel/grammar.ebnf @@ -1,18 +1,20 @@ program = { statement } ; -statement = if | while | ( expression , ";" ) ; +statement = function | loop | while | if | expression_statement ; function = "function" , identifier , "(" , { identifier , "," , } ")" , block +(* implemented *) loop = "loop" , block ; while = "while" , "(" , expression , ")" , block ; -(* implemented *) if = "if" , "(" , expression , ")" , block [ , "else" , ( if | block ) ] ; block = "{" , { statement } , "}" ; +expression_statement = expression , ";" ; + expression = assignment | declaration ; declaration = "var" , identifier , "=" , expression ; diff --git a/kabel/src/parser.rs b/kabel/src/parser.rs index 07e7c8d7e42097f6c75bbe18c9ffecd926ce4926..f43a5c7f866b96ba33d1c61eb81f3747042c9f50 100644 --- a/kabel/src/parser.rs +++ b/kabel/src/parser.rs @@ -47,13 +47,66 @@ impl Parser { pub fn statement(&mut self) -> Result { match self.peek()?.token_type { - TokenType::Ident(ident) => { - match ident.as_str() { - "if" => self.if_statement(), - _ => self.expression_statement() - } + TokenType::Ident(ident) => match ident.as_str() { + "loop" => self.loop_statement(), + "while" => self.while_statement(), + "if" => self.if_statement(), + _ => self.expression_statement(), + }, + _ => self.expression_statement(), + } + } + + pub fn loop_statement(&mut self) -> Result { + let loop_ident = self.read_token()?; + let block = self.block()?; + Ok(AST { + ast_type: ASTType::Loop(Box::new(block.clone())), + start: loop_ident.start, + end: block.end, + line: loop_ident.line, + column: loop_ident.column, + }) + } + + pub fn while_statement(&mut self) -> Result { + let while_ident = self.read_token()?; + let left_paren = self.read_token()?; + if let TokenType::LeftParen = left_paren.token_type { + let condition = self.expression()?; + let right_paren = self.read_token()?; + if let TokenType::RightParen = right_paren.token_type { + let block = self.block()?; + return Ok(AST { + ast_type: ASTType::While(Box::new(condition), Box::new(block.clone())), + start: while_ident.start, + end: block.end, + line: while_ident.line, + column: while_ident.column, + }); + } else { + return Err(KabelError::new( + ErrorKind::UnexpectedToken, + format!( + "Expected ) found {}", + self.text[right_paren.start..right_paren.end].to_string() + ), + right_paren.line, + right_paren.column, + self.text[right_paren.line_start..right_paren.end].to_string(), + )); } - _ => self.expression_statement() + } else { + return Err(KabelError::new( + ErrorKind::UnexpectedToken, + format!( + "Expected ( found {}", + self.text[left_paren.start..left_paren.end].to_string() + ), + left_paren.line, + left_paren.column, + self.text[left_paren.line_start..left_paren.end].to_string(), + )); } } @@ -72,7 +125,11 @@ impl Parser { if let TokenType::LeftBrace = self.peek()?.token_type { let else_block = self.block()?; return Ok(AST { - ast_type: ASTType::If(Box::new(condition), Box::new(block.clone()), Some(Box::new(else_block.clone()))), + ast_type: ASTType::If( + Box::new(condition), + Box::new(block.clone()), + Some(Box::new(else_block.clone())), + ), start: if_ident.start, end: else_block.end, line: if_ident.line, @@ -84,7 +141,11 @@ impl Parser { if content == "if" { let else_if = self.if_statement()?; return Ok(AST { - ast_type: ASTType::If(Box::new(condition), Box::new(block.clone()), Some(Box::new(else_if.clone()))), + ast_type: ASTType::If( + Box::new(condition), + Box::new(block.clone()), + Some(Box::new(else_if.clone())), + ), start: if_ident.start, end: else_if.end, line: if_ident.line, @@ -95,11 +156,13 @@ impl Parser { ErrorKind::UnexpectedToken, format!( "Expected if found {}", - self.text[else_if_ident.start..else_if_ident.end].to_string() + self.text[else_if_ident.start..else_if_ident.end] + .to_string() ), else_if_ident.line, else_if_ident.column, - self.text[else_if_ident.line_start..else_if_ident.end].to_string(), + self.text[else_if_ident.line_start..else_if_ident.end] + .to_string(), )); } } @@ -752,6 +815,8 @@ pub struct AST { pub enum ASTType { Program(Vec), + Loop(Box), + While(Box, Box), If(Box, Box, Option>), Block(Vec),