@@ 1,12 1,14 @@
program = { statement } ;
-statement = function | return | loop | while | if | expression_statement ;
+statement = function | return | loop | while | for | break | continue
+ | if | expression_statement ;
function = "function" , identifier , "(" , { identifier , "," , } ")" , block
return = "return" , expression , ";" ;
loop = "loop" , block ;
while = "while" , "(" , expression , ")" , block ;
+for = "for" , "(" , [ expression ] , ";" , [ expression ] , ";" , [ expression ] , ")" , block
break = "break" , ";" ;
continue = "continue" , ";" ;
@@ 52,6 52,7 @@ impl Parser {
"return" => self.return_statement(),
"loop" => self.loop_statement(),
"while" => self.while_statement(),
+ "for" => self.for_statement(),
"break" => self.break_statement(),
"continue" => self.continue_statement(),
"if" => self.if_statement(),
@@ 165,6 166,56 @@ impl Parser {
}
}
+ pub fn for_statement(&mut self) -> Result<AST , KabelError> {
+ let for_ident = self.read_token()?;
+ let left_paren = self.read_token()?;
+ if let TokenType::LeftParen = left_paren.token_type {
+ let expression1;
+ if let TokenType::Semicolon = self.peek()?.token_type {
+ expression1 = None;
+ } else {
+ expression1 = Some(self.expression()?);
+ }
+ let semicolon = self.read_token()?;
+ if let TokenType::Semicolon = semicolon.token_type {
+ let expression2;
+ if let TokenType::Semicolon = self.peek()?.token_type {
+ expression2 = None;
+ } else {
+ expression2 = Some(self.expression()?);
+ }
+ let semicolon = self.read_token()?;
+ if let TokenType::Semicolon = semicolon.token_type {
+ let expression3;
+ if let TokenType::RightParen = self.peek()?.token_type {
+ expression3 = None;
+ } else {
+ expression3 = Some(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::For(Box::new(expression1), Box::new(expression2), Box::new(expression3), Box::new(block.clone())),
+ start: for_ident.start,
+ end: block.end,
+ line: for_ident.line,
+ column: for_ident.column,
+ });
+ } else {
+ return Err(unexpected_token!(self, "Expected ) found {}", right_paren));
+ }
+ } else {
+ return Err(unexpected_token!(self, "Expected ; found {}", semicolon));
+ }
+ } else {
+ return Err(unexpected_token!(self, "Expected ; found {}", semicolon));
+ }
+ } else {
+ return Err(unexpected_token!(self, "Expected ( found {}", left_paren));
+ }
+ }
+
pub fn break_statement(&mut self) -> Result<AST, KabelError> {
let break_ident = self.read_token()?;
let semicolon = self.read_token()?;
@@ 626,8 677,7 @@ impl Parser {
pub fn subscript(&mut self) -> Result<AST, KabelError> {
let mut primary = self.primary()?;
- while self.current < self.input.len() &&
- self.peek()?.token_type == TokenType::LeftSquare {
+ while self.current < self.input.len() && self.peek()?.token_type == TokenType::LeftSquare {
self.read_token()?;
let expr = self.expression()?;
let right_brace = self.read_token()?;
@@ 867,6 917,7 @@ pub enum ASTType {
Return(Option<Box<AST>>), // expression
Loop(Box<AST>), // block
While(Box<AST>, Box<AST>), // condition, block
+ For(Box<Option<AST>>, Box<Option<AST>>, Box<Option<AST>>, Box<AST>), // expr1, expr2, expr3, block
Break,
Continue,
If(Box<AST>, Box<AST>, Option<Box<AST>>), // condition, block, else/else if