use crate::lexer::tokens::{Token, Keyword, Operator, Punctuation, Literal};
use crate::parser::ast::{
Expression, Statement, Program, LetStatement, ReturnStatement, FunctionStatement,
Parameter, FunctionCall, SpawnStatement, AgentStatement, MessageStatement,
EventStatement, IfStatement, WhileStatement, TryStatement, CatchBlock, Attribute, BlockStatement,
AttributeTarget, ServiceStatement, ServiceField, EventDeclaration, CompilationTargetInfo,
FieldVisibility, ForInStatement
};
use crate::parser::error::{ParserError, ErrorContext, ErrorRecovery};
use std::collections::{HashMap, HashSet};
pub struct Parser {
tokens: Vec<Token>,
token_positions: Vec<(usize, usize)>, pub(crate) recovery_skip_from: Option<usize>,
pub(crate) recovery_continue_at: Option<usize>,
}
impl Parser {
const MAX_RECURSION_DEPTH: usize = 100;
pub fn new(tokens: Vec<Token>) -> Self {
Self {
tokens,
token_positions: Vec::new(),
recovery_skip_from: None,
recovery_continue_at: None,
}
}
pub fn new_with_positions(tokens_with_pos: Vec<crate::lexer::tokens::TokenWithPosition>) -> Self {
let mut tokens = Vec::new();
let mut positions = Vec::new();
for twp in tokens_with_pos {
positions.push((twp.line, twp.column));
tokens.push(twp.token);
}
Self {
tokens,
token_positions: positions,
recovery_skip_from: None,
recovery_continue_at: None,
}
}
pub fn set_recovery_skip_from(&mut self, position: usize) {
self.recovery_skip_from = Some(position);
}
pub fn get_recovery_continue_at(&mut self) -> Option<usize> {
self.recovery_continue_at.take()
}
pub(crate) fn skip_to_sync_point_from(&mut self, start: usize) -> bool {
let mut pos = start;
while pos < self.tokens.len() {
let token = &self.tokens[pos];
let is_sync = match token {
Token::Punctuation(Punctuation::Semicolon) | Token::Punctuation(Punctuation::RightBrace) => true,
Token::EOF => true,
Token::Keyword(k) => matches!(k,
Keyword::Let | Keyword::Fn | Keyword::If | Keyword::While | Keyword::Try
| Keyword::For | Keyword::Return | Keyword::Service | Keyword::Agent
| Keyword::Spawn | Keyword::Event | Keyword::Msg | Keyword::Async
),
Token::Punctuation(Punctuation::LeftBrace) => true,
Token::Punctuation(Punctuation::At) => true,
_ => false,
};
if is_sync {
self.recovery_continue_at = Some(pos);
return true;
}
pos += 1;
}
self.recovery_continue_at = Some(pos);
true
}
fn get_token_position(&self, position: usize) -> (usize, usize) {
if position < self.token_positions.len() {
self.token_positions[position]
} else {
(1, 1)
}
}
fn error_unexpected_token(&self, position: usize, expected: &[&str]) -> ParserError {
let token = self.tokens.get(position).unwrap_or(&Token::EOF);
let (line, column) = self.get_token_position(position);
ParserError::unexpected_token(token, expected, line, column)
}
pub fn parse(&mut self) -> Result<Program, ParserError> {
let mut program = Program::new();
let mut position = 0;
while position < self.tokens.len() {
let (new_position, statement) = self.parse_statement(position, 0)?;
program.add_statement(statement);
position = new_position;
}
Ok(program)
}
pub fn parse_with_recovery(&mut self) -> (Program, Vec<ParserError>) {
let mut program = Program::new();
let mut errors = Vec::new();
let mut position = 0;
while position < self.tokens.len() {
match self.parse_statement(position, 0) {
Ok((new_position, statement)) => {
program.add_statement(statement);
position = new_position;
}
Err(e) => {
errors.push(e.clone());
self.set_recovery_skip_from(position);
if self.recover_from_error(&e).is_ok() {
if let Some(next_pos) = self.get_recovery_continue_at() {
position = next_pos;
} else {
break;
}
} else {
break;
}
}
}
}
(program, errors)
}
fn parse_statement(&mut self, position: usize, depth: usize) -> Result<(usize, Statement), ParserError> {
if depth > Self::MAX_RECURSION_DEPTH {
let (line, _column) = self.get_token_position(position);
return Err(ParserError::SemanticError {
message: format!("Maximum recursion depth ({}) exceeded in statement parsing", Self::MAX_RECURSION_DEPTH),
line,
context: ErrorContext::new(),
});
}
if let Some(Token::Punctuation(Punctuation::At)) = self.tokens.get(position) {
let mut current_position = position;
let mut attributes = Vec::new();
while current_position < self.tokens.len() {
if let Some(Token::Punctuation(Punctuation::At)) = self.tokens.get(current_position) {
let (new_pos, attr) = self.parse_attribute(current_position)?;
attributes.push(attr);
current_position = new_pos;
} else {
break;
}
}
if let Some(Token::Keyword(Keyword::Fn)) = self.tokens.get(current_position) {
let (new_pos, mut func_stmt) = self.parse_function_statement(current_position)?;
if let Statement::Function(ref mut func) = func_stmt {
func.attributes = attributes;
}
return Ok((new_pos, func_stmt));
} else if let Some(Token::Keyword(Keyword::Async)) = self.tokens.get(current_position) {
let (new_pos, mut func_stmt) = self.parse_async_function_statement(current_position)?;
if let Statement::Function(ref mut func) = func_stmt {
func.attributes = attributes;
}
return Ok((new_pos, func_stmt));
} else if let Some(Token::Keyword(Keyword::Service)) = self.tokens.get(current_position) {
let (new_pos, service_stmt) = self.parse_service_statement_with_attributes(current_position, attributes)?;
return Ok((new_pos, service_stmt));
} else {
let expected = vec!["function declaration", "service declaration"];
return Err(self.error_unexpected_token(current_position, &expected));
}
}
if let Some(Token::Keyword(Keyword::Let)) = self.tokens.get(position) {
self.parse_let_statement(position)
} else if let Some(Token::Keyword(Keyword::Fn)) = self.tokens.get(position) {
self.parse_function_statement(position)
} else if let Some(Token::Keyword(Keyword::Spawn)) = self.tokens.get(position) {
self.parse_spawn_statement(position)
} else if let Some(Token::Keyword(Keyword::Agent)) = self.tokens.get(position) {
self.parse_agent_statement(position)
} else if let Some(Token::Keyword(Keyword::Msg)) = self.tokens.get(position) {
self.parse_message_statement(position)
} else if let Some(Token::Keyword(Keyword::Event)) = self.tokens.get(position) {
self.parse_event_statement(position)
} else if let Some(Token::Keyword(Keyword::If)) = self.tokens.get(position) {
self.parse_if_statement(position)
} else if let Some(Token::Keyword(Keyword::While)) = self.tokens.get(position) {
self.parse_while_statement(position)
} else if let Some(Token::Keyword(Keyword::Try)) = self.tokens.get(position) {
self.parse_try_statement(position)
} else if let Some(Token::Keyword(Keyword::For)) = self.tokens.get(position) {
self.parse_for_in_statement(position)
} else if let Some(Token::Keyword(Keyword::Service)) = self.tokens.get(position) {
self.parse_service_statement(position)
} else if let Some(Token::Keyword(Keyword::Return)) = self.tokens.get(position) {
self.parse_return_statement(position)
} else if let Some(Token::Punctuation(Punctuation::LeftBrace)) = self.tokens.get(position) {
let (new_position, block) = self.parse_block_statement(position, depth + 1)?;
Ok((new_position, Statement::Block(block)))
} else if let Some(Token::Punctuation(Punctuation::Semicolon)) = self.tokens.get(position) {
Ok((position + 1, Statement::Expression(Expression::Literal(Literal::Null))))
} else if let Some(Token::EOF) = self.tokens.get(position) {
Ok((position + 1, Statement::Expression(Expression::Literal(Literal::Null))))
} else {
if let Some(Token::Keyword(Keyword::Service)) = self.tokens.get(position) {
return self.parse_service_statement(position);
}
let (new_position, expr) = self.parse_expression(position)?;
Ok((new_position, Statement::Expression(expr)))
}
}
fn parse_let_statement(&mut self, position: usize) -> Result<(usize, Statement), ParserError> {
let mut current_position = position + 1;
let _is_mutable = if let Some(Token::Keyword(Keyword::Mut)) = self.tokens.get(current_position) {
current_position += 1;
true
} else {
false
};
let (new_position, name) = self.expect_identifier_or_keyword(current_position)?;
current_position = new_position;
let (new_position, _) = self.expect_token(current_position, &Token::Operator(Operator::Assign))?;
current_position = new_position;
let (new_position, value) = self.parse_expression(current_position)?;
current_position = new_position;
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::Semicolon))?;
current_position = new_position;
Ok((current_position, Statement::Let(LetStatement { name, value })))
}
fn parse_return_statement(&mut self, position: usize) -> Result<(usize, Statement), ParserError> {
let mut current_position = position + 1;
let value = if let Some(Token::Punctuation(Punctuation::Semicolon)) = self.tokens.get(current_position) {
None
} else {
let (new_position, expr) = self.parse_expression(current_position)?;
current_position = new_position;
Some(expr)
};
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::Semicolon))?;
Ok((new_position, Statement::Return(ReturnStatement { value })))
}
fn parse_block_statement(&mut self, position: usize, depth: usize) -> Result<(usize, BlockStatement), ParserError> {
if depth > Self::MAX_RECURSION_DEPTH {
let (line, _column) = self.get_token_position(position);
return Err(ParserError::SemanticError {
message: format!("Maximum recursion depth ({}) exceeded in block statement parsing", Self::MAX_RECURSION_DEPTH),
line,
context: ErrorContext::new(),
});
}
let (position, _) = self.expect_token(position, &Token::Punctuation(Punctuation::LeftBrace))?;
let mut block = BlockStatement::new();
let mut current_position = position;
while current_position < self.tokens.len() {
if let Some(Token::Punctuation(Punctuation::RightBrace)) = self.tokens.get(current_position) {
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::RightBrace))?;
return Ok((new_position, block));
}
let (new_position, statement) = self.parse_statement(current_position, depth + 1)?;
block.add_statement(statement);
current_position = new_position;
}
Err(ParserError::unexpected_eof("}"))
}
fn parse_expression(&mut self, position: usize) -> Result<(usize, Expression), ParserError> {
self.parse_assignment(position, 0) }
fn parse_expression_with_depth(&mut self, position: usize, depth: usize) -> Result<(usize, Expression), ParserError> {
self.parse_assignment(position, depth)
}
fn parse_assignment(&mut self, position: usize, depth: usize) -> Result<(usize, Expression), ParserError> {
if depth > Self::MAX_RECURSION_DEPTH {
let (line, column) = self.get_token_position(position);
return Err(ParserError::SemanticError {
message: format!(
"Maximum recursion depth ({}) exceeded at line {}, column {}. This may indicate malformed input or a parser bug.",
Self::MAX_RECURSION_DEPTH, line, column
),
line,
context: ErrorContext::new(),
});
}
let (position, expr) = self.parse_or(position, depth)?;
if let Some(Token::Operator(Operator::Assign)) = self.tokens.get(position) {
let (position, _) = self.expect_token(position, &Token::Operator(Operator::Assign))?;
let (position, value) = self.parse_assignment(position, depth + 1)?;
match expr {
Expression::Identifier(name) => {
return Ok((position, Expression::Assignment(name, Box::new(value))));
}
Expression::FieldAccess(object_expr, field_name) => {
return Ok((position, Expression::FieldAssignment(object_expr, field_name, Box::new(value))));
}
Expression::IndexAccess(container, index_expr) => {
let mut args = vec![*container.clone(), *index_expr.clone(), value];
match container.as_ref() {
Expression::Identifier(var_name) => {
args.push(Expression::Literal(Literal::String(var_name.clone())));
}
Expression::FieldAccess(_, field_name) => {
args.push(Expression::Literal(Literal::String(String::new()))); args.push(Expression::Literal(Literal::String(field_name.clone()))); }
_ => {}
}
return Ok((position, Expression::FunctionCall(FunctionCall {
name: "__index_assign__".to_string(),
arguments: args,
})));
}
Expression::FunctionCall(call) if call.name == "__index__" && call.arguments.len() == 2 => {
let mut args = vec![call.arguments[0].clone(), call.arguments[1].clone(), value];
match &call.arguments[0] {
Expression::Identifier(var_name) => {
args.push(Expression::Literal(Literal::String(var_name.clone())));
}
Expression::FieldAccess(_, field_name) => {
args.push(Expression::Literal(Literal::String(String::new())));
args.push(Expression::Literal(Literal::String(field_name.clone())));
}
_ => {}
}
return Ok((position, Expression::FunctionCall(FunctionCall {
name: "__index_assign__".to_string(),
arguments: args,
})));
}
_ => {
return Err(ParserError::invalid_function_call(
"assignment",
"Invalid assignment target - expected identifier, field access, or array access",
1
));
}
}
}
Ok((position, expr))
}
fn parse_or(&mut self, position: usize, depth: usize) -> Result<(usize, Expression), ParserError> {
let mut current_position = position;
let (new_position, mut expr) = self.parse_and(current_position, depth)?;
current_position = new_position;
while current_position < self.tokens.len() {
if let Some(Token::Operator(Operator::Or)) = self.tokens.get(current_position) {
let (new_pos, _) = self.expect_token(current_position, &Token::Operator(Operator::Or))?;
let (new_pos, right) = self.parse_and(new_pos, depth)?;
expr = Expression::BinaryOp(Box::new(expr), Operator::Or, Box::new(right));
current_position = new_pos;
} else {
break;
}
}
Ok((current_position, expr))
}
fn parse_and(&mut self, position: usize, depth: usize) -> Result<(usize, Expression), ParserError> {
let mut current_position = position;
let (new_position, mut expr) = self.parse_equality(current_position, depth)?;
current_position = new_position;
while current_position < self.tokens.len() {
if let Some(Token::Operator(Operator::And)) = self.tokens.get(current_position) {
let (new_pos, _) = self.expect_token(current_position, &Token::Operator(Operator::And))?;
let (new_pos, right) = self.parse_equality(new_pos, depth)?;
expr = Expression::BinaryOp(Box::new(expr), Operator::And, Box::new(right));
current_position = new_pos;
} else {
break;
}
}
Ok((current_position, expr))
}
fn parse_equality(&mut self, position: usize, depth: usize) -> Result<(usize, Expression), ParserError> {
let mut current_position = position;
let (new_position, mut expr) = self.parse_comparison(current_position, depth)?;
current_position = new_position;
while current_position < self.tokens.len() {
if let Some(Token::Operator(Operator::Equal)) = self.tokens.get(current_position) {
let (new_pos, _) = self.expect_token(current_position, &Token::Operator(Operator::Equal))?;
let (new_pos, right) = self.parse_comparison(new_pos, depth)?;
expr = Expression::BinaryOp(Box::new(expr), Operator::Equal, Box::new(right));
current_position = new_pos;
} else if let Some(Token::Operator(Operator::NotEqual)) = self.tokens.get(current_position) {
let (new_pos, _) = self.expect_token(current_position, &Token::Operator(Operator::NotEqual))?;
let (new_pos, right) = self.parse_comparison(new_pos, depth)?;
expr = Expression::BinaryOp(Box::new(expr), Operator::NotEqual, Box::new(right));
current_position = new_pos;
} else {
break;
}
}
Ok((current_position, expr))
}
fn parse_comparison(&mut self, position: usize, depth: usize) -> Result<(usize, Expression), ParserError> {
let mut current_position = position;
let (new_position, mut expr) = self.parse_term(current_position, depth)?;
current_position = new_position;
while current_position < self.tokens.len() {
let op = self.tokens.get(current_position).and_then(|t| {
if let Token::Operator(o) = t { Some(o.clone()) } else { None }
});
if let Some(op) = op {
match &op {
Operator::Less | Operator::LessEqual | Operator::Greater | Operator::GreaterEqual => {
let (new_pos, _) = self.expect_token(current_position, &Token::Operator(op.clone()))?;
let (new_pos, right) = self.parse_term(new_pos, depth)?;
expr = Expression::BinaryOp(Box::new(expr), op, Box::new(right));
current_position = new_pos;
}
_ => break,
}
} else {
break;
}
}
Ok((current_position, expr))
}
fn parse_term(&mut self, position: usize, depth: usize) -> Result<(usize, Expression), ParserError> {
let mut current_position = position;
let (new_position, mut expr) = self.parse_factor(current_position, depth)?;
current_position = new_position;
while current_position < self.tokens.len() {
let op = self.tokens.get(current_position).and_then(|t| {
if let Token::Operator(o) = t { Some(o.clone()) } else { None }
});
if let Some(op) = op {
match &op {
Operator::Plus | Operator::Minus => {
let (new_pos, _) = self.expect_token(current_position, &Token::Operator(op.clone()))?;
let (new_pos, right) = self.parse_factor(new_pos, depth)?;
expr = Expression::BinaryOp(Box::new(expr), op, Box::new(right));
current_position = new_pos;
}
_ => break,
}
} else {
break;
}
}
Ok((current_position, expr))
}
fn parse_factor(&mut self, position: usize, depth: usize) -> Result<(usize, Expression), ParserError> {
let mut current_position = position;
let (new_position, mut expr) = self.parse_unary(current_position, depth)?;
current_position = new_position;
while current_position < self.tokens.len() {
let op = self.tokens.get(current_position).and_then(|t| {
if let Token::Operator(o) = t { Some(o.clone()) } else { None }
});
if let Some(op) = op {
match &op {
Operator::Star | Operator::Slash | Operator::Percent => {
let (new_pos, _) = self.expect_token(current_position, &Token::Operator(op.clone()))?;
let (new_pos, right) = self.parse_unary(new_pos, depth)?;
expr = Expression::BinaryOp(Box::new(expr), op, Box::new(right));
current_position = new_pos;
}
_ => break,
}
} else {
break;
}
}
Ok((current_position, expr))
}
fn parse_unary(&mut self, position: usize, depth: usize) -> Result<(usize, Expression), ParserError> {
if let Some(Token::Keyword(Keyword::Spawn)) = self.tokens.get(position) {
let (position, _) = self.expect_token(position, &Token::Keyword(Keyword::Spawn))?;
let (position, expr) = self.parse_unary(position, depth)?;
return Ok((position, Expression::Spawn(Box::new(expr))));
}
let op = self.tokens.get(position).and_then(|t| {
if let Token::Operator(o) = t { Some(o.clone()) } else { None }
});
if let Some(op) = op {
match &op {
Operator::Minus | Operator::Not => {
let (position, _) = self.expect_token(position, &Token::Operator(op.clone()))?;
let (position, right) = self.parse_unary(position, depth)?;
return Ok((position, Expression::UnaryOp(op, Box::new(right))));
}
_ => {}
}
}
let mut current_position = position;
let (new_position, mut expr) = self.parse_primary(current_position, depth)?;
current_position = new_position;
while current_position < self.tokens.len() {
if let Some(Token::Punctuation(Punctuation::LeftBracket)) = self.tokens.get(current_position) {
let (new_pos, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::LeftBracket))?;
current_position = new_pos;
let (new_pos, index_expr) = self.parse_expression_with_depth(current_position, depth + 1)?;
current_position = new_pos;
let (new_pos, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::RightBracket))?;
current_position = new_pos;
expr = Expression::IndexAccess(Box::new(expr), Box::new(index_expr));
continue;
}
if let Some(Token::Punctuation(Punctuation::Dot)) = self.tokens.get(current_position) {
let (new_pos, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::Dot))?;
current_position = new_pos;
let (new_pos, field_name) = self.expect_identifier_or_keyword(current_position)?;
current_position = new_pos;
if let Some(Token::Punctuation(Punctuation::LeftParen)) = self.tokens.get(current_position) {
let (new_pos, arguments) = self.parse_function_arguments(current_position, depth)?;
current_position = new_pos;
expr = Expression::FunctionCall(FunctionCall {
name: format!("{}.{}", match &expr {
Expression::Identifier(name) => name.clone(),
Expression::FieldAccess(obj, field) => format!("{}.{}", match obj.as_ref() {
Expression::Identifier(n) => n.clone(),
_ => "self".to_string(),
}, field),
_ => "self".to_string(),
}, field_name),
arguments,
});
} else {
expr = Expression::FieldAccess(Box::new(expr), field_name);
}
continue;
}
break;
}
Ok((current_position, expr))
}
fn parse_primary(&mut self, position: usize, depth: usize) -> Result<(usize, Expression), ParserError> {
if let Some(token) = self.tokens.get(position) {
match token {
Token::Literal(Literal::Int(value)) => {
return Ok((position + 1, Expression::Literal(Literal::Int(*value))));
}
Token::Literal(Literal::Float(value)) => {
return Ok((position + 1, Expression::Literal(Literal::Float(*value))));
}
Token::Literal(Literal::String(value)) => {
return Ok((position + 1, Expression::Literal(Literal::String(value.clone()))));
}
Token::Literal(Literal::Bool(value)) => {
return Ok((position + 1, Expression::Literal(Literal::Bool(*value))));
}
Token::Literal(Literal::Null) => {
return Ok((position + 1, Expression::Literal(Literal::Null)));
}
Token::Identifier(name) => {
let namespace_name = name.clone();
if let Some(Token::Operator(Operator::Not)) = self.tokens.get(position + 1) {
if let Some(Token::Punctuation(Punctuation::LeftParen)) = self.tokens.get(position + 2) {
let (new_position, _) = self.expect_token(position + 1, &Token::Operator(Operator::Not))?;
let (new_position, _) = self.expect_token(new_position, &Token::Punctuation(Punctuation::LeftParen))?;
let (new_position, arguments) = self.parse_function_arguments(new_position, depth)?;
let (new_position, _) = self.expect_token(new_position, &Token::Punctuation(Punctuation::RightParen))?;
let macro_name = namespace_name.to_lowercase();
return Ok((new_position, match macro_name.as_str() {
"vec" => Expression::ArrayLiteral(arguments),
"map" => {
if arguments.len() % 2 != 0 {
let (line, col) = self.get_token_position(position);
return Err(ParserError::unexpected_token(
self.tokens.get(position).unwrap_or(&Token::EOF),
&["map! requires even number of arguments (key, value pairs)"],
line, col
));
}
let mut obj = HashMap::new();
for i in (0..arguments.len()).step_by(2) {
let key_expr = &arguments[i];
let key_str = match key_expr {
Expression::Literal(Literal::String(s)) => s.clone(),
_ => {
let (line, col) = self.get_token_position(position);
return Err(ParserError::unexpected_token(
self.tokens.get(position).unwrap_or(&Token::EOF),
&["map! keys must be string literals"],
line, col
));
}
};
obj.insert(key_str, arguments[i + 1].clone());
}
Expression::ObjectLiteral(obj)
}
_ => Expression::FunctionCall(FunctionCall {
name: format!("{}!", namespace_name),
arguments,
}),
}));
}
}
if let Some(Token::Punctuation(Punctuation::DoubleColon)) = self.tokens.get(position + 1) {
let (new_position, _) = self.expect_token(position + 1, &Token::Punctuation(Punctuation::DoubleColon))?;
let (new_position, method_name) = self.expect_identifier_or_keyword(new_position)?;
if let Some(Token::Punctuation(Punctuation::LeftParen)) = self.tokens.get(new_position) {
let (new_position, arguments) = self.parse_function_arguments(new_position, depth)?;
return Ok((new_position, Expression::FunctionCall(FunctionCall {
name: format!("{}::{}", namespace_name, method_name),
arguments,
})));
} else {
return Ok((new_position, Expression::Identifier(format!("{}::{}", namespace_name, method_name))));
}
}
else if let Some(Token::Punctuation(Punctuation::LeftParen)) = self.tokens.get(position + 1) {
let (new_position, arguments) = self.parse_function_arguments(position + 1, depth)?;
return Ok((new_position, Expression::FunctionCall(FunctionCall {
name: namespace_name.clone(),
arguments,
})));
}
else if let Some(Token::Punctuation(Punctuation::Dot)) = self.tokens.get(position + 1) {
let (new_position, _) = self.expect_token(position + 1, &Token::Punctuation(Punctuation::Dot))?;
let (new_position, field_name) = self.expect_identifier_or_keyword(new_position)?;
if let Some(Token::Punctuation(Punctuation::LeftParen)) = self.tokens.get(new_position) {
let (new_pos, arguments) = self.parse_function_arguments(new_position, depth)?;
return Ok((new_pos, Expression::FunctionCall(FunctionCall {
name: format!("{}.{}", namespace_name, field_name),
arguments,
})));
} else {
return Ok((new_position, Expression::FieldAccess(
Box::new(Expression::Identifier(namespace_name)),
field_name
)));
}
} else {
return Ok((position + 1, Expression::Identifier(namespace_name.clone())));
}
}
Token::Keyword(Keyword::Service) => {
let namespace_name = "service".to_string();
if let Some(Token::Punctuation(Punctuation::DoubleColon)) = self.tokens.get(position + 1) {
let (new_position, _) = self.expect_token(position + 1, &Token::Punctuation(Punctuation::DoubleColon))?;
let (new_position, method_name) = self.expect_identifier_or_keyword(new_position)?;
if let Some(Token::Punctuation(Punctuation::LeftParen)) = self.tokens.get(new_position) {
let (new_position, arguments) = self.parse_function_arguments(new_position, depth)?;
return Ok((new_position, Expression::FunctionCall(FunctionCall {
name: format!("{}::{}", namespace_name, method_name),
arguments,
})));
} else {
return Ok((new_position, Expression::Identifier(format!("{}::{}", namespace_name, method_name))));
}
} else {
return Ok((position + 1, Expression::Identifier(namespace_name.clone())));
}
}
Token::Keyword(Keyword::Ai) => {
let namespace_name = "ai".to_string();
if let Some(Token::Punctuation(Punctuation::DoubleColon)) = self.tokens.get(position + 1) {
let (new_position, _) = self.expect_token(position + 1, &Token::Punctuation(Punctuation::DoubleColon))?;
let (new_position, method_name) = self.expect_identifier_or_keyword(new_position)?;
if let Some(Token::Punctuation(Punctuation::LeftParen)) = self.tokens.get(new_position) {
let (new_position, arguments) = self.parse_function_arguments(new_position, depth)?;
return Ok((new_position, Expression::FunctionCall(FunctionCall {
name: format!("{}::{}", namespace_name, method_name),
arguments,
})));
} else {
return Ok((new_position, Expression::Identifier(format!("{}::{}", namespace_name, method_name))));
}
} else {
return Ok((position + 1, Expression::Identifier(namespace_name.clone())));
}
}
Token::Keyword(Keyword::Await) => {
let (position, _) = self.expect_token(position, &Token::Keyword(Keyword::Await))?;
let (position, expr) = self.parse_primary(position, depth)?;
return Ok((position, Expression::Await(Box::new(expr))));
}
Token::Keyword(Keyword::Throw) => {
let (position, _) = self.expect_token(position, &Token::Keyword(Keyword::Throw))?;
let (position, expr) = self.parse_expression_with_depth(position, depth + 1)?;
return Ok((position, Expression::Throw(Box::new(expr))));
}
Token::Keyword(_) => {
let (new_position, name) = self.expect_identifier_or_keyword(position)?;
return Ok((new_position, Expression::Identifier(name)));
}
Token::Punctuation(Punctuation::LeftParen) => {
let (position, _) = self.expect_token(position, &Token::Punctuation(Punctuation::LeftParen))?;
let (position, expr) = self.parse_expression_with_depth(position, depth + 1)?;
let (position, _) = self.expect_token(position, &Token::Punctuation(Punctuation::RightParen))?;
return Ok((position, expr));
}
Token::Punctuation(Punctuation::LeftBrace) => {
let (position, object_literal) = self.parse_object_literal(position)?;
return Ok((position, Expression::ObjectLiteral(object_literal)));
}
Token::Punctuation(Punctuation::LeftBracket) => {
let (position, array_literal) = self.parse_array_literal(position)?;
return Ok((position, Expression::ArrayLiteral(array_literal)));
}
Token::Operator(Operator::Not) => {
let (position, _) = self.expect_token(position, &Token::Operator(Operator::Not))?;
let (position, _) = self.expect_token(position, &Token::Punctuation(Punctuation::LeftParen))?;
let (position, arguments) = self.parse_function_arguments(position, depth)?;
let (position, _) = self.expect_token(position, &Token::Punctuation(Punctuation::RightParen))?;
return Ok((position, Expression::FunctionCall(FunctionCall {
name: "macro".to_string(),
arguments,
})));
}
_ => {}
}
}
let (line, column) = self.get_token_position(position);
Err(ParserError::unexpected_token(
self.tokens.get(position).unwrap_or(&Token::EOF),
&["expression"],
line,
column
))
}
fn parse_function_statement(&mut self, position: usize) -> Result<(usize, Statement), ParserError> {
let mut current_position = position + 1;
let (new_position, name) = self.expect_identifier(current_position)?;
current_position = new_position;
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::LeftParen))?;
current_position = new_position;
let (new_position, parameters) = self.parse_parameters(current_position)?;
current_position = new_position;
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::RightParen))?;
current_position = new_position;
let return_type = if let Some(Token::Punctuation(Punctuation::Arrow)) = self.tokens.get(current_position) {
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::Arrow))?;
current_position = new_position;
let (new_position, return_type) = self.parse_type_expression(current_position)?;
current_position = new_position;
Some(return_type)
} else {
None
};
let (new_position, body) = self.parse_block_statement(current_position, 0)?;
current_position = new_position;
Ok((current_position, Statement::Function(FunctionStatement {
name,
parameters,
return_type,
body,
attributes: Vec::new(),
is_async: false,
})))
}
fn parse_async_function_statement(&mut self, position: usize) -> Result<(usize, Statement), ParserError> {
let mut current_position = position + 1;
let (new_position, _) = self.expect_token(current_position, &Token::Keyword(Keyword::Fn))?;
current_position = new_position;
let (new_position, name) = self.expect_identifier(current_position)?;
current_position = new_position;
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::LeftParen))?;
current_position = new_position;
let (new_position, parameters) = self.parse_parameters(current_position)?;
current_position = new_position;
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::RightParen))?;
current_position = new_position;
let return_type = if let Some(Token::Punctuation(Punctuation::Arrow)) = self.tokens.get(current_position) {
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::Arrow))?;
current_position = new_position;
let (new_position, return_type) = self.parse_type_expression(current_position)?;
current_position = new_position;
Some(return_type)
} else {
None
};
let (new_position, body) = self.parse_block_statement(current_position, 0)?;
current_position = new_position;
Ok((current_position, Statement::Function(FunctionStatement {
name,
parameters,
return_type,
body,
attributes: Vec::new(),
is_async: true,
})))
}
fn parse_parameters(&self, position: usize) -> Result<(usize, Vec<Parameter>), ParserError> {
let mut current_position = position;
let mut parameters = Vec::new();
if let Some(Token::Punctuation(Punctuation::RightParen)) = self.tokens.get(current_position) {
return Ok((current_position, parameters));
}
loop {
let (new_position, name) = self.expect_identifier_or_keyword(current_position)?;
current_position = new_position;
let param_type = if let Some(Token::Punctuation(Punctuation::Colon)) = self.tokens.get(current_position) {
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::Colon))?;
current_position = new_position;
let (new_position, param_type) = self.parse_type_expression(current_position)?;
current_position = new_position;
Some(param_type)
} else {
None
};
parameters.push(Parameter { name, param_type });
if let Some(Token::Punctuation(Punctuation::Comma)) = self.tokens.get(current_position) {
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::Comma))?;
current_position = new_position;
} else {
break;
}
}
Ok((current_position, parameters))
}
fn parse_spawn_statement(&mut self, position: usize) -> Result<(usize, Statement), ParserError> {
let mut current_position = position + 1;
let (new_position, agent_name) = self.expect_identifier(current_position)?;
current_position = new_position;
let mut agent_type = None;
if let Some(Token::Punctuation(Punctuation::Colon)) = self.tokens.get(current_position) {
current_position += 1; let (new_position, type_name) = self.expect_identifier(current_position)?;
current_position = new_position;
agent_type = Some(type_name);
}
let mut config = None;
if let Some(Token::Punctuation(Punctuation::LeftBrace)) = self.tokens.get(current_position) {
if agent_type.is_some() { let (new_position, config_map) = self.parse_object_literal(current_position)?;
current_position = new_position;
config = Some(config_map);
}
}
let (new_position, body) = self.parse_block_statement(current_position, 0)?;
current_position = new_position;
Ok((current_position, Statement::Spawn(SpawnStatement {
agent_name,
agent_type,
config,
body,
})))
}
fn parse_agent_statement(&mut self, position: usize) -> Result<(usize, Statement), ParserError> {
let mut current_position = position + 1;
let (new_position, name) = self.expect_identifier(current_position)?;
current_position = new_position;
let agent_type = if let Some(Token::Punctuation(Punctuation::Colon)) = self.tokens.get(current_position) {
current_position += 1; let (new_position, type_str) = self.expect_identifier(current_position)?;
current_position = new_position;
match type_str.as_str() {
"ai" => crate::parser::ast::AgentType::AI,
"system" => crate::parser::ast::AgentType::System,
"worker" => crate::parser::ast::AgentType::Worker,
_ => crate::parser::ast::AgentType::Custom(type_str),
}
} else {
let (line, column) = self.get_token_position(current_position);
return Err(ParserError::unexpected_token(&self.tokens[current_position], &[":"], line, column));
};
let (new_position, config) = self.parse_object_literal(current_position)?;
current_position = new_position;
let mut capabilities = Vec::new();
if let Some(Token::Keyword(Keyword::With)) = self.tokens.get(current_position) {
current_position += 1; let (new_position, caps) = self.parse_capabilities_list(current_position)?;
current_position = new_position;
capabilities = caps;
}
let (new_position, body) = self.parse_block_statement(current_position, 0)?;
current_position = new_position;
Ok((current_position, Statement::Agent(AgentStatement {
name,
agent_type,
config,
capabilities,
body,
})))
}
fn parse_object_literal(&mut self, position: usize) -> Result<(usize, HashMap<String, Expression>), ParserError> {
let mut current_position = position;
if let Some(Token::Punctuation(Punctuation::LeftBrace)) = self.tokens.get(current_position) {
current_position += 1;
} else {
return Err(ParserError::unexpected_token(&self.tokens[current_position], &["{"], current_position, 0));
}
let mut properties = HashMap::new();
loop {
let token = self.tokens.get(current_position).cloned();
match token {
Some(Token::Punctuation(Punctuation::RightBrace)) => {
current_position += 1;
break;
}
Some(Token::Identifier(key)) => {
current_position += 1;
if let Some(Token::Punctuation(Punctuation::Colon)) = self.tokens.get(current_position) {
current_position += 1; } else if let Some(Token::Identifier(id)) = self.tokens.get(current_position) {
if id == "this" {
} else {
let (line, column) = self.get_token_position(current_position);
return Err(ParserError::unexpected_token(&self.tokens[current_position], &[":"], line, column));
}
} else {
let (line, column) = self.get_token_position(current_position);
return Err(ParserError::unexpected_token(&self.tokens[current_position], &[":"], line, column));
}
let (new_position, value) = self.parse_expression(current_position)?;
current_position = new_position;
properties.insert(key, value);
if let Some(Token::Punctuation(Punctuation::Comma)) = self.tokens.get(current_position) {
current_position += 1; }
}
Some(Token::Literal(Literal::String(key))) => {
current_position += 1;
if let Some(Token::Punctuation(Punctuation::Colon)) = self.tokens.get(current_position) {
current_position += 1; } else if let Some(Token::Identifier(id)) = self.tokens.get(current_position) {
if id == "this" {
} else {
let (line, column) = self.get_token_position(current_position);
return Err(ParserError::unexpected_token(&self.tokens[current_position], &[":"], line, column));
}
} else {
let (line, column) = self.get_token_position(current_position);
return Err(ParserError::unexpected_token(&self.tokens[current_position], &[":"], line, column));
}
let (new_position, value) = self.parse_expression(current_position)?;
current_position = new_position;
properties.insert(key, value);
if let Some(Token::Punctuation(Punctuation::Comma)) = self.tokens.get(current_position) {
current_position += 1; }
}
Some(_) => {
let (line, column) = self.get_token_position(current_position);
return Err(ParserError::unexpected_token(&self.tokens[current_position], &["property key", "}"], line, column));
}
None => break,
}
}
Ok((current_position, properties))
}
fn parse_array_literal(&mut self, position: usize) -> Result<(usize, Vec<Expression>), ParserError> {
let mut current_position = position;
if let Some(Token::Punctuation(Punctuation::LeftBracket)) = self.tokens.get(current_position) {
current_position += 1;
} else {
let (line, column) = self.get_token_position(position);
return Err(ParserError::unexpected_token(
&self.tokens[position],
&["["],
line,
column,
));
}
let mut elements = Vec::new();
while let Some(token) = self.tokens.get(current_position) {
match token {
Token::Punctuation(Punctuation::RightBracket) => {
current_position += 1;
break;
}
_ => {
let (new_position, expr) = self.parse_expression(current_position)?;
current_position = new_position;
elements.push(expr);
if let Some(Token::Punctuation(Punctuation::Comma)) = self.tokens.get(current_position) {
current_position += 1; } else if let Some(Token::Punctuation(Punctuation::RightBracket)) = self.tokens.get(current_position) {
continue;
} else {
let (line, column) = self.get_token_position(current_position);
return Err(ParserError::unexpected_token(
&self.tokens[current_position],
&[",", "]"],
line,
column,
));
}
}
}
}
Ok((current_position, elements))
}
fn parse_capabilities_list(&self, position: usize) -> Result<(usize, Vec<String>), ParserError> {
let mut current_position = position;
let mut capabilities = Vec::new();
if let Some(Token::Punctuation(Punctuation::LeftBracket)) = self.tokens.get(current_position) {
current_position += 1;
} else {
return Err(ParserError::unexpected_token(&self.tokens[current_position], &["["], current_position, 0));
}
while let Some(token) = self.tokens.get(current_position) {
match token {
Token::Punctuation(Punctuation::RightBracket) => {
current_position += 1;
break;
}
Token::Literal(Literal::String(capability)) => {
current_position += 1; capabilities.push(capability.clone());
if let Some(Token::Punctuation(Punctuation::Comma)) = self.tokens.get(current_position) {
current_position += 1; }
}
_ => {
return Err(ParserError::unexpected_token(&self.tokens[current_position], &["string literal", "]"], current_position, 0));
}
}
}
Ok((current_position, capabilities))
}
fn parse_message_statement(&mut self, position: usize) -> Result<(usize, Statement), ParserError> {
let mut current_position = position + 1;
let (new_position, recipient) = self.expect_identifier(current_position)?;
current_position = new_position;
let (new_position, _) = self.expect_token(current_position, &Token::Keyword(Keyword::With))?;
current_position = new_position;
let (new_position, data) = self.parse_message_data(current_position)?;
current_position = new_position;
Ok((current_position, Statement::Message(MessageStatement {
recipient,
data,
})))
}
fn parse_event_statement(&mut self, position: usize) -> Result<(usize, Statement), ParserError> {
let mut current_position = position + 1;
let (new_position, event_name) = self.expect_identifier(current_position)?;
current_position = new_position;
let (new_position, data) = self.parse_message_data(current_position)?;
current_position = new_position;
Ok((current_position, Statement::Event(EventStatement {
event_name,
data,
})))
}
fn parse_message_data(&mut self, position: usize) -> Result<(usize, HashMap<String, Expression>), ParserError> {
let mut current_position = position;
let mut data = HashMap::new();
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::LeftBrace))?;
current_position = new_position;
if let Some(Token::Punctuation(Punctuation::RightBrace)) = self.tokens.get(current_position) {
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::RightBrace))?;
return Ok((new_position, data));
}
loop {
let (new_position, key) = self.expect_identifier(current_position)?;
current_position = new_position;
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::Colon))?;
current_position = new_position;
let (new_position, value) = self.parse_expression(current_position)?;
current_position = new_position;
data.insert(key, value);
if let Some(Token::Punctuation(Punctuation::Comma)) = self.tokens.get(current_position) {
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::Comma))?;
current_position = new_position;
} else {
break;
}
}
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::RightBrace))?;
Ok((new_position, data))
}
fn parse_if_statement(&mut self, position: usize) -> Result<(usize, Statement), ParserError> {
let mut current_position = position + 1;
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::LeftParen))?;
current_position = new_position;
let (new_position, condition) = self.parse_expression(current_position)?;
current_position = new_position;
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::RightParen))?;
current_position = new_position;
let (new_position, consequence) = self.parse_block_statement(current_position, 0)?;
current_position = new_position;
let alternative = if let Some(Token::Keyword(Keyword::Else)) = self.tokens.get(current_position) {
let (new_pos, _) = self.expect_token(current_position, &Token::Keyword(Keyword::Else))?;
current_position = new_pos;
let else_block = if let (Some(Token::Keyword(Keyword::If)), Some(Token::Punctuation(Punctuation::LeftParen))) =
(self.tokens.get(current_position), self.tokens.get(current_position + 1))
{
let (new_pos, if_stmt) = self.parse_if_statement(current_position)?;
current_position = new_pos;
BlockStatement {
statements: vec![if_stmt],
}
} else {
let (new_pos, block) = self.parse_block_statement(current_position, 0)?;
current_position = new_pos;
block
};
Some(else_block)
} else {
None
};
Ok((current_position, Statement::If(IfStatement {
condition,
consequence,
alternative,
})))
}
fn parse_while_statement(&mut self, position: usize) -> Result<(usize, Statement), ParserError> {
let mut current_position = position + 1;
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::LeftParen))?;
current_position = new_position;
let (new_position, condition) = self.parse_expression(current_position)?;
current_position = new_position;
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::RightParen))?;
current_position = new_position;
let (new_position, body) = self.parse_block_statement(current_position, 0)?;
current_position = new_position;
Ok((current_position, Statement::While(WhileStatement {
condition,
body,
})))
}
fn parse_function_arguments(&mut self, position: usize, depth: usize) -> Result<(usize, Vec<Expression>), ParserError> {
let mut current_position = position;
let mut arguments = Vec::new();
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::LeftParen))?;
current_position = new_position;
if let Some(Token::Punctuation(Punctuation::RightParen)) = self.tokens.get(current_position) {
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::RightParen))?;
return Ok((new_position, arguments));
}
loop {
let (new_position, argument) = self.parse_expression_with_depth(current_position, depth + 1)?;
current_position = new_position;
arguments.push(argument);
let param_name = arguments.last().and_then(|a| {
if let Expression::Identifier(p) = a { Some(p.clone()) } else { None }
});
if let Some(param) = param_name {
if let Some(Token::Punctuation(Punctuation::FatArrow)) = self.tokens.get(current_position) {
let (pos2, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::FatArrow))?;
let (pos3, body) = self.parse_block_statement(pos2, depth)?;
arguments.pop();
arguments.push(Expression::ArrowFunction {
param,
body,
});
current_position = pos3;
let (new_pos, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::RightParen))?;
return Ok((new_pos, arguments));
}
}
if let Some(Token::Punctuation(Punctuation::Comma)) = self.tokens.get(current_position) {
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::Comma))?;
current_position = new_position;
} else {
break;
}
}
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::RightParen))?;
Ok((new_position, arguments))
}
fn parse_attribute(&mut self, position: usize) -> Result<(usize, Attribute), ParserError> {
let mut current_position = position + 1;
let name = if let Some(Token::Identifier(name)) = self.tokens.get(current_position) {
let (new_position, _) = self.expect_identifier(current_position)?;
current_position = new_position;
name.clone()
} else if let Some(Token::Keyword(keyword)) = self.tokens.get(current_position) {
let (new_position, _) = self.expect_token(current_position, &Token::Keyword(keyword.clone()))?;
current_position = new_position;
match keyword {
Keyword::Txn => "txn".to_string(),
Keyword::Secure => "secure".to_string(),
Keyword::Limit => "limit".to_string(),
Keyword::Trust => "trust".to_string(),
Keyword::Chain => "chain".to_string(),
_ => format!("{:?}", keyword).to_lowercase(),
}
} else {
let (line, column) = self.get_token_position(current_position);
return Err(ParserError::unexpected_token(
self.tokens.get(current_position).unwrap_or(&Token::EOF),
&["identifier", "keyword"],
line,
column
));
};
let mut parameters = Vec::new();
if let Some(Token::Punctuation(Punctuation::LeftParen)) = self.tokens.get(current_position) {
let (new_pos, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::LeftParen))?;
current_position = new_pos;
if let Some(Token::Punctuation(Punctuation::RightParen)) = self.tokens.get(current_position) {
let (new_pos, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::RightParen))?;
return Ok((new_pos, Attribute {
name,
parameters,
target: AttributeTarget::Function, }));
}
loop {
let (new_pos, param) = self.parse_expression(current_position)?; current_position = new_pos;
parameters.push(param);
if let Some(Token::Punctuation(Punctuation::Comma)) = self.tokens.get(current_position) {
let (new_pos, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::Comma))?;
current_position = new_pos;
} else {
break;
}
}
let (new_pos, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::RightParen))?;
current_position = new_pos;
}
let target = AttributeTarget::Function;
Ok((current_position, Attribute {
name,
parameters,
target,
}))
}
fn parse_try_statement(&mut self, position: usize) -> Result<(usize, Statement), ParserError> {
let mut current_position = position + 1;
let (new_position, try_block) = self.parse_block_statement(current_position, 0)?;
current_position = new_position;
let mut catch_blocks = Vec::new();
let mut finally_block = None;
while let Some(Token::Keyword(Keyword::Catch)) = self.tokens.get(current_position) {
let (new_position, catch_block) = self.parse_catch_block(current_position)?;
current_position = new_position;
catch_blocks.push(catch_block);
}
if let Some(Token::Keyword(Keyword::Finally)) = self.tokens.get(current_position) {
let (new_position, finally) = self.parse_finally_block(current_position)?;
current_position = new_position;
finally_block = Some(finally);
}
Ok((current_position, Statement::Try(TryStatement {
try_block,
catch_blocks,
finally_block,
})))
}
fn parse_catch_block(&mut self, position: usize) -> Result<(usize, CatchBlock), ParserError> {
let mut current_position = position + 1;
let mut error_type = None;
let mut error_variable = None;
if let Some(Token::Punctuation(Punctuation::LeftParen)) = self.tokens.get(current_position) {
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::LeftParen))?;
current_position = new_position;
if let Some(Token::Identifier(type_name)) = self.tokens.get(current_position) {
let (new_position, _) = self.expect_identifier(current_position)?;
current_position = new_position;
error_type = Some(type_name.clone());
if let Some(Token::Identifier(var_name)) = self.tokens.get(current_position) {
let (new_position, _) = self.expect_identifier(current_position)?;
current_position = new_position;
error_variable = Some(var_name.clone());
}
}
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::RightParen))?;
current_position = new_position;
}
let (new_position, body) = self.parse_block_statement(current_position, 0)?;
current_position = new_position;
Ok((current_position, CatchBlock {
error_type,
error_variable,
body,
}))
}
fn parse_finally_block(&mut self, position: usize) -> Result<(usize, BlockStatement), ParserError> {
let mut current_position = position + 1;
let (new_position, body) = self.parse_block_statement(current_position, 0)?;
current_position = new_position;
Ok((current_position, body))
}
fn parse_for_in_statement(&mut self, position: usize) -> Result<(usize, Statement), ParserError> {
let mut current_position = position + 1; let (new_position, variable) = self.expect_identifier_or_keyword(current_position)?;
current_position = new_position;
let (new_position, _) = self.expect_token(current_position, &Token::Keyword(Keyword::In))?;
current_position = new_position;
let (new_position, iterable) = self.parse_expression(current_position)?;
current_position = new_position;
let (new_position, body) = self.parse_block_statement(current_position, 0)?;
current_position = new_position;
Ok((current_position, Statement::ForIn(ForInStatement {
variable,
iterable,
body,
})))
}
fn parse_service_statement_with_attributes(&mut self, position: usize, pre_parsed_attributes: Vec<Attribute>) -> Result<(usize, Statement), ParserError> {
let (new_position, _) = self.expect_token(position, &Token::Keyword(Keyword::Service))?;
let mut current_position = new_position;
let (new_position, name) = self.expect_identifier(current_position)?;
current_position = new_position;
let mut attributes = pre_parsed_attributes;
let mut compilation_target = None;
while let Some(Token::Punctuation(Punctuation::At)) = self.tokens.get(current_position) {
if let Some(Token::Keyword(Keyword::CompileTarget)) = self.tokens.get(current_position + 1) {
let (new_position, target_info) = self.parse_compile_target_attribute(current_position)?;
compilation_target = Some(target_info);
current_position = new_position;
} else {
let (new_position, attr) = self.parse_attribute(current_position)?;
attributes.push(attr);
current_position = new_position;
}
}
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::LeftBrace))?;
current_position = new_position;
let mut fields = Vec::new();
let mut methods = Vec::new();
let mut events = Vec::new();
while current_position < self.tokens.len() {
match self.tokens.get(current_position) {
Some(Token::Keyword(Keyword::Fn)) => {
let (new_position, method) = self.parse_function_statement(current_position)?;
if let Statement::Function(func) = method {
methods.push(func);
}
current_position = new_position;
}
Some(Token::Keyword(Keyword::Event)) => {
let (new_position, event) = self.parse_event_declaration(current_position)?;
events.push(event);
current_position = new_position;
}
Some(Token::Punctuation(Punctuation::RightBrace)) => {
current_position += 1;
break;
}
_ => {
let (new_position, field) = self.parse_service_field(current_position)?;
fields.push(field);
current_position = new_position;
}
}
}
for attr in &mut attributes {
attr.target = AttributeTarget::Module;
}
let service_stmt = ServiceStatement {
name,
attributes,
fields,
methods,
events,
compilation_target,
};
if let Some(_) = &service_stmt.compilation_target {
self.validate_target_constraints(&service_stmt)?;
}
Ok((current_position, Statement::Service(service_stmt)))
}
fn parse_service_statement(&mut self, position: usize) -> Result<(usize, Statement), ParserError> {
let (new_position, _) = self.expect_token(position, &Token::Keyword(Keyword::Service))?;
let mut current_position = new_position;
let (new_position, name) = self.expect_identifier(current_position)?;
current_position = new_position;
let mut attributes = Vec::new();
let mut compilation_target = None;
while let Some(Token::Punctuation(Punctuation::At)) = self.tokens.get(current_position) {
if let Some(Token::Keyword(Keyword::CompileTarget)) = self.tokens.get(current_position + 1) {
let (new_position, target_info) = self.parse_compile_target_attribute(current_position)?;
compilation_target = Some(target_info);
current_position = new_position;
} else {
let (new_position, attr) = self.parse_attribute(current_position)?;
attributes.push(attr);
current_position = new_position;
}
}
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::LeftBrace))?;
current_position = new_position;
let mut fields = Vec::new();
let mut methods = Vec::new();
let mut events = Vec::new();
while current_position < self.tokens.len() {
match self.tokens.get(current_position) {
Some(Token::Keyword(Keyword::Fn)) => {
let (new_position, method) = self.parse_function_statement(current_position)?;
if let Statement::Function(func) = method {
methods.push(func);
}
current_position = new_position;
}
Some(Token::Keyword(Keyword::Event)) => {
let (new_position, event) = self.parse_event_declaration(current_position)?;
events.push(event);
current_position = new_position;
}
Some(Token::Punctuation(Punctuation::RightBrace)) => {
current_position += 1;
break;
}
_ => {
let (new_position, field) = self.parse_service_field(current_position)?;
fields.push(field);
current_position = new_position;
}
}
}
for attr in &mut attributes {
attr.target = AttributeTarget::Module;
}
let service_stmt = ServiceStatement {
name,
attributes,
fields,
methods,
events,
compilation_target,
};
if let Some(_) = &service_stmt.compilation_target {
self.validate_target_constraints(&service_stmt)?;
}
Ok((current_position, Statement::Service(service_stmt)))
}
fn parse_service_field(&mut self, position: usize) -> Result<(usize, ServiceField), ParserError> {
let mut current_position = position;
let mut visibility = FieldVisibility::Public;
if let Some(Token::Punctuation(Punctuation::At)) = self.tokens.get(current_position) {
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::At))?;
current_position = new_position;
let (new_position, vis_name) = self.expect_identifier_or_keyword(current_position)?;
current_position = new_position;
let vis_name = vis_name.to_lowercase();
visibility = match vis_name.as_str() {
"public" => FieldVisibility::Public,
"private" => FieldVisibility::Private,
"internal" => FieldVisibility::Internal,
_ => {
let (line, col) = self.get_token_position(current_position.saturating_sub(1));
return Err(ParserError::unexpected_token(
self.tokens.get(current_position.saturating_sub(1)).unwrap_or(&Token::EOF),
&["@public", "@private", "@internal"],
line, col
));
}
};
} else if let Some(Token::Keyword(Keyword::Private)) = self.tokens.get(current_position) {
let (new_position, _) = self.expect_token(current_position, &Token::Keyword(Keyword::Private))?;
current_position = new_position;
visibility = FieldVisibility::Private;
}
let (new_position, name) = self.expect_identifier(current_position)?;
current_position = new_position;
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::Colon))?;
current_position = new_position;
let (new_position, field_type) = self.parse_type_expression(current_position)?;
current_position = new_position;
let initial_value = if let Some(Token::Operator(Operator::Assign)) = self.tokens.get(current_position) {
let (new_position, _) = self.expect_token(current_position, &Token::Operator(Operator::Assign))?;
current_position = new_position;
let (new_position, value) = self.parse_expression(current_position)?;
current_position = new_position;
Some(value)
} else {
None
};
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::Semicolon))?;
current_position = new_position;
let field = ServiceField {
name,
field_type,
initial_value,
visibility,
};
Ok((current_position, field))
}
fn parse_type_expression(&self, position: usize) -> Result<(usize, String), ParserError> {
let mut current_position = position;
let base_type = if let Some(Token::Identifier(name)) = self.tokens.get(current_position) {
let (new_position, _) = self.expect_identifier(current_position)?;
current_position = new_position;
name.clone()
} else if let Some(Token::Keyword(keyword)) = self.tokens.get(current_position) {
let (new_position, _) = self.expect_token(current_position, &Token::Keyword(keyword.clone()))?;
current_position = new_position;
match keyword {
Keyword::List => "list".to_string(),
Keyword::Map => "map".to_string(),
Keyword::Set => "set".to_string(),
Keyword::Option => "option".to_string(),
Keyword::Result => "result".to_string(),
_ => format!("{:?}", keyword).to_lowercase(),
}
} else {
let (line, column) = self.get_token_position(current_position);
return Err(ParserError::unexpected_token(
self.tokens.get(current_position).unwrap_or(&Token::EOF),
&["identifier", "keyword"],
line,
column
));
};
if let Some(Token::Operator(Operator::Less)) = self.tokens.get(current_position) {
let (new_pos, _) = self.expect_token(current_position, &Token::Operator(Operator::Less))?;
current_position = new_pos;
let mut type_params = Vec::new();
loop {
let (new_pos, param_type) = self.parse_type_expression(current_position)?;
current_position = new_pos;
type_params.push(param_type);
if let Some(Token::Punctuation(Punctuation::Comma)) = self.tokens.get(current_position) {
let (new_pos, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::Comma))?;
current_position = new_pos;
} else if let Some(Token::Operator(Operator::Greater)) = self.tokens.get(current_position) {
let (new_pos, _) = self.expect_token(current_position, &Token::Operator(Operator::Greater))?;
current_position = new_pos;
break;
} else {
return Err(ParserError::unexpected_token(
self.tokens.get(current_position).unwrap_or(&Token::EOF),
&[",", ">"],
1,
1
));
}
}
let type_str = format!("{}<{}>", base_type, type_params.join(", "));
Ok((current_position, type_str))
} else {
Ok((current_position, base_type))
}
}
fn parse_event_declaration(&self, position: usize) -> Result<(usize, EventDeclaration), ParserError> {
let mut current_position = position + 1;
let (new_position, name) = self.expect_identifier(current_position)?;
current_position = new_position;
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::LeftParen))?;
current_position = new_position;
let mut parameters = Vec::new();
while current_position < self.tokens.len() {
if let Some(Token::Punctuation(Punctuation::RightParen)) = self.tokens.get(current_position) {
current_position += 1;
break;
}
let (new_position, param_name) = self.expect_identifier(current_position)?;
current_position = new_position;
let param_type = if let Some(Token::Punctuation(Punctuation::Colon)) = self.tokens.get(current_position) {
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::Colon))?;
current_position = new_position;
let (new_position, type_name) = self.parse_type_expression(current_position)?;
current_position = new_position;
Some(type_name)
} else {
None
};
parameters.push(Parameter {
name: param_name,
param_type,
});
if let Some(Token::Punctuation(Punctuation::Comma)) = self.tokens.get(current_position) {
current_position += 1;
}
}
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::Semicolon))?;
current_position = new_position;
Ok((current_position, EventDeclaration { name, parameters }))
}
fn parse_compile_target_attribute(&mut self, position: usize) -> Result<(usize, CompilationTargetInfo), ParserError> {
let mut current_position = position + 1;
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::LeftParen))?;
current_position = new_position;
let target_name = if let Some(Token::Literal(Literal::String(name))) = self.tokens.get(current_position) {
let (new_position, _) = self.expect_token(current_position, &Token::Literal(Literal::String(name.clone())))?;
current_position = new_position;
name.clone()
} else {
return Err(ParserError::unexpected_token(
self.tokens.get(current_position).unwrap_or(&Token::EOF),
&["string literal"],
1,
1
));
};
let (new_position, _) = self.expect_token(current_position, &Token::Punctuation(Punctuation::RightParen))?;
current_position = new_position;
let target = crate::lexer::tokens::CompilationTarget::from_string(&target_name)
.ok_or_else(|| ParserError::unexpected_token(
self.tokens.get(position).unwrap_or(&Token::EOF),
&["valid compilation target"],
1,
1
))?;
let constraints = crate::lexer::tokens::get_target_constraints()
.get(&target)
.cloned()
.unwrap_or_else(|| crate::lexer::tokens::TargetConstraint::new(target.clone()));
let target_info = CompilationTargetInfo {
target,
constraints,
validation_errors: Vec::new(),
};
Ok((current_position, target_info))
}
fn collect_namespaces_from_expression(&self, expr: &Expression) -> HashSet<String> {
let mut out = HashSet::new();
match expr {
Expression::FunctionCall(call) => {
if let Some(ns) = call.name.split("::").next() {
if call.name.contains("::") && !ns.is_empty() {
out.insert(ns.to_string());
}
}
for arg in &call.arguments {
out.extend(self.collect_namespaces_from_expression(arg));
}
}
Expression::BinaryOp(l, _, r) => {
out.extend(self.collect_namespaces_from_expression(l));
out.extend(self.collect_namespaces_from_expression(r));
}
Expression::UnaryOp(_, e) => {
out.extend(self.collect_namespaces_from_expression(e));
}
Expression::Assignment(_, v) => {
out.extend(self.collect_namespaces_from_expression(v));
}
Expression::FieldAccess(obj, _) => {
out.extend(self.collect_namespaces_from_expression(obj));
}
Expression::FieldAssignment(obj, _, v) => {
out.extend(self.collect_namespaces_from_expression(obj));
out.extend(self.collect_namespaces_from_expression(v));
}
Expression::Await(e) | Expression::Spawn(e) | Expression::Throw(e) => {
out.extend(self.collect_namespaces_from_expression(e));
}
Expression::IndexAccess(c, i) => {
out.extend(self.collect_namespaces_from_expression(c));
out.extend(self.collect_namespaces_from_expression(i));
}
Expression::ObjectLiteral(props) => {
for (_, e) in props {
out.extend(self.collect_namespaces_from_expression(e));
}
}
Expression::ArrayLiteral(elems) => {
for e in elems {
out.extend(self.collect_namespaces_from_expression(e));
}
}
Expression::ArrowFunction { body, .. } => {
out.extend(self.collect_namespaces_from_block(&body));
}
_ => {}
}
out
}
fn collect_namespaces_from_statement(&self, stmt: &Statement) -> HashSet<String> {
let mut out = HashSet::new();
match stmt {
Statement::Expression(expr) => {
out.extend(self.collect_namespaces_from_expression(expr));
}
Statement::Let(let_stmt) => {
out.extend(self.collect_namespaces_from_expression(&let_stmt.value));
}
Statement::Return(ret) => {
if let Some(ref e) = ret.value {
out.extend(self.collect_namespaces_from_expression(e));
}
}
Statement::Block(block) => {
out.extend(self.collect_namespaces_from_block(block));
}
Statement::If(if_stmt) => {
out.extend(self.collect_namespaces_from_expression(&if_stmt.condition));
out.extend(self.collect_namespaces_from_block(&if_stmt.consequence));
if let Some(ref alt) = if_stmt.alternative {
out.extend(self.collect_namespaces_from_block(alt));
}
}
Statement::While(while_stmt) => {
out.extend(self.collect_namespaces_from_expression(&while_stmt.condition));
out.extend(self.collect_namespaces_from_block(&while_stmt.body));
}
Statement::Try(try_stmt) => {
out.extend(self.collect_namespaces_from_block(&try_stmt.try_block));
for cb in &try_stmt.catch_blocks {
out.extend(self.collect_namespaces_from_block(&cb.body));
}
if let Some(ref fb) = try_stmt.finally_block {
out.extend(self.collect_namespaces_from_block(fb));
}
}
Statement::ForIn(for_stmt) => {
out.extend(self.collect_namespaces_from_expression(&for_stmt.iterable));
out.extend(self.collect_namespaces_from_block(&for_stmt.body));
}
Statement::Function(func) => {
out.extend(self.collect_namespaces_from_block(&func.body));
}
Statement::Spawn(spawn) => {
out.extend(self.collect_namespaces_from_block(&spawn.body));
}
Statement::Agent(agent) => {
out.extend(self.collect_namespaces_from_block(&agent.body));
}
Statement::Message(msg) => {
for (_, e) in &msg.data {
out.extend(self.collect_namespaces_from_expression(e));
}
}
Statement::Event(ev) => {
for (_, e) in &ev.data {
out.extend(self.collect_namespaces_from_expression(e));
}
}
Statement::Service(service) => {
for method in &service.methods {
out.extend(self.collect_namespaces_from_block(&method.body));
}
}
}
out
}
fn collect_namespaces_from_block(&self, block: &BlockStatement) -> HashSet<String> {
let mut out = HashSet::new();
for stmt in &block.statements {
out.extend(self.collect_namespaces_from_statement(stmt));
}
out
}
fn validate_target_constraints(&self, service: &ServiceStatement) -> Result<(), ParserError> {
if let Some(ref target_info) = service.compilation_target {
let constraint = &target_info.constraints;
let mut found_required_attrs = Vec::new();
for attr in &service.attributes {
if constraint.required_attributes.contains(&attr.name) {
found_required_attrs.push(attr.name.clone());
}
}
if found_required_attrs.len() < constraint.required_attributes.len() {
let missing: Vec<String> = constraint.required_attributes
.iter()
.filter(|attr| !found_required_attrs.contains(attr))
.cloned()
.collect();
return Err(ParserError::unexpected_token(
self.tokens.get(0).unwrap_or(&Token::EOF),
&[&format!("Missing required attributes: {:?}", missing)],
1,
1
));
}
let forbidden_namespaces: HashSet<String> = constraint
.forbidden_operations
.iter()
.filter_map(|op| op.split("::").next().map(|s| s.to_string()))
.collect();
for method in &service.methods {
let used_namespaces = self.collect_namespaces_from_block(&method.body);
let violating: Vec<String> = used_namespaces
.intersection(&forbidden_namespaces)
.cloned()
.collect();
if !violating.is_empty() {
return Err(ParserError::unexpected_token(
self.tokens.get(0).unwrap_or(&Token::EOF),
&[&format!(
"Method '{}' uses forbidden namespace(s) for target {:?}: {:?}",
method.name,
target_info.target,
violating
)],
1,
1
));
}
}
}
Ok(())
}
fn expect_token(&self, position: usize, expected: &Token) -> Result<(usize, &Token), ParserError> {
if let Some(token) = self.tokens.get(position) {
if token == expected {
Ok((position + 1, token))
} else {
Err(self.error_unexpected_token(position, &[&format!("{:?}", expected)]))
}
} else {
Err(ParserError::unexpected_eof(&format!("{:?}", expected)))
}
}
fn expect_identifier(&self, position: usize) -> Result<(usize, String), ParserError> {
if let Some(Token::Identifier(name)) = self.tokens.get(position) {
Ok((position + 1, name.clone()))
} else {
Err(self.error_unexpected_token(position, &["identifier"]))
}
}
fn expect_identifier_or_keyword(&self, position: usize) -> Result<(usize, String), ParserError> {
if let Some(Token::Identifier(name)) = self.tokens.get(position) {
Ok((position + 1, name.clone()))
} else if let Some(Token::Keyword(keyword)) = self.tokens.get(position) {
let name = match keyword {
Keyword::Service => "service".to_string(),
Keyword::Ai => "ai".to_string(),
Keyword::Chain => "chain".to_string(),
Keyword::Mobile => "mobile".to_string(),
Keyword::Desktop => "desktop".to_string(),
Keyword::Iot => "iot".to_string(),
Keyword::Persistent => "persistent".to_string(),
Keyword::Cached => "cached".to_string(),
Keyword::Versioned => "versioned".to_string(),
Keyword::Deprecated => "deprecated".to_string(),
Keyword::CompileTarget => "compile_target".to_string(),
Keyword::Interface => "interface".to_string(),
Keyword::Txn => "txn".to_string(),
Keyword::Secure => "secure".to_string(),
Keyword::Limit => "limit".to_string(),
Keyword::Trust => "trust".to_string(),
Keyword::Import => "import".to_string(),
Keyword::Export => "export".to_string(),
Keyword::As => "as".to_string(),
Keyword::Private => "private".to_string(),
Keyword::Audit => "audit".to_string(),
Keyword::With => "with".to_string(),
Keyword::Finally => "finally".to_string(),
Keyword::Await => "await".to_string(),
Keyword::Async => "async".to_string(),
Keyword::Result => "Result".to_string(),
Keyword::Option => "Option".to_string(),
Keyword::Some => "Some".to_string(),
Keyword::None => "None".to_string(),
Keyword::Ok => "Ok".to_string(),
Keyword::Err => "Err".to_string(),
Keyword::List => "List".to_string(),
Keyword::Map => "Map".to_string(),
Keyword::Set => "Set".to_string(),
Keyword::Generic => "Generic".to_string(),
Keyword::Box => "Box".to_string(),
Keyword::Ref => "ref".to_string(),
Keyword::Mut => "mut".to_string(),
Keyword::Const => "const".to_string(),
Keyword::Static => "static".to_string(),
Keyword::Extern => "extern".to_string(),
Keyword::Crate => "crate".to_string(),
Keyword::Super => "super".to_string(),
Keyword::Self_ => "self".to_string(),
Keyword::SelfType => "Self".to_string(),
_ => format!("{:?}", keyword).to_lowercase(),
};
Ok((position + 1, name))
} else {
let (line, column) = self.get_token_position(position);
Err(ParserError::unexpected_token(
self.tokens.get(position).unwrap_or(&Token::EOF),
&["identifier", "keyword"],
line,
column
))
}
}
}