@@ 1,7 1,7 @@
use crate::{
error::{ErrorKind, KabelError},
lexer::{Token, TokenType},
- lit,
+ lit, unexpected_token,
};
pub struct Parser {
@@ 48,6 48,7 @@ impl Parser {
pub fn statement(&mut self) -> Result<AST, KabelError> {
match self.peek()?.token_type {
TokenType::Ident(ident) => match ident.as_str() {
+ "function" => self.function_statement(),
"loop" => self.loop_statement(),
"while" => self.while_statement(),
"if" => self.if_statement(),
@@ 57,6 58,40 @@ impl Parser {
}
}
+ pub fn function_statement(&mut self) -> Result<AST, KabelError> {
+ let function_ident = self.read_token()?;
+ let ident = self.read_token()?;
+ if let TokenType::Ident(name) = ident.token_type {
+ let left_paren = self.read_token()?;
+ if let TokenType::LeftParen = left_paren.token_type {
+ let mut expressions = Vec::new();
+ while self.peek()?.token_type != TokenType::RightParen {
+ expressions.push(self.expression()?);
+ if let TokenType::Comma = self.peek()?.token_type {
+ self.read_token()?;
+ }
+ }
+ let right_paren = self.read_token()?;
+ if let TokenType::RightParen = right_paren.token_type {
+ let block = self.block()?;
+ return Ok(AST {
+ ast_type: ASTType::Function(Box::new(lit!(Ident, name, ident)), expressions, Box::new(block.clone())),
+ start: function_ident.start,
+ end: block.end,
+ line: function_ident.line,
+ column: function_ident.column,
+ });
+ } else {
+ return Err(unexpected_token!(self, "Expected ) found {}", right_paren));
+ }
+ } else {
+ return Err(unexpected_token!(self, "Expected ( found {}", left_paren));
+ }
+ } else {
+ return Err(unexpected_token!(self, "Expected identifier found {}", ident));
+ }
+ }
+
pub fn loop_statement(&mut self) -> Result<AST, KabelError> {
let loop_ident = self.read_token()?;
let block = self.block()?;
@@ 85,28 120,10 @@ impl Parser {
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(),
- ));
+ return Err(unexpected_token!(self, "Expected ) found {}", right_paren));
}
} 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(),
- ));
+ return Err(unexpected_token!(self, "Expected ( found {}", left_paren));
}
}
@@ 152,30 169,10 @@ impl Parser {
column: if_ident.column,
});
} else {
- return Err(KabelError::new(
- ErrorKind::UnexpectedToken,
- format!(
- "Expected if found {}",
- 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(),
- ));
+ return Err(unexpected_token!(self, "Expected if found {}", else_if_ident));
}
}
- return Err(KabelError::new(
- ErrorKind::UnexpectedToken,
- format!(
- "Unexpected token {}",
- self.text[else_ident.start..else_ident.end].to_string()
- ),
- else_ident.line,
- else_ident.column,
- self.text[else_ident.line_start..else_ident.end].to_string(),
- ));
+ return Err(unexpected_token!(self, "Unexpected token {}", else_ident));
} else {
self.current -= 1;
}
@@ 189,28 186,10 @@ impl Parser {
column: if_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(),
- ));
+ return Err(unexpected_token!(self, "Expected ) found {}", right_paren));
}
} 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(),
- ));
+ return Err(unexpected_token!(self, "Expected ( found {}", left_paren));
}
}
@@ 230,16 209,7 @@ impl Parser {
column: left_brace.column,
});
} else {
- return Err(KabelError::new(
- ErrorKind::UnexpectedToken,
- format!(
- "Expected {{ found {}",
- self.text[left_brace.start..left_brace.end].to_string()
- ),
- left_brace.line,
- left_brace.column,
- self.text[left_brace.line_start..left_brace.end].to_string(),
- ));
+ return Err(unexpected_token!(self, "Expected {{ found {}", left_brace));
}
}
@@ 260,16 230,7 @@ impl Parser {
return Ok(expression);
} else {
self.current -= 1;
- return Err(KabelError::new(
- ErrorKind::UnexpectedToken,
- format!(
- "Expected ; found {}",
- self.text[semicolon.start..semicolon.end].to_string()
- ),
- semicolon.line,
- semicolon.column,
- self.text[semicolon.line_start..semicolon.end].to_string(),
- ));
+ return Err(unexpected_token!(self, "Expected ; found {}", semicolon));
}
}
@@ 301,28 262,10 @@ impl Parser {
column: var.column,
});
} else {
- return Err(KabelError::new(
- ErrorKind::UnexpectedToken,
- format!(
- "Expected equals, found {}",
- self.text[equal.start..equal.end].to_string()
- ),
- equal.line,
- equal.column,
- self.text[equal.line_start..equal.end].to_string(),
- ));
+ return Err(unexpected_token!(self, "Expected = found {}", equal));
}
} else {
- return Err(KabelError::new(
- ErrorKind::UnexpectedToken,
- format!(
- "Expected identifier, found {}",
- self.text[ident.start..ident.end].to_string()
- ),
- ident.line,
- ident.column,
- self.text[ident.line_start..ident.end].to_string(),
- ));
+ return Err(unexpected_token!(self, "Expected identifier found {}", ident));
}
}
@@ 645,16 588,7 @@ impl Parser {
return Ok(self.group(token)?);
}
_ => {
- return Err(KabelError::new(
- ErrorKind::UnexpectedToken,
- format!(
- "Unexpected token {}",
- self.text[token.start..token.end].to_string()
- ),
- token.line,
- token.column,
- self.text[token.line_start..token.end].to_string(),
- ));
+ return Err(unexpected_token!(self, "Unexpected token {}", token));
}
}
}
@@ 696,16 630,7 @@ impl Parser {
column: expr.column,
};
} else {
- return Err(KabelError::new(
- ErrorKind::UnexpectedToken,
- format!(
- "Unexpected token {}",
- self.text[child.start..child.end].to_string()
- ),
- child.line,
- child.column,
- self.text[child.line_start..child.end].to_string(),
- ));
+ return Err(unexpected_token!(self, "Unexpected token {}", child));
}
if self.current >= self.input.len() {
break;
@@ 815,12 740,13 @@ 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>),
+ Function(Box<AST>, Vec<AST>, Box<AST>), // name, args, block
+ Loop(Box<AST>), // block
+ While(Box<AST>, Box<AST>), // condition, block
+ If(Box<AST>, Box<AST>, Option<Box<AST>>), // condition, block, else/else if
+ Block(Vec<AST>), // statements
- Decl(Box<AST>, Box<AST>),
+ Decl(Box<AST>, Box<AST>), // identifier, expression
Binary(Box<AST>, BinOp, Box<AST>),
Unary(UnOp, Box<AST>),