use crate::{
ast::{LhsAssign, LhsAssignType}, ast_from_ast, ast_from_ast_token, ast_from_token, ast_from_token_ast, collect_lines, error::{ErrorKind, KabelError}, lexer::{Token, TokenType}, lit, name, unexpected_token
};
use crate::ast::{AST, ASTType, BinOp, UnOp, Lit};
pub struct Parser {
input: Vec<Token>,
text: Vec<String>,
current: usize,
token: Token,
pub errors: Vec<KabelError>,
}
impl Parser {
pub fn new(text: String, input: Vec<Token>) -> Self {
Self {
input: input.clone(),
text: text.lines().collect::<Vec<&str>>().iter().map(|s| s.to_string()).collect(),
current: 0,
token: input[0].clone(),
errors: Vec::new(),
}
}
pub fn program(&mut self) -> AST {
let mut program = Vec::new();
loop {
if self.current >= self.input.len() {
break;
}
match self.statement() {
Ok(ast) => program.push(ast),
Err(e) => self.errors.push(e),
}
}
AST {
kind: ASTType::Program(program),
extensions: Vec::new(),
start_line: 0,
end_line: 0,
start_column: 0,
end_column: 0,
}
}
pub fn statement(&mut self) -> Result<AST, KabelError> {
match self.peek()?.token_type {
TokenType::Function => self.function_statement(),
TokenType::Return => self.return_statement(),
TokenType::Loop => self.loop_statement(),
TokenType::While => self.while_statement(),
TokenType::For => self.for_statement(),
TokenType::Break => self.break_statement(),
TokenType::Continue => self.continue_statement(),
TokenType::If => self.if_statement(),
TokenType::LeftBrace => self.block(),
TokenType::Var => self.declaration(),
TokenType::Print => self.print_statement(), // REMOVE LATER
_ => self.expression_statement(),
}
}
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 {
let ident = self.read_token()?;
if let TokenType::Ident(name) = ident.token_type {
expressions.push(name!(name, ident));
} else {
return Err(unexpected_token!(self, "Expected identifier but found {}", ident));
}
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_from_token_ast!(AST,
ASTType::Function(
name!(name, ident),
expressions,
Box::new(block.clone())
),
function_ident,
block
));
} else {
return Err(unexpected_token!(self, "Expected ) but found {}", right_paren));
}
} else {
return Err(unexpected_token!(self, "Expected ( but found {}", left_paren));
}
} else {
return Err(unexpected_token!(
self,
"Expected identifier but found {}",
ident
));
}
}
pub fn return_statement(&mut self) -> Result<AST, KabelError> {
let return_ident = self.read_token()?;
if let TokenType::Semicolon = self.peek()?.token_type {
let semicolon = self.read_token()?;
return Ok(ast_from_token!(AST,
ASTType::Return(Box::new(None)),
return_ident,
semicolon
));
}
let expression = self.expression()?;
let semicolon = self.read_token()?;
if let TokenType::Semicolon = semicolon.token_type {
Ok(ast_from_token!(AST,
ASTType::Return(Box::new(Some(expression))),
return_ident,
semicolon
))
} else {
return Err(unexpected_token!(self, "Expected ; but found {}", semicolon));
}
}
pub fn loop_statement(&mut self) -> Result<AST, KabelError> {
let loop_ident = self.read_token()?;
let block = self.block()?;
Ok(ast_from_token_ast!(AST,
ASTType::Loop(Box::new(block.clone())),
loop_ident,
block
))
}
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_from_token_ast!(AST,
ASTType::While(Box::new(condition), Box::new(block.clone())),
while_ident,
block
));
} else {
return Err(unexpected_token!(self, "Expected ) but found {}", right_paren));
}
} else {
return Err(unexpected_token!(self, "Expected ( but found {}", left_paren));
}
}
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 {
if let TokenType::Var = self.peek()?.token_type {
expression1 = Some(self.declaration()?);
} else {
expression1 = Some(self.expression()?);
let semicolon = self.read_token()?;
if let TokenType::Semicolon = semicolon.token_type {} else {
self.current -= 1;
return Err(unexpected_token!(self, "Expected ; but found {}", semicolon));
}
}
}
let expression2;
if let TokenType::Semicolon = self.peek()?.token_type {
expression2 = None;
} else {
expression2 = Some(self.expression()?);
}
let semicolon_2 = self.read_token()?;
if let TokenType::Semicolon = semicolon_2.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(Self::build_for(for_ident, semicolon_2, expression1, expression2, expression3, block));
return Ok(ast_from_token_ast!(AST,
ASTType::For(
Box::new(expression1),
Box::new(expression2),
Box::new(expression3),
Box::new(block.clone())
),
for_ident,
block
));
} else {
return Err(unexpected_token!(self, "Expected ) but found {}", right_paren));
}
} else {
return Err(unexpected_token!(self, "Expected ; but found {}", semicolon_2));
}
} else {
return Err(unexpected_token!(self, "Expected ( but found {}", left_paren));
}
}
/*fn build_for(for_ident: Token, semicolon_2: Token, expression1: Option<AST>, expression2: Option<AST>, expression3: Option<AST>, block: AST) -> AST {
let mut outer_block = Vec::new();
if let Some(expression1) = expression1.clone() {
outer_block.push(expression1);
}
let mut new_block = block.clone();
if let Some(expression3) = expression3 {
if let ASTType::Block(inner) = block.clone().kind {
let mut new_inner = inner;
new_inner.push(ast_from_ast!(ASTType::Expr(Box::new(expression3.clone())), expression3, expression3));
new_block = ast_from_ast!(ASTType::Block(new_inner), block, block);
}
}
let condition = if let Some(expression2) = expression2 {
expression2
} else { lit!(Bool, true, semicolon_2) };
let while_ast = ast_from_ast!(ASTType::While(Box::new(condition.clone()), Box::new(new_block.clone())), condition, block);
outer_block.push(while_ast.clone());
let outer_block = ast_from_token_ast!(ASTType::Block(outer_block), for_ident, new_block);
outer_block
}*/
pub fn break_statement(&mut self) -> Result<AST, KabelError> {
let break_ident = self.read_token()?;
let semicolon = self.read_token()?;
if let TokenType::Semicolon = semicolon.token_type {
Ok(ast_from_token!(AST, ASTType::Break, break_ident, semicolon))
} else {
Err(unexpected_token!(self, "Expected ; but found {}", semicolon))
}
}
pub fn continue_statement(&mut self) -> Result<AST, KabelError> {
let continue_ident = self.read_token()?;
let semicolon = self.read_token()?;
if let TokenType::Semicolon = semicolon.token_type {
Ok(ast_from_token!(AST, ASTType::Continue, continue_ident, semicolon))
} else {
Err(unexpected_token!(self, "Expected ; but found {}", semicolon))
}
}
pub fn if_statement(&mut self) -> Result<AST, KabelError> {
let if_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()?;
if self.current < self.input.len() {
let else_ident = self.peek()?;
if let TokenType::Else = else_ident.token_type {
self.read_token()?;
if let TokenType::LeftBrace = self.peek()?.token_type {
let else_block = self.block()?;
return Ok(ast_from_token_ast!(AST,
ASTType::If(
Box::new(condition),
Box::new(block.clone()),
Box::new(Some(else_block.clone()))
),
if_ident,
else_block
));
}
let else_if_ident = self.peek()?;
if let TokenType::If = else_if_ident.token_type {
let else_if = self.if_statement()?;
return Ok(ast_from_token_ast!(AST,
ASTType::If(
Box::new(condition),
Box::new(block.clone()),
Box::new(Some(else_if.clone()))
),
if_ident,
else_if
));
}
return Err(unexpected_token!(self, "Unexpected token {}", else_ident));
}
}
return Ok(ast_from_token_ast!(AST,
ASTType::If(Box::new(condition), Box::new(block.clone()), Box::new(None)),
if_ident,
block
));
} else {
return Err(unexpected_token!(self, "Expected ) but found {}", right_paren));
}
} else {
return Err(unexpected_token!(self, "Expected ( but found {}", left_paren));
}
}
pub fn block(&mut self) -> Result<AST, KabelError> {
let left_brace = self.read_token()?;
if let TokenType::LeftBrace = left_brace.token_type {
let mut stmts = Vec::new();
while self.peek()?.token_type != TokenType::RightBrace {
stmts.push(self.statement()?);
}
let right_brace = self.read_token()?;
return Ok(ast_from_token!(AST, ASTType::Block(stmts), left_brace, right_brace));
} else {
return Err(unexpected_token!(self, "Expected {{ but found {}", left_brace));
}
}
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()?;
let semicolon = self.read_token()?;
if let TokenType::Semicolon = semicolon.token_type {
return Ok(ast_from_token!(AST,
ASTType::Decl(name!(name, ident), Box::new(expr.clone())),
var,
semicolon
));
} else {
return Err(unexpected_token!(self, "Expected ; but found {}", equal));
}
} else {
return Err(unexpected_token!(self, "Expected = but found {}", equal));
}
} else {
return Err(unexpected_token!(
self,
"Expected identifier but found {}",
ident
));
}
}
// REMOVE LATER
pub fn print_statement(&mut self) -> Result<AST, KabelError> {
let print_ident = self.read_token()?;
let expression = self.expression()?;
let semicolon = self.read_token()?;
if matches!(semicolon.token_type, TokenType::Semicolon) {
Ok(ast_from_token!(AST, ASTType::Print(Box::new(expression)), print_ident, semicolon))
} else {
Err(unexpected_token!(self, "Expected ; but found {}", semicolon))
}
}
pub fn expression_statement(&mut self) -> Result<AST, KabelError> {
let expression = self.expression()?;
if self.current >= self.input.len() {
let last = self.input.last().unwrap();
return Err(KabelError::new(
ErrorKind::UnexpectedEof,
"Unexpected end of file, expected ;".to_string(),
None,
expression.start_line,
last.end_column,
self.text[last.line].to_string(),
));
}
let semicolon = self.read_token()?;
if let TokenType::Semicolon = semicolon.token_type {
return Ok(ast_from_ast_token!(AST, ASTType::Expr(Box::new(expression.clone())),
expression, semicolon));
} else {
self.current -= 1;
return Err(unexpected_token!(self, "Expected ; but found {}", semicolon));
}
}
pub fn expression(&mut self) -> Result<AST, KabelError> {
let assignment = self.assignment()?;
Ok(assignment)
}
pub fn assignment(&mut self) -> Result<AST, KabelError> {
if let TokenType::Ident(name) = self.peek()?.token_type {
let ident = self.read_token()?;
let lhs_type;
if let TokenType::LeftSquare = self.peek()?.token_type {
self.read_token()?;
let index = self.expression()?;
let right_square = self.read_token()?;
lhs_type = ast_from_token!(LhsAssign, LhsAssignType::Subscript(Box::new(lit!(Ident, name.clone(), ident)), Box::new(index)), ident, right_square);
} else {
lhs_type = ast_from_token!(LhsAssign, LhsAssignType::Ident(name.clone()), ident, ident);
}
if self.current >= self.input.len() {
self.current -= 1;
return self.ternary();
}
if let TokenType::Equal
| TokenType::PlusEqual
| TokenType::MinusEqual
| TokenType::StarEqual
| TokenType::SlashEqual
| TokenType::PercentEqual
| TokenType::AndEqual
| TokenType::CaretEqual
| TokenType::OrEqual = self.peek()?.token_type
{
let binop = self.read_token()?;
let expr = self.expression()?;
if binop.token_type == TokenType::Equal {
return Ok(ast_from_token_ast!(AST,
ASTType::Assign(
lhs_type,
Box::new(expr.clone())
),
ident,
expr
));
} else if binop.token_type == TokenType::PlusEqual {
return Ok(ast_from_token_ast!(AST,
ASTType::Assign(
lhs_type,
Box::new(
ast_from_ast!(AST,
ASTType::Binary(
Box::new(lit!(Ident, name, ident)),
BinOp::Add,
Box::new(expr.clone())
),
expr,
expr
)
.clone()
)
),
ident,
expr
));
} else if binop.token_type == TokenType::MinusEqual {
return Ok(ast_from_token_ast!(AST,
ASTType::Assign(
lhs_type,
Box::new(
ast_from_ast!(AST,
ASTType::Binary(
Box::new(lit!(Ident, name, ident)),
BinOp::Sub,
Box::new(expr.clone())
),
expr,
expr
)
.clone()
)
),
ident,
expr
));
} else if binop.token_type == TokenType::StarEqual {
return Ok(ast_from_token_ast!(AST,
ASTType::Assign(
lhs_type,
Box::new(
ast_from_ast!(AST,
ASTType::Binary(
Box::new(lit!(Ident, name, ident)),
BinOp::Mul,
Box::new(expr.clone())
),
expr,
expr
)
.clone()
)
),
ident,
expr
));
} else if binop.token_type == TokenType::SlashEqual {
return Ok(ast_from_token_ast!(AST,
ASTType::Assign(
lhs_type,
Box::new(
ast_from_ast!(AST,
ASTType::Binary(
Box::new(lit!(Ident, name, ident)),
BinOp::Div,
Box::new(expr.clone())
),
expr,
expr
)
.clone()
)
),
ident,
expr
));
} else if binop.token_type == TokenType::PercentEqual {
return Ok(ast_from_token_ast!(AST,
ASTType::Assign(
lhs_type,
Box::new(
ast_from_ast!(AST,
ASTType::Binary(
Box::new(lit!(Ident, name, ident)),
BinOp::Mod,
Box::new(expr.clone())
),
expr,
expr
)
.clone()
)
),
ident,
expr
));
} else if binop.token_type == TokenType::AndEqual {
return Ok(ast_from_token_ast!(AST,
ASTType::Assign(
lhs_type,
Box::new(
ast_from_ast!(AST,
ASTType::Binary(
Box::new(lit!(Ident, name, ident)),
BinOp::BitAnd,
Box::new(expr.clone())
),
expr,
expr
)
.clone()
)
),
ident,
expr
));
} else if binop.token_type == TokenType::CaretEqual {
return Ok(ast_from_token_ast!(AST,
ASTType::Assign(
lhs_type,
Box::new(
ast_from_ast!(AST,
ASTType::Binary(
Box::new(lit!(Ident, name, ident)),
BinOp::BitXor,
Box::new(expr.clone())
),
expr,
expr
)
.clone()
)
),
ident,
expr
));
} else {
return Ok(ast_from_token_ast!(AST,
ASTType::Assign(
lhs_type,
Box::new(
ast_from_ast!(AST,
ASTType::Binary(
Box::new(lit!(Ident, name, ident)),
BinOp::BitOr,
Box::new(expr.clone())
),
expr,
expr
)
.clone()
)
),
ident,
expr
));
}
}
self.current -= 1;
return self.anonymous_function();
}
return self.anonymous_function();
}
pub fn anonymous_function(&mut self) -> Result<AST, KabelError> {
if let TokenType::LeftParen = self.peek()?.token_type {
let left_paren = self.read_token()?;
match self.peek()?.token_type {
TokenType::Ident(name) => {
let param = self.read_token()?;
if matches!(self.peek()?.token_type, TokenType::Comma) {
self.read_token()?;
let mut params = vec![name!(name, param)];
while self.peek()?.token_type != TokenType::RightParen {
let ident = self.read_token()?;
if let TokenType::Ident(name) = ident.token_type {
params.push(name!(name, ident));
} else {
return Err(unexpected_token!(self, "Expected identifier but found {}", ident));
}
if let TokenType::Comma = self.peek()?.token_type {
self.read_token()?;
}
}
self.read_token()?; // right paren
if let TokenType::Arrow = self.peek()?.token_type {
self.read_token()?;
if let TokenType::LeftBrace = self.peek()?.token_type {
let block = self.block()?;
return Ok(ast_from_token_ast!(AST, ASTType::Anonymous(params, Box::new(block.clone())), left_paren, block));
} else {
let left_brace = self.read_token()?;
return Err(unexpected_token!(self, "Expected {{ but found {}", left_brace));
}
} else {
let arrow = self.read_token()?;
return Err(unexpected_token!(self, "Expected => but found {}", arrow));
}
} else if matches!(self.peek()?.token_type, TokenType::RightParen) {
self.read_token()?; // right paren
let params = vec![name!(name, param)];
if let TokenType::Arrow = self.peek()?.token_type {
self.read_token()?;
if let TokenType::LeftBrace = self.peek()?.token_type {
let block = self.block()?;
return Ok(ast_from_token_ast!(AST, ASTType::Anonymous(params, Box::new(block.clone())), left_paren, block));
} else {
let left_brace = self.read_token()?;
return Err(unexpected_token!(self, "Expected {{ but found {}", left_brace));
}
} else {
let arrow = self.read_token()?;
return Err(unexpected_token!(self, "Expected => but found {}", arrow));
}
} else {
self.current -= 1;
return self.group(left_paren);
}
}
TokenType::RightParen => {
self.read_token()?; // right paren
if let TokenType::Arrow = self.peek()?.token_type {
self.read_token()?;
let block = self.block()?;
return Ok(ast_from_token_ast!(AST, ASTType::Anonymous(Vec::new(), Box::new(block.clone())), left_paren, block));
} else {
let arrow = self.read_token()?;
return Err(unexpected_token!(self, "Expected => but found {}", arrow));
}
}
_ => {
return self.group(left_paren);
}
}
}
return self.ternary();
}
pub fn ternary(&mut self) -> Result<AST, KabelError> {
let condition = self.logical_or()?;
if let TokenType::Question = self.peek()?.token_type {
self.read_token()?;
let true_expr = self.expression()?;
if let TokenType::Colon = self.peek()?.token_type {
self.read_token()?;
let false_expr = self.expression()?;
return Ok(ast_from_ast!(AST,
ASTType::Ternary(
Box::new(condition.clone()),
Box::new(true_expr),
Box::new(false_expr.clone())
),
condition,
false_expr
));
} else {
return Err(unexpected_token!(self, "Expected : but found {}", self.token));
}
}
Ok(condition)
}
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 {
self.read_token()?;
let right = self.logical_and()?;
left = ast_from_ast!(AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Or, Box::new(right.clone())),
left,
right
);
}
Ok(left)
}
pub fn logical_and(&mut self) -> Result<AST, KabelError> {
let mut left = self.bit_and()?;
while self.current < self.input.len() && self.peek()?.token_type == TokenType::AndAnd {
self.read_token()?;
let right = self.bit_and()?;
left = ast_from_ast!(AST,
ASTType::Binary(Box::new(left.clone()), BinOp::And, Box::new(right.clone())),
left,
right
);
}
Ok(left)
}
pub fn bit_and(&mut self) -> Result<AST, KabelError> {
let mut left = self.bit_xor()?;
while self.current < self.input.len() && self.peek()?.token_type == TokenType::And {
self.read_token()?;
let right = self.bit_xor()?;
left = ast_from_ast!(AST,
ASTType::Binary(
Box::new(left.clone()),
BinOp::BitAnd,
Box::new(right.clone())
),
left,
right
);
}
Ok(left)
}
pub fn bit_xor(&mut self) -> Result<AST, KabelError> {
let mut left = self.bit_or()?;
while self.current < self.input.len() && self.peek()?.token_type == TokenType::Caret {
self.read_token()?;
let right = self.bit_or()?;
left = ast_from_ast!(AST,
ASTType::Binary(
Box::new(left.clone()),
BinOp::BitXor,
Box::new(right.clone())
),
left,
right
);
}
Ok(left)
}
pub fn bit_or(&mut self) -> Result<AST, KabelError> {
let mut left = self.equality()?;
while self.current < self.input.len() && self.peek()?.token_type == TokenType::Or {
self.read_token()?;
let right = self.equality()?;
left = ast_from_ast!(AST,
ASTType::Binary(
Box::new(left.clone()),
BinOp::BitOr,
Box::new(right.clone())
),
left,
right
);
}
Ok(left)
}
pub fn equality(&mut self) -> Result<AST, KabelError> {
let mut left = self.comparison()?;
while self.current < self.input.len()
&& (self.peek()?.token_type == TokenType::EqualEqual
|| self.peek()?.token_type == TokenType::BangEqual)
{
let binop = self.read_token()?;
let right = self.comparison()?;
if binop.token_type == TokenType::EqualEqual {
left = ast_from_ast!(AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Eq, Box::new(right.clone())),
left,
right
);
} else {
left = ast_from_ast!(AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Ne, Box::new(right.clone())),
left,
right
);
}
}
Ok(left)
}
pub fn comparison(&mut self) -> Result<AST, KabelError> {
let mut left = self.term()?;
while self.current < self.input.len()
&& (self.peek()?.token_type == TokenType::Less
|| self.peek()?.token_type == TokenType::LessEqual
|| self.peek()?.token_type == TokenType::Greater
|| self.peek()?.token_type == TokenType::GreaterEqual)
{
let binop = self.read_token()?;
let right = self.term()?;
if binop.token_type == TokenType::Less {
left = ast_from_ast!(AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Ls, Box::new(right.clone())),
left,
right
);
} else if binop.token_type == TokenType::LessEqual {
left = ast_from_ast!(AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Le, Box::new(right.clone())),
left,
right
);
} else if binop.token_type == TokenType::Greater {
left = ast_from_ast!(AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Gr, Box::new(right.clone())),
left,
right
);
} else {
left = ast_from_ast!(AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Ge, Box::new(right.clone())),
left,
right
);
}
}
Ok(left)
}
pub fn term(&mut self) -> Result<AST, KabelError> {
let mut left = self.factor()?;
while self.current < self.input.len()
&& (self.peek()?.token_type == TokenType::Plus
|| self.peek()?.token_type == TokenType::Minus)
{
let binop = self.read_token()?;
let right = self.factor()?;
if binop.token_type == TokenType::Plus {
left = ast_from_ast!(AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Add, Box::new(right.clone())),
left,
right
);
} else {
left = ast_from_ast!(AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Sub, Box::new(right.clone())),
left,
right
);
}
}
Ok(left)
}
pub fn factor(&mut self) -> Result<AST, KabelError> {
let mut left = self.unary()?;
while self.current < self.input.len()
&& (self.peek()?.token_type == TokenType::Star
|| self.peek()?.token_type == TokenType::Slash
|| self.peek()?.token_type == TokenType::Percent)
{
let binop = self.read_token()?;
let right = self.unary()?;
if binop.token_type == TokenType::Star {
left = ast_from_ast!(AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Mul, Box::new(right.clone())),
left,
right
);
} else if binop.token_type == TokenType::Slash {
left = ast_from_ast!(AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Div, Box::new(right.clone())),
left,
right
);
} else {
left = ast_from_ast!(AST,
ASTType::Binary(Box::new(left.clone()), BinOp::Mod, Box::new(right.clone())),
left,
right
);
}
}
Ok(left)
}
pub fn unary(&mut self) -> Result<AST, KabelError> {
if let TokenType::Bang | TokenType::Minus = self.peek()?.token_type {
let token = self.read_token()?;
let unary = self.unary()?;
if token.token_type == TokenType::Bang {
return Ok(ast_from_token_ast!(AST,
ASTType::Unary(UnOp::Not, Box::new(unary.clone())),
token,
unary
));
} else {
return Ok(ast_from_token_ast!(AST,
ASTType::Unary(UnOp::Neg, Box::new(unary.clone())),
token,
unary
));
}
}
self.subscript()
}
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 {
self.read_token()?;
let expr = self.expression()?;
let right_brace = self.read_token()?;
if let TokenType::RightSquare = right_brace.token_type {
primary = ast_from_ast_token!(AST,
ASTType::Subscript(Box::new(primary.clone()), Box::new(expr)),
primary,
right_brace
);
} else {
return Err(unexpected_token!(self, "Expected ] but found {}", right_brace));
}
}
Ok(primary)
}
pub fn primary(&mut self) -> Result<AST, KabelError> {
let token = self.read_token()?;
match token.token_type {
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);
}
if let TokenType::PlusPlus | TokenType::MinusMinus = self.peek()?.token_type {
return self.incdec(token);
}
}
return Ok(lit!(Ident, ident.clone(), token));
}
TokenType::Num(num) => {
return Ok(lit!(Num, num, token));
}
TokenType::Str(string) => {
return Ok(lit!(Str, string, token));
}
TokenType::True => return Ok(lit!(Bool, true, token)),
TokenType::False => return Ok(lit!(Bool, false, token)),
TokenType::LeftParen => {
return self.group(token);
}
TokenType::LeftSquare => {
return self.array(token);
}
_ => {
return Err(unexpected_token!(self, "Unexpected token {}", token));
}
}
}
pub fn array(&mut self, left_square: Token) -> Result<AST, KabelError> {
let mut expressions = Vec::new();
while self.peek()?.token_type != TokenType::RightSquare {
expressions.push(self.expression()?);
if let TokenType::Comma = self.peek()?.token_type {
self.read_token()?;
}
}
let right_square = self.read_token()?;
Ok(ast_from_token!(AST,
ASTType::Lit(Lit::Array(expressions)),
left_square,
right_square
))
}
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_from_ast!(AST,
ASTType::Member(Box::new(expr.clone()), Box::new(call.clone())),
expr,
call
);
if self.current >= self.input.len() {
break;
}
continue;
}
}
expr = ast_from_ast_token!(AST,
ASTType::Member(
Box::new(expr.clone()),
Box::new(lit!(Ident, child_str, child))
),
expr,
child
);
} else {
return Err(unexpected_token!(self, "Unexpected token {}", child));
}
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_from_token!(AST,
ASTType::Call(Box::new(lit!(Ident, name, ident)), expressions),
ident,
right_paren
));
}
panic!("Call logic broke");
}
pub fn incdec(&mut self, ident: Token) -> Result<AST, KabelError> {
if let TokenType::Ident(name) = ident.token_type {
let oper = self.read_token()?;
if oper.token_type == TokenType::PlusPlus {
return Ok(ast_from_token!(AST,
ASTType::Assign(
ast_from_token!(LhsAssign, LhsAssignType::Ident(name.clone()), ident, ident),
Box::new(ast_from_token!(AST,
ASTType::Binary(
Box::new(lit!(Ident, name, ident)),
BinOp::Add,
Box::new(lit!(Num, 1., oper))
),
oper,
oper
))
),
ident,
oper
));
} else {
return Ok(ast_from_token!(AST,
ASTType::Assign(
ast_from_token!(LhsAssign, LhsAssignType::Ident(name.clone()), ident, ident),
Box::new(ast_from_token!(AST,
ASTType::Binary(
Box::new(lit!(Ident, name, ident)),
BinOp::Sub,
Box::new(lit!(Num, 1., oper))
),
oper,
oper
))
),
ident,
oper
));
}
}
panic!("Inc/dec logic broke");
}
pub fn group(&mut self, left_paren: Token) -> Result<AST, KabelError> {
let expr = self.expression()?;
let right_paren = self.peek();
if let Ok(right_paren) = right_paren {
if right_paren.token_type != TokenType::RightParen {
return Err(KabelError::new(
ErrorKind::MissingDelimiter,
"Missing right parenthesis".to_string(),
None,
right_paren.line,
right_paren.start_column,
self.text[left_paren.line..right_paren.line].iter().fold("".to_string(), |acc, string| acc + string + "\n"),
));
}
self.read_token()?;
return Ok(ast_from_token!(AST,
expr.kind,
left_paren,
right_paren
));
}
if let Err(e) = right_paren {
return Err(KabelError::new(
ErrorKind::MissingDelimiter,
"Missing right parenthesis".to_string(),
None,
e.line,
e.column,
collect_lines!(self.text[left_paren.line..expr.end_line]),
));
}
unreachable!();
}
pub fn read_token(&mut self) -> Result<Token, KabelError> {
if self.current >= self.input.len() {
let last_token = self.input[self.input.len() - 1].clone();
return Err(KabelError::new(
ErrorKind::UnexpectedEof,
"Unexpected end of file".to_string(),
None,
last_token.line,
last_token.start_column,
self.text[last_token.line].clone(),
));
}
self.token = self.input[self.current].clone();
self.current += 1;
return Ok(self.token.clone());
}
pub fn peek(&mut self) -> Result<Token, KabelError> {
if self.current >= self.input.len() {
let last_token = self.input[self.input.len() - 1].clone();
return Err(KabelError::new(
ErrorKind::UnexpectedEof,
"Unexpected end of file".to_string(),
None,
last_token.line,
last_token.start_column,
self.text[last_token.line].clone(),
));
}
return Ok(self.input[self.current].clone());
}
}