use crate::ast::*;
use crate::error::{Error, Result};
use crate::lexer::{Token, TokenKind};
use crate::value::Value;
use std::collections::HashMap;
pub struct Parser {
tokens: Vec<Token>,
current: usize,
}
impl Parser {
pub fn new(tokens: Vec<Token>) -> Self {
Self { tokens, current: 0 }
}
pub fn parse(&mut self) -> Result<Program> {
let mut statements = Vec::new();
while !self.is_at_end() {
if self.match_token(&TokenKind::Newline) {
continue;
}
statements.push(self.declaration()?);
}
Ok(Program { statements })
}
fn declaration(&mut self) -> Result<Statement> {
if self.match_token(&TokenKind::Let) {
self.var_declaration(false)
} else if self.match_token(&TokenKind::Const) {
self.var_declaration(true)
} else if self.match_token(&TokenKind::Function) {
self.function_declaration()
} else {
self.statement()
}
}
fn var_declaration(&mut self, is_const: bool) -> Result<Statement> {
let name = self.consume_identifier("Expected variable name")?;
self.consume(&TokenKind::Assign, "Expected '=' after variable name")?;
let value = self.expression()?;
self.consume_statement_terminator()?;
Ok(Statement::VarDeclaration {
name,
value,
is_const,
})
}
fn function_declaration(&mut self) -> Result<Statement> {
let name = self.consume_identifier("Expected function name")?;
self.consume(&TokenKind::LeftParen, "Expected '(' after function name")?;
let mut parameters = Vec::new();
if !self.check(&TokenKind::RightParen) {
loop {
let param_name = self.consume_identifier("Expected parameter name")?;
let param_type = if self.match_token(&TokenKind::Colon) {
Some(self.parse_type()?)
} else {
None
};
let default_value = if self.match_token(&TokenKind::Assign) {
Some(self.expression()?)
} else {
None
};
parameters.push(Parameter {
name: param_name,
param_type,
default_value,
});
if !self.match_token(&TokenKind::Comma) {
break;
}
}
}
self.consume(&TokenKind::RightParen, "Expected ')' after parameters")?;
let return_type = if self.match_token(&TokenKind::Arrow) {
Some(self.parse_type()?)
} else {
None
};
self.consume(&TokenKind::LeftBrace, "Expected '{' before function body")?;
let body = self.block_statement()?;
Ok(Statement::Function {
name,
parameters,
body: vec![body],
return_type,
})
}
fn parse_type(&mut self) -> Result<Type> {
match &self.advance().kind {
TokenKind::Identifier(name) => match name.as_str() {
"string" => Ok(Type::String),
"number" => Ok(Type::Number),
"boolean" => Ok(Type::Boolean),
"any" => Ok(Type::Any),
"null" => Ok(Type::Null),
_ => Err(self.error("Unknown type")),
},
TokenKind::LeftBracket => {
let element_type = self.parse_type()?;
self.consume(&TokenKind::RightBracket, "Expected ']' after array element type")?;
Ok(Type::Array(Box::new(element_type)))
}
TokenKind::LeftBrace => {
let mut fields = HashMap::new();
while !self.check(&TokenKind::RightBrace) && !self.is_at_end() {
let field_name = self.consume_identifier("Expected field name")?;
self.consume(&TokenKind::Colon, "Expected ':' after field name")?;
let field_type = self.parse_type()?;
fields.insert(field_name, field_type);
if !self.match_token(&TokenKind::Comma) {
break;
}
}
self.consume(&TokenKind::RightBrace, "Expected '}' after object type")?;
Ok(Type::Object(fields))
}
_ => Err(self.error("Expected type")),
}
}
fn statement(&mut self) -> Result<Statement> {
if self.match_token(&TokenKind::If) {
self.if_statement()
} else if self.match_token(&TokenKind::While) {
self.while_statement()
} else if self.match_token(&TokenKind::For) {
self.for_statement()
} else if self.match_token(&TokenKind::Return) {
self.return_statement()
} else if self.match_token(&TokenKind::Break) {
self.consume_statement_terminator()?;
Ok(Statement::Break)
} else if self.match_token(&TokenKind::Continue) {
self.consume_statement_terminator()?;
Ok(Statement::Continue)
} else if self.match_token(&TokenKind::LeftBrace) {
self.block_statement()
} else {
self.expression_statement()
}
}
fn if_statement(&mut self) -> Result<Statement> {
let condition = self.expression()?;
self.consume(&TokenKind::LeftBrace, "Expected '{' after if condition")?;
let then_branch = self.block_body()?;
let else_branch = if self.match_token(&TokenKind::Else) {
if self.match_token(&TokenKind::If) {
Some(vec![self.if_statement()?])
} else {
self.consume(&TokenKind::LeftBrace, "Expected '{' after else")?;
Some(self.block_body()?)
}
} else {
None
};
Ok(Statement::If {
condition,
then_branch,
else_branch,
})
}
fn while_statement(&mut self) -> Result<Statement> {
let condition = self.expression()?;
self.consume(&TokenKind::LeftBrace, "Expected '{' after while condition")?;
let body = self.block_body()?;
Ok(Statement::While { condition, body })
}
fn for_statement(&mut self) -> Result<Statement> {
let variable = self.consume_identifier("Expected variable name in for loop")?;
self.consume(&TokenKind::In, "Expected 'in' after for loop variable")?;
let iterable = self.expression()?;
self.consume(&TokenKind::LeftBrace, "Expected '{' after for loop iterable")?;
let body = self.block_body()?;
Ok(Statement::For {
variable,
iterable,
body,
})
}
fn return_statement(&mut self) -> Result<Statement> {
let value = if self.check(&TokenKind::Newline) || self.check(&TokenKind::Semicolon) || self.is_at_end() {
None
} else {
Some(self.expression()?)
};
self.consume_statement_terminator()?;
Ok(Statement::Return(value))
}
fn block_statement(&mut self) -> Result<Statement> {
let statements = self.block_body()?;
Ok(Statement::Block(statements))
}
fn block_body(&mut self) -> Result<Vec<Statement>> {
let mut statements = Vec::new();
while !self.check(&TokenKind::RightBrace) && !self.is_at_end() {
if self.match_token(&TokenKind::Newline) {
continue;
}
statements.push(self.declaration()?);
}
self.consume(&TokenKind::RightBrace, "Expected '}' after block")?;
Ok(statements)
}
fn expression_statement(&mut self) -> Result<Statement> {
let expr = self.expression()?;
if let Expression::Variable(name) = &expr {
if let Some(op) = self.assignment_operator() {
let value = self.expression()?;
self.consume_statement_terminator()?;
return Ok(Statement::Assignment {
target: AssignmentTarget::Variable(name.clone()),
operator: op,
value,
});
}
} else if let Expression::Property { object, property } = &expr {
if let Some(op) = self.assignment_operator() {
let value = self.expression()?;
self.consume_statement_terminator()?;
return Ok(Statement::Assignment {
target: AssignmentTarget::Property {
object: *object.clone(),
property: property.clone(),
},
operator: op,
value,
});
}
} else if let Expression::Index { object, index } = &expr {
if let Some(op) = self.assignment_operator() {
let value = self.expression()?;
self.consume_statement_terminator()?;
return Ok(Statement::Assignment {
target: AssignmentTarget::Index {
object: *object.clone(),
index: *index.clone(),
},
operator: op,
value,
});
}
}
self.consume_statement_terminator()?;
Ok(Statement::Expression(expr))
}
fn assignment_operator(&mut self) -> Option<AssignmentOperator> {
if self.match_token(&TokenKind::Assign) {
Some(AssignmentOperator::Assign)
} else if self.match_token(&TokenKind::PlusAssign) {
Some(AssignmentOperator::PlusAssign)
} else if self.match_token(&TokenKind::MinusAssign) {
Some(AssignmentOperator::MinusAssign)
} else {
None
}
}
fn expression(&mut self) -> Result<Expression> {
self.conditional()
}
fn conditional(&mut self) -> Result<Expression> {
let expr = self.logical_or()?;
if self.match_token(&TokenKind::Question) {
let true_expr = self.expression()?;
self.consume(&TokenKind::Colon, "Expected ':' after conditional true expression")?;
let false_expr = self.expression()?;
Ok(Expression::Conditional {
condition: Box::new(expr),
true_expr: Box::new(true_expr),
false_expr: Box::new(false_expr),
})
} else {
Ok(expr)
}
}
fn logical_or(&mut self) -> Result<Expression> {
let mut expr = self.logical_and()?;
while self.match_token(&TokenKind::Or) {
let right = self.logical_and()?;
expr = Expression::Binary {
left: Box::new(expr),
operator: BinaryOperator::Or,
right: Box::new(right),
};
}
Ok(expr)
}
fn logical_and(&mut self) -> Result<Expression> {
let mut expr = self.equality()?;
while self.match_token(&TokenKind::And) {
let right = self.equality()?;
expr = Expression::Binary {
left: Box::new(expr),
operator: BinaryOperator::And,
right: Box::new(right),
};
}
Ok(expr)
}
fn equality(&mut self) -> Result<Expression> {
let mut expr = self.comparison()?;
while let Some(op) = self.match_equality_operator() {
let right = self.comparison()?;
expr = Expression::Binary {
left: Box::new(expr),
operator: op,
right: Box::new(right),
};
}
Ok(expr)
}
fn match_equality_operator(&mut self) -> Option<BinaryOperator> {
if self.match_token(&TokenKind::Equal) {
Some(BinaryOperator::Equal)
} else if self.match_token(&TokenKind::NotEqual) {
Some(BinaryOperator::NotEqual)
} else {
None
}
}
fn comparison(&mut self) -> Result<Expression> {
let mut expr = self.term()?;
while let Some(op) = self.match_comparison_operator() {
let right = self.term()?;
expr = Expression::Binary {
left: Box::new(expr),
operator: op,
right: Box::new(right),
};
}
Ok(expr)
}
fn match_comparison_operator(&mut self) -> Option<BinaryOperator> {
if self.match_token(&TokenKind::Greater) {
Some(BinaryOperator::Greater)
} else if self.match_token(&TokenKind::GreaterEqual) {
Some(BinaryOperator::GreaterEqual)
} else if self.match_token(&TokenKind::Less) {
Some(BinaryOperator::Less)
} else if self.match_token(&TokenKind::LessEqual) {
Some(BinaryOperator::LessEqual)
} else {
None
}
}
fn term(&mut self) -> Result<Expression> {
let mut expr = self.factor()?;
while let Some(op) = self.match_term_operator() {
let right = self.factor()?;
expr = Expression::Binary {
left: Box::new(expr),
operator: op,
right: Box::new(right),
};
}
Ok(expr)
}
fn match_term_operator(&mut self) -> Option<BinaryOperator> {
if self.match_token(&TokenKind::Minus) {
Some(BinaryOperator::Subtract)
} else if self.match_token(&TokenKind::Plus) {
Some(BinaryOperator::Add)
} else {
None
}
}
fn factor(&mut self) -> Result<Expression> {
let mut expr = self.unary()?;
while let Some(op) = self.match_factor_operator() {
let right = self.unary()?;
expr = Expression::Binary {
left: Box::new(expr),
operator: op,
right: Box::new(right),
};
}
Ok(expr)
}
fn match_factor_operator(&mut self) -> Option<BinaryOperator> {
if self.match_token(&TokenKind::Divide) {
Some(BinaryOperator::Divide)
} else if self.match_token(&TokenKind::Multiply) {
Some(BinaryOperator::Multiply)
} else if self.match_token(&TokenKind::Modulo) {
Some(BinaryOperator::Modulo)
} else {
None
}
}
fn unary(&mut self) -> Result<Expression> {
if let Some(op) = self.match_unary_operator() {
let operand = self.unary()?;
Ok(Expression::Unary {
operator: op,
operand: Box::new(operand),
})
} else {
self.call()
}
}
fn match_unary_operator(&mut self) -> Option<UnaryOperator> {
if self.match_token(&TokenKind::Minus) {
Some(UnaryOperator::Minus)
} else if self.match_token(&TokenKind::Not) {
Some(UnaryOperator::Not)
} else if self.match_token(&TokenKind::Tilde) {
Some(UnaryOperator::BitwiseNot)
} else {
None
}
}
fn call(&mut self) -> Result<Expression> {
let mut expr = self.primary()?;
loop {
if self.match_token(&TokenKind::LeftParen) {
expr = self.finish_call(expr)?;
} else if self.match_token(&TokenKind::Dot) {
let property = self.consume_identifier("Expected property name after '.'")?;
expr = Expression::Property {
object: Box::new(expr),
property,
};
} else if self.match_token(&TokenKind::LeftBracket) {
let index = self.expression()?;
self.consume(&TokenKind::RightBracket, "Expected ']' after index")?;
expr = Expression::Index {
object: Box::new(expr),
index: Box::new(index),
};
} else {
break;
}
}
Ok(expr)
}
fn finish_call(&mut self, callee: Expression) -> Result<Expression> {
let mut arguments = Vec::new();
if !self.check(&TokenKind::RightParen) {
loop {
arguments.push(self.expression()?);
if !self.match_token(&TokenKind::Comma) {
break;
}
}
}
self.consume(&TokenKind::RightParen, "Expected ')' after arguments")?;
Ok(Expression::Call {
callee: Box::new(callee),
arguments,
})
}
fn primary(&mut self) -> Result<Expression> {
let token = self.advance().clone();
match &token.kind {
TokenKind::Number(n) => Ok(Expression::Literal(Value::Number(*n))),
TokenKind::String(s) => Ok(Expression::Literal(Value::String(s.clone()))),
TokenKind::True => Ok(Expression::Literal(Value::Boolean(true))),
TokenKind::False => Ok(Expression::Literal(Value::Boolean(false))),
TokenKind::Null => Ok(Expression::Literal(Value::Null)),
TokenKind::Identifier(name) => Ok(Expression::Variable(name.clone())),
TokenKind::LeftParen => {
let expr = self.expression()?;
self.consume(&TokenKind::RightParen, "Expected ')' after expression")?;
Ok(expr)
}
TokenKind::LeftBracket => self.array_literal(),
TokenKind::LeftBrace => self.object_literal(),
_ => Err(self.error_at_token(&token, "Expected expression")),
}
}
fn array_literal(&mut self) -> Result<Expression> {
let mut elements = Vec::new();
if !self.check(&TokenKind::RightBracket) {
loop {
elements.push(self.expression()?);
if !self.match_token(&TokenKind::Comma) {
break;
}
}
}
self.consume(&TokenKind::RightBracket, "Expected ']' after array elements")?;
Ok(Expression::Array(elements))
}
fn object_literal(&mut self) -> Result<Expression> {
let mut properties = HashMap::new();
if !self.check(&TokenKind::RightBrace) {
loop {
let key = self.consume_identifier("Expected property name")?;
self.consume(&TokenKind::Colon, "Expected ':' after property name")?;
let value = self.expression()?;
properties.insert(key, value);
if !self.match_token(&TokenKind::Comma) {
break;
}
}
}
self.consume(&TokenKind::RightBrace, "Expected '}' after object properties")?;
Ok(Expression::Object(properties))
}
fn consume_identifier(&mut self, message: &str) -> Result<String> {
if let TokenKind::Identifier(name) = &self.peek().kind {
let name = name.clone();
self.advance();
Ok(name)
} else {
Err(self.error(message))
}
}
fn consume_statement_terminator(&mut self) -> Result<()> {
if self.match_token(&TokenKind::Semicolon) || self.match_token(&TokenKind::Newline) || self.is_at_end() {
Ok(())
} else {
Err(self.error("Expected newline or ';' after statement"))
}
}
fn match_token(&mut self, kind: &TokenKind) -> bool {
if self.check(kind) {
self.advance();
true
} else {
false
}
}
fn consume(&mut self, kind: &TokenKind, message: &str) -> Result<&Token> {
if self.check(kind) {
Ok(self.advance())
} else {
Err(self.error(message))
}
}
fn check(&self, kind: &TokenKind) -> bool {
if self.is_at_end() {
return false;
}
&self.peek().kind == kind
}
fn advance(&mut self) -> &Token {
if !self.is_at_end() {
self.current += 1;
}
self.previous()
}
fn is_at_end(&self) -> bool {
self.peek().kind == TokenKind::Eof
}
fn peek(&self) -> &Token {
&self.tokens[self.current]
}
fn previous(&self) -> &Token {
&self.tokens[self.current - 1]
}
fn error(&self, message: &str) -> Error {
self.error_at_token(self.peek(), message)
}
fn error_at_token(&self, token: &Token, message: &str) -> Error {
Error::parse_error(token.line, message.to_string())
}
}