@@ 2,19 2,23 @@ program = { statement } ;
statement = if | while | ( expression , ";" ) ;
-while = "while" , expression , block ;
+function = "function" , identifier , "(" , { identifier , "," , } ")" , block
-if = "if" , expression , block ;
+loop = "loop" , block ;
+
+while = "while" , "(" , expression , ")" , block ;
+
+if = "if" , "(" , expression , ")" , block [ , "else" , ( if | block ) ] ;
block = "{" , { statement } , "}" ;
+(* implemented *)
expression = assignment | declaration ;
declaration = "var" , identifier , "=" , expression ;
-assignment = { identifier , "=" , } logical_or ;
+assignment = ( identifier , "=" , assignment ) | logical_or;
-(* implemented *)
logical_or = logical_and { , "||" , logical_and } ;
logical_and = equality { , "&&" , equality } ;
@@ 29,7 33,11 @@ factor = unary { , ( "*" | "/" ) , unary } ;
unary = ( ( "!" | "-" ) , unary ) | primary ;
-primary = identifier | number | string | group ;
+primary = identifier | member | call | number | string | group ;
+
+member = identifier , "." , { ( identifier | call ) , "." ? } ;
+
+call = ( identifier , "(" , { expression, "," ? } , ")" ) ;
group = "(" , expression , ")" ;
@@ 1,6 1,6 @@
use crate::{
error::{ErrorKind, KabelError},
- lexer::{Token, TokenType},
+ lexer::{Token, TokenType}, lit,
};
pub struct Parser {
@@ 45,19 45,92 @@ impl Parser {
}
pub fn expression(&mut self) -> Result<AST, KabelError> {
- let equality = self.logical_or()?;
- Ok(equality)
+ if let TokenType::Ident(name) = self.peek()?.token_type {
+ if name == "var" {
+ return self.declaration();
+ }
+ }
+ let assignment = self.assignment()?;
+ Ok(assignment)
+ }
+
+ pub fn declaration(&mut self) -> Result<AST, KabelError> {
+ let var = self.read_token()?;
+ let ident = self.read_token()?;
+ if let TokenType::Ident(name) = ident.token_type {
+ let equal = self.read_token()?;
+ if let TokenType::Equal = equal.token_type {
+ let expr = self.expression()?;
+ return Ok(AST {
+ ast_type: ASTType::Decl(Box::new(lit!(Ident, name, ident)), Box::new(expr.clone())),
+ start: var.start,
+ end: expr.end,
+ line: var.line,
+ 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(),
+ ));
+ }
+ } 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(),
+ ));
+ }
+ }
+
+ pub fn assignment(&mut self) -> Result<AST, KabelError> {
+ if let TokenType::Ident(name) = self.peek()?.token_type {
+ let ident = self.read_token()?;
+ if self.current >= self.input.len() {
+ self.current -= 1;
+ return self.logical_or();
+ }
+ if self.peek()?.token_type == TokenType::Equal {
+ self.read_token()?;
+ let expr = self.assignment()?;
+ return Ok(AST {
+ ast_type: ASTType::Binary(Box::new(lit!(Ident, name, ident)), BinOp::Assign, Box::new(expr.clone())),
+ start: ident.start,
+ end: expr.end,
+ line: ident.line,
+ column: ident.column,
+ });
+ }
+ self.current -= 1;
+ return self.logical_or();
+ }
+
+ return self.logical_or();
}
pub fn logical_or(&mut self) -> Result<AST, KabelError> {
let mut left = self.logical_and()?;
- while self.current < self.input.len()
- && self.peek()?.token_type == TokenType::OrOr {
+ while self.current < self.input.len() && self.peek()?.token_type == TokenType::OrOr {
self.read_token()?;
let right = self.logical_and()?;
left = AST {
- ast_type: ASTType::Binary(Box::new(left.clone()), BinOp::Or, Box::new(right.clone())),
+ ast_type: ASTType::Binary(
+ Box::new(left.clone()),
+ BinOp::Or,
+ Box::new(right.clone()),
+ ),
start: left.start,
end: right.end,
line: left.line,
@@ 70,12 143,15 @@ impl Parser {
pub fn logical_and(&mut self) -> Result<AST, KabelError> {
let mut left = self.equality()?;
- while self.current < self.input.len()
- && self.peek()?.token_type == TokenType::AndAnd {
+ while self.current < self.input.len() && self.peek()?.token_type == TokenType::AndAnd {
self.read_token()?;
let right = self.equality()?;
left = AST {
- ast_type: ASTType::Binary(Box::new(left.clone()), BinOp::And, Box::new(right.clone())),
+ ast_type: ASTType::Binary(
+ Box::new(left.clone()),
+ BinOp::And,
+ Box::new(right.clone()),
+ ),
start: left.start,
end: right.end,
line: left.line,
@@ 294,9 370,17 @@ impl Parser {
let token = self.read_token()?;
match token.token_type {
- TokenType::Ident(ident) => {
+ TokenType::Ident(ref ident) => {
+ if self.current < self.input.len() {
+ if let TokenType::LeftParen = self.peek()?.token_type {
+ return self.call(token);
+ }
+ if let TokenType::Period = self.peek()?.token_type {
+ return self.member(token);
+ }
+ }
return Ok(AST {
- ast_type: ASTType::Ident(ident),
+ ast_type: ASTType::Lit(Lit::Ident(ident.clone())),
start: token.start,
end: token.end,
line: token.line,
@@ 305,7 389,7 @@ impl Parser {
}
TokenType::Num(num) => {
return Ok(AST {
- ast_type: ASTType::Num(num),
+ ast_type: ASTType::Lit(Lit::Num(num)),
start: token.start,
end: token.end,
line: token.line,
@@ 314,7 398,7 @@ impl Parser {
}
TokenType::Str(string) => {
return Ok(AST {
- ast_type: ASTType::Str(string),
+ ast_type: ASTType::Lit(Lit::Str(string)),
start: token.start,
end: token.end,
line: token.line,
@@ 338,6 422,80 @@ impl Parser {
}
}
}
+
+ pub fn member(&mut self, ident: Token) -> Result<AST, KabelError> {
+ if let TokenType::Ident(first) = ident.token_type {
+ let mut expr: AST = lit!(Ident, first, ident);
+ while self.peek()?.token_type == TokenType::Period {
+ self.read_token()?;
+ let child = self.read_token()?;
+ if let TokenType::Ident(child_str) = child.clone().token_type {
+ if self.current < self.input.len() {
+ if let TokenType::LeftParen = self.peek()?.token_type {
+ let call = self.call(child)?;
+ expr = AST {
+ ast_type: ASTType::Member(Box::new(expr.clone()), Box::new(call.clone())),
+ start: expr.start,
+ end: call.end,
+ line: expr.line,
+ column: expr.column,
+ };
+ if self.current >= self.input.len() {
+ break;
+ }
+ continue;
+ }
+ }
+ expr = AST {
+ ast_type: ASTType::Member(Box::new(expr.clone()), Box::new(lit!(Ident, child_str, child))),
+ start: expr.start,
+ end: child.end,
+ line: expr.line,
+ 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(),
+ ));
+ }
+ if self.current >= self.input.len() {
+ break;
+ }
+ }
+ return Ok(expr);
+ }
+ panic!("Bad member logic");
+ }
+
+ pub fn call(&mut self, ident: Token) -> Result<AST, KabelError> {
+ self.read_token()?;
+ 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::Ident(name) = ident.token_type {
+ return Ok(AST {
+ ast_type: ASTType::Call(Box::new(lit!(Ident, name, ident)), expressions),
+ start: ident.start,
+ end: right_paren.end,
+ line: ident.start,
+ column: ident.column,
+ });
+ }
+ panic!("Call logic broke");
+ }
+
pub fn group(&mut self, left_paren: Token) -> Result<AST, KabelError> {
let expr = self.expression()?;
let right_paren = self.peek();
@@ 415,10 573,18 @@ pub struct AST {
pub enum ASTType {
Program(Vec<AST>),
+ Decl(Box<AST>, Box<AST>),
Binary(Box<AST>, BinOp, Box<AST>),
Unary(UnOp, Box<AST>),
Group(Box<AST>),
+ Lit(Lit),
+ Call(Box<AST>, Vec<AST>),
+ Member(Box<AST>, Box<AST>),
+}
+
+#[derive(Debug, Clone)]
+pub enum Lit {
Ident(String),
Num(f32),
Str(String),
@@ 438,6 604,7 @@ pub enum BinOp {
Le,
Or,
And,
+ Assign,
}
#[derive(Debug, Clone, Copy)]