@@ 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 ;
@@ 47,13 47,66 @@ impl Parser {
pub fn statement(&mut self) -> Result<AST, KabelError> {
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<AST, KabelError> {
+ 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<AST, KabelError> {
+ 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<AST>),
+ Loop(Box<AST>),
+ While(Box<AST>, Box<AST>),
If(Box<AST>, Box<AST>, Option<Box<AST>>),
Block(Vec<AST>),