use crate::ast::*; use crate::lexer::Token; use std::iter::Peekable; use std::ops::Range; use std::vec::IntoIter; type TokenIter = Peekable)>>; pub struct Parser { pub file: String, pub tokens: TokenIter, } #[derive(Debug)] pub struct ParseError { pub message: String, pub span: Span, } impl Parser { pub fn new(file: String, tokens: Vec<(Token, Range)>) -> Self { Parser { file, tokens: tokens.into_iter().peekable(), } } // Parse the entire file into a list of AST nodes pub fn parse(&mut self) -> Result, ParseError> { let mut nodes = Vec::new(); while self.peek().is_some() { nodes.push(self.parse_top_level()?); } Ok(nodes) } fn peek(&mut self) -> Option<&Token> { self.tokens.peek().map(|(token, _)| token) } fn peek_span(&mut self) -> Option> { self.tokens.peek().map(|(_, span)| span.clone()) } fn next(&mut self) -> Option<(Token, Range)> { self.tokens.next() } fn expect(&mut self, expected: Token) -> Result, ParseError> { match self.next() { Some((token, span)) if std::mem::discriminant(&token) == std::mem::discriminant(&expected) => { Ok(span) } Some((token, span)) => Err(ParseError { message: format!("Expected {:?}, found {:?}", expected, token), span: Span::new(&span, self.file.clone()), }), None => Err(ParseError { message: format!("Expected {:?}, found EOF", expected), span: Span::new(&(0..0), self.file.clone()), }), } } fn error(&self, msg: String, span: Range) -> Result { Err(ParseError { message: msg, span: Span::new(&span, self.file.clone()), }) } fn parse_top_level(&mut self) -> Result { let mut attributes = Vec::new(); // Parse any leading attributes while matches!(self.peek(), Some(Token::At)) { attributes.push(self.parse_attribute()?); } let start = self.peek_span().unwrap_or(0..0).start; let token = self.peek().cloned(); match token { Some(Token::KeywordUse) => { self.next(); let path = match self.next() { Some((Token::String(s), _)) => s, Some((_, span)) => { return self.error("Expected string after 'use'".to_string(), span); } None => { return self.error("Expected string after 'use'".to_string(), start..start); } }; let end = self.peek_span().unwrap_or(start..start).end; Ok(ASTNode { kind: ASTNodeKind::Use(path), span: Span::new(&(start..end), self.file.clone()), attributes, }) } Some(Token::KeywordFn) => { self.next(); let func = self.parse_function()?; let end = self.peek_span().unwrap_or(start..start).end; Ok(ASTNode { kind: ASTNodeKind::Function(func), span: Span::new(&(start..end), self.file.clone()), attributes, }) } Some(Token::KeywordStruct) => { self.next(); let struct_def = self.parse_struct()?; let end = self.peek_span().unwrap_or(start..start).end; Ok(ASTNode { kind: ASTNodeKind::Struct(struct_def), span: Span::new(&(start..end), self.file.clone()), attributes, }) } Some(Token::KeywordEnum) => { self.next(); let enum_def = self.parse_enum()?; let end = self.peek_span().unwrap_or(start..start).end; Ok(ASTNode { kind: ASTNodeKind::Enum(enum_def), span: Span::new(&(start..end), self.file.clone()), attributes, }) } Some(Token::KeywordImpl) => { self.next(); let impl_def = self.parse_impl()?; let end = self.peek_span().unwrap_or(start..start).end; Ok(ASTNode { kind: ASTNodeKind::Impl(impl_def), span: Span::new(&(start..end), self.file.clone()), attributes, }) } Some(Token::KeywordTrait) => { self.next(); let trait_def = self.parse_trait()?; let end = self.peek_span().unwrap_or(start..start).end; Ok(ASTNode { kind: ASTNodeKind::Trait(trait_def), span: Span::new(&(start..end), self.file.clone()), attributes, }) } Some(Token::KeywordExtern) => { self.next(); let extern_def = self.parse_extern()?; let end = self.peek_span().unwrap_or(start..start).end; Ok(ASTNode { kind: ASTNodeKind::Extern(extern_def), span: Span::new(&(start..end), self.file.clone()), attributes, }) } Some(Token::KeywordLoad) => { self.next(); let load_def = self.parse_load()?; let end = self.peek_span().unwrap_or(start..start).end; Ok(ASTNode { kind: ASTNodeKind::Load(load_def), span: Span::new(&(start..end), self.file.clone()), attributes, }) } Some(token) => { let span = self.peek_span().unwrap_or(start..start); self.error(format!("Unexpected token at top level: {:?}", token), span) } None => self.error("Unexpected EOF".to_string(), start..start), } } fn parse_attribute(&mut self) -> Result { self.expect(Token::At)?; let start = self.peek_span().unwrap_or(0..0).start; let name = match self.next() { Some((Token::Variable(name), _)) => name, Some((_, span)) => return self.error("Expected attribute name".to_string(), span), None => return self.error("Expected attribute name".to_string(), start..start), }; // Parentheses are optional let mut args = vec![]; if matches!(self.peek(), Some(Token::LParen)) { self.next(); loop { let token = self.peek().cloned(); match token { Some(Token::RParen) => { self.next(); break; } Some(Token::String(s)) => { self.next(); args.push(AttributeArg::Literal(s)); } Some(Token::Variable(id)) => { self.next(); let next_token = self.peek().cloned(); if matches!(next_token, Some(Token::Assign)) { self.next(); match self.next() { Some((Token::Variable(val), _)) => { args.push(AttributeArg::KeyValue(id, val)) } Some((_, span)) => { return self.error("Expected value after =".to_string(), span); } None => { return self .error("Expected value after =".to_string(), start..start); } } } else { args.push(AttributeArg::Value(id)); } } Some(token) => { let span = self.peek_span().unwrap_or(start..start); return self .error(format!("Unexpected token in attribute: {:?}", token), span); } None => { return self.error("Expected attribute argument".to_string(), start..start); } } let next_token = self.peek().cloned(); if matches!(next_token, Some(Token::Comma)) { self.next(); } else if matches!(next_token, Some(Token::RParen)) { // ok } else { { let span = self.peek_span().unwrap_or(start..start); return self.error("Expected , or )".to_string(), span); } } } } let end = self.peek_span().unwrap_or(start..start).end; Ok(Attribute { name, args, span: Span::new(&(start..end), self.file.clone()), }) } fn parse_function(&mut self) -> Result { let start = self.peek_span().unwrap_or(0..0).start; let name = match self.next() { Some((Token::Variable(n), _)) => n, Some((_, span)) => return self.error("Expected function name".to_string(), span), None => return self.error("Expected function name".to_string(), start..start), }; // Parse type parameters if present let parameters = if matches!(self.peek(), Some(Token::Less)) { self.next(); self.parse_parameters()? } else { Vec::new() }; // Parse function arguments self.expect(Token::LParen)?; let mut args = Vec::new(); loop { if matches!(self.peek(), Some(Token::RParen)) { self.next(); break; } let arg_name = match self.next() { Some((Token::Variable(n), _)) => n, Some((_, span)) => return self.error("Expected argument name".to_string(), span), None => return self.error("Expected argument name".to_string(), start..start), }; let arg_type = if matches!(self.peek(), Some(Token::Colon)) { self.next(); Some(self.parse_type_annot()?) } else { None }; args.push((arg_name, arg_type)); if matches!(self.peek(), Some(Token::Comma)) { self.next(); } else if !matches!(self.peek(), Some(Token::RParen)) { let span = self.peek_span().unwrap_or(start..start); return self.error("Expected , or )".to_string(), span); } } // Parse return type if present let return_type = if matches!(self.peek(), Some(Token::Arrow)) { self.next(); Some(self.parse_type_annot()?) } else { None }; // Parse body expression let body = self.parse_expr()?; Ok(Function { name, parameters, args, return_type, body, }) } fn parse_struct(&mut self) -> Result { let start = self.peek_span().unwrap_or(0..0).start; let name = match self.next() { Some((Token::Variable(n), _)) => n, Some((_, span)) => return self.error("Expected struct name".to_string(), span), None => return self.error("Expected struct name".to_string(), start..start), }; // Parse type parameters if present let parameters = if matches!(self.peek(), Some(Token::Less)) { self.next(); self.parse_parameters()? } else { Vec::new() }; // Parse fields let mut fields = Vec::new(); loop { if matches!(self.peek(), Some(Token::KeywordEnd)) { self.next(); break; } let field_start = self.peek_span().unwrap_or(0..0).start; let field_name = match self.next() { Some((Token::Variable(n), _)) => n, Some((_, span)) => return self.error("Expected field name".to_string(), span), None => return self.error("Expected field name".to_string(), start..start), }; self.expect(Token::Colon)?; let field_type = self.parse_type_annot()?; let field_end = self.peek_span().unwrap_or(field_start..field_start).start; fields.push(Field { name: field_name, field_type, span: Span::new(&(field_start..field_end), self.file.clone()), }); if matches!(self.peek(), Some(Token::Comma)) { self.next(); } } Ok(Struct { name, parameters, fields, }) } fn parse_enum(&mut self) -> Result { let start = self.peek_span().unwrap_or(0..0).start; let name = match self.next() { Some((Token::Variable(n), _)) => n, Some((_, span)) => return self.error("Expected enum name".to_string(), span), None => return self.error("Expected enum name".to_string(), start..start), }; // Parse type parameters if present let parameters = if matches!(self.peek(), Some(Token::Less)) { self.next(); self.parse_parameters()? } else { Vec::new() }; // Parse variants let mut variants = Vec::new(); loop { if matches!(self.peek(), Some(Token::KeywordEnd)) { self.next(); break; } let variant_start = self.peek_span().unwrap_or(0..0).start; let variant_name = match self.next() { Some((Token::Variable(n), _)) => n, Some((_, span)) => return self.error("Expected variant name".to_string(), span), None => return self.error("Expected variant name".to_string(), start..start), }; let mut fields = Vec::new(); if matches!(self.peek(), Some(Token::LParen)) { self.next(); loop { if matches!(self.peek(), Some(Token::RParen)) { self.next(); break; } fields.push(self.parse_type_annot()?); if matches!(self.peek(), Some(Token::Comma)) { self.next(); } } } let variant_end = self .peek_span() .unwrap_or(variant_start..variant_start) .start; variants.push(Variant { name: variant_name, fields, span: Span::new(&(variant_start..variant_end), self.file.clone()), }); if matches!(self.peek(), Some(Token::Comma)) { self.next(); } } Ok(Enum { name, parameters, variants, }) } fn parse_impl(&mut self) -> Result { let start = self.peek_span().unwrap_or(0..0).start; // Parse impl target as a type (could be generic like Option) let target_type = self.parse_type_annot()?; // Extract the base type name from the type annotation let target = match target_type { TypeAnnot::Var(name) => name, TypeAnnot::Cons(name, _) => name, _ => { return self.error( "Expected type name for impl target".to_string(), start..start, ); } }; // Parse optional trait name let trait_name = if matches!(self.peek(), Some(Token::Colon)) { self.next(); match self.next() { Some((Token::Variable(n), _)) => Some(n), Some((_, span)) => return self.error("Expected trait name".to_string(), span), None => return self.error("Expected trait name".to_string(), start..start), } } else { None }; // Parse methods let mut methods = Vec::new(); loop { if matches!(self.peek(), Some(Token::KeywordEnd)) { self.next(); break; } self.expect(Token::KeywordFn)?; methods.push(self.parse_function()?); } Ok(Impl { target, trait_name, methods, }) } fn parse_trait(&mut self) -> Result { let start = self.peek_span().unwrap_or(0..0).start; let name = match self.next() { Some((Token::Variable(n), _)) => n, Some((_, span)) => return self.error("Expected trait name".to_string(), span), None => return self.error("Expected trait name".to_string(), start..start), }; // Parse type parameters if present let parameters = if matches!(self.peek(), Some(Token::Less)) { self.next(); self.parse_parameters()? } else { Vec::new() }; // Parse methods let mut methods = Vec::new(); loop { if matches!(self.peek(), Some(Token::KeywordEnd)) { self.next(); break; } if matches!(self.peek(), Some(Token::KeywordFn)) { self.next(); methods.push(self.parse_function_signature()?); // Optional comma between methods if matches!(self.peek(), Some(Token::Comma)) { self.next(); } } else { break; } } Ok(Trait { name, methods, parameters, associated_types: Vec::new(), }) } fn parse_extern(&mut self) -> Result { let start = self.peek_span().unwrap_or(0..0).start; let name = match self.next() { Some((Token::Variable(n), _)) => n, Some((_, span)) => return self.error("Expected extern name".to_string(), span), None => return self.error("Expected extern name".to_string(), start..start), }; // Parse argument types (with optional parameter names) self.expect(Token::LParen)?; let mut args = Vec::new(); loop { if matches!(self.peek(), Some(Token::RParen)) { self.next(); break; } args.push(self.parse_type_annot()?); if matches!(self.peek(), Some(Token::Comma)) { self.next(); } } // Parse return type self.expect(Token::Arrow)?; let return_type = self.parse_type_annot()?; // Parse from clause self.expect(Token::KeywordFrom)?; let from = match self.next() { Some((Token::Variable(n), _)) => n, Some((_, span)) => return self.error("Expected library identifier".to_string(), span), None => return self.error("Expected library identifier".to_string(), start..start), }; let end = self.peek_span().unwrap_or(start..start).end; Ok(Extern { name, args, return_type, from, span: Span::new(&(start..end), self.file.clone()), }) } fn parse_load(&mut self) -> Result { let start = self.peek_span().unwrap_or(0..0).start; let library = match self.next() { Some((Token::String(s), _)) => s, Some((_, span)) => return self.error("Expected library name".to_string(), span), None => return self.error("Expected library name".to_string(), start..start), }; self.expect(Token::KeywordAs)?; let alias = match self.next() { Some((Token::Variable(a), _)) => a, Some((_, span)) => return self.error("Expected alias".to_string(), span), None => return self.error("Expected alias".to_string(), start..start), }; let end = self.peek_span().unwrap_or(start..start).end; Ok(Load { library, alias, span: Span::new(&(start..end), self.file.clone()), }) } fn parse_parameters(&mut self) -> Result, ParseError> { let start = self.peek_span().unwrap_or(0..0).start; let mut params = Vec::new(); loop { if matches!(self.peek(), Some(Token::Greater)) { self.next(); break; } let param_start = self.peek_span().unwrap_or(0..0).start; let param_name = match self.next() { Some((Token::Variable(n), _)) => n, Some((_, span)) => return self.error("Expected parameter name".to_string(), span), None => return self.error("Expected parameter name".to_string(), start..start), }; let bounds = if matches!(self.peek(), Some(Token::Colon)) { self.next(); self.parse_trait_bounds()? } else { Vec::new() }; let kind = if matches!(self.peek(), Some(Token::Colon)) { self.next(); Some(self.parse_kind()?) } else { None }; let param_end = self.peek_span().unwrap_or(param_start..param_start).end; params.push(Parameter { name: param_name, bounds, kind, span: Span::new(&(param_start..param_end), self.file.clone()), }); if matches!(self.peek(), Some(Token::Comma)) { self.next(); } } Ok(params) } fn parse_trait_bounds(&mut self) -> Result, ParseError> { let mut bounds = Vec::new(); loop { match self.next() { Some((Token::Variable(n), _)) => bounds.push(n), Some((_, span)) => return self.error("Expected trait name".to_string(), span), None => return self.error("Expected trait name".to_string(), 0..0), } if !matches!(self.peek(), Some(Token::Plus)) { break; } self.next(); } Ok(bounds) } fn parse_kind(&mut self) -> Result { if matches!(self.peek(), Some(Token::Mul)) { self.next(); Ok(Kind::Star) } else { let k1 = Box::new(self.parse_kind()?); self.expect(Token::Arrow)?; let k2 = Box::new(self.parse_kind()?); Ok(Kind::Arrow(k1, k2)) } } fn parse_type_annot(&mut self) -> Result { let start = self.peek_span().unwrap_or(0..0).start; // Check for function type: fn (args)->ret if matches!(self.peek(), Some(Token::KeywordFn)) { self.next(); self.expect(Token::LParen)?; let mut arg_types = Vec::new(); loop { if matches!(self.peek(), Some(Token::RParen)) { self.next(); break; } arg_types.push(self.parse_type_annot()?); if matches!(self.peek(), Some(Token::Comma)) { self.next(); } } self.expect(Token::Arrow)?; let ret_type = Box::new(self.parse_type_annot()?); return Ok(TypeAnnot::Function(arg_types, ret_type)); } let mut base_type = match self.next() { Some((Token::Variable(n), _)) => TypeAnnot::Cons(n, vec![]), Some((Token::KeywordBool, _)) => TypeAnnot::Cons("bool".to_string(), vec![]), Some((Token::KeywordInt, _)) => TypeAnnot::Cons("int".to_string(), vec![]), Some((Token::KeywordFloat, _)) => TypeAnnot::Cons("float".to_string(), vec![]), Some((Token::KeywordString, _)) => TypeAnnot::Cons("string".to_string(), vec![]), Some((Token::LParen, _)) => { // Check for unit type: () if matches!(self.peek(), Some(Token::RParen)) { self.next(); return Ok(TypeAnnot::Cons("unit".to_string(), vec![])); } let mut types = Vec::new(); loop { if matches!(self.peek(), Some(Token::RParen)) { self.next(); break; } types.push(self.parse_type_annot()?); if matches!(self.peek(), Some(Token::Comma)) { self.next(); } } // Single element in parens is not a tuple, unwrap it if types.len() == 1 { types.pop().unwrap() } else { TypeAnnot::Tuple(types) } } Some((Token::LBracket, _)) => { let inner = self.parse_type_annot()?; self.expect(Token::RBracket)?; TypeAnnot::Array(Box::new(inner)) } Some((Token::Bang, _)) => TypeAnnot::Cons("never".to_string(), vec![]), Some((_, span)) => return self.error("Expected type name".to_string(), span), None => return self.error("Expected type name".to_string(), start..start), }; // Parse type arguments if present if matches!(self.peek(), Some(Token::Less)) { self.next(); let mut args = Vec::new(); loop { if matches!(self.peek(), Some(Token::Greater)) { self.next(); break; } args.push(self.parse_type_annot()?); if matches!(self.peek(), Some(Token::Comma)) { self.next(); } } base_type = match base_type { TypeAnnot::Cons(name, _) => TypeAnnot::Cons(name, args), _ => { return self.error("Expected type name for generic".to_string(), start..start); } }; } // Parse array types while matches!(self.peek(), Some(Token::LBracket)) { self.next(); self.expect(Token::RBracket)?; base_type = TypeAnnot::Array(Box::new(base_type)); } Ok(base_type) } fn parse_function_signature(&mut self) -> Result { let start = self.peek_span().unwrap_or(0..0).start; let name = match self.next() { Some((Token::Variable(n), _)) => n, Some((_, span)) => return self.error("Expected function name".to_string(), span), None => return self.error("Expected function name".to_string(), start..start), }; self.expect(Token::LParen)?; let mut params = Vec::new(); loop { if matches!(self.peek(), Some(Token::RParen)) { self.next(); break; } let param_start = self.peek_span().unwrap_or(0..0).start; let param_name = match self.next() { Some((Token::Variable(n), _)) => n, Some((_, span)) => return self.error("Expected parameter name".to_string(), span), None => return self.error("Expected parameter name".to_string(), start..start), }; // Parameters in trait methods may have type annotations if matches!(self.peek(), Some(Token::Colon)) { self.next(); let _param_type = self.parse_type_annot()?; } let param_end = self.peek_span().unwrap_or(param_start..param_start).end; params.push(Parameter { name: param_name, bounds: Vec::new(), kind: None, span: Span::new(&(param_start..param_end), self.file.clone()), }); if matches!(self.peek(), Some(Token::Comma)) { self.next(); } } self.expect(Token::Arrow)?; let return_type = self.parse_type_annot()?; Ok(FunctionSignature { name, params, return_type, }) } fn parse_expr(&mut self) -> Result { let mut attributes = Vec::new(); // Parse any leading attributes while matches!(self.peek(), Some(Token::At)) { attributes.push(self.parse_attribute()?); } let mut expr = self.parse_assignment()?; expr.attributes = attributes; Ok(expr) } fn parse_range_expr(&mut self) -> Result { let left = self.parse_or_expr()?; if matches!(self.peek(), Some(Token::DotDot)) { let start = left.span.start; self.next(); let right = self.parse_or_expr()?; let end = right.span.end; Ok(Expr { kind: ExprKind::Range(Box::new(left), Box::new(right)), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } else { Ok(left) } } fn parse_assignment(&mut self) -> Result { let left = self.parse_range_expr()?; if matches!(self.peek(), Some(Token::Assign)) { let start = left.span.start; self.next(); let right = self.parse_assignment()?; let end = right.span.end; Ok(Expr { kind: ExprKind::Assign(Box::new(left), Box::new(right)), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } else { Ok(left) } } fn parse_or_expr(&mut self) -> Result { let mut left = self.parse_and_expr()?; loop { if matches!(self.peek(), Some(Token::Or)) { let start = left.span.start; self.next(); let right = self.parse_and_expr()?; let end = right.span.end; left = Expr { kind: ExprKind::BinOp(Box::new(left), BinOp::Or, Box::new(right)), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }; } else { break; } } Ok(left) } fn parse_and_expr(&mut self) -> Result { let mut left = self.parse_eq_expr()?; loop { if matches!(self.peek(), Some(Token::And)) { let start = left.span.start; self.next(); let right = self.parse_eq_expr()?; let end = right.span.end; left = Expr { kind: ExprKind::BinOp(Box::new(left), BinOp::And, Box::new(right)), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }; } else { break; } } Ok(left) } fn parse_eq_expr(&mut self) -> Result { let mut left = self.parse_comp_expr()?; loop { let op = match self.peek() { Some(Token::Eq) => BinOp::Eq, Some(Token::NotEq) => BinOp::Neq, _ => break, }; let start = left.span.start; self.next(); let right = self.parse_comp_expr()?; let end = right.span.end; left = Expr { kind: ExprKind::BinOp(Box::new(left), op, Box::new(right)), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }; } Ok(left) } fn parse_comp_expr(&mut self) -> Result { let mut left = self.parse_add_expr()?; loop { let op = match self.peek() { Some(Token::Less) => BinOp::Lt, Some(Token::Greater) => BinOp::Gt, Some(Token::LessEq) => BinOp::Leq, Some(Token::GreaterEq) => BinOp::Geq, _ => break, }; let start = left.span.start; self.next(); let right = self.parse_add_expr()?; let end = right.span.end; left = Expr { kind: ExprKind::BinOp(Box::new(left), op, Box::new(right)), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }; } Ok(left) } fn parse_add_expr(&mut self) -> Result { let mut left = self.parse_mul_expr()?; loop { let op = match self.peek() { Some(Token::Plus) => BinOp::Add, Some(Token::Minus) => BinOp::Sub, _ => break, }; let start = left.span.start; self.next(); let right = self.parse_mul_expr()?; let end = right.span.end; left = Expr { kind: ExprKind::BinOp(Box::new(left), op, Box::new(right)), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }; } Ok(left) } fn parse_mul_expr(&mut self) -> Result { let mut left = self.parse_unary_expr()?; loop { let op = match self.peek() { Some(Token::Mul) => BinOp::Mul, Some(Token::Div) => BinOp::Div, Some(Token::Mod) => BinOp::Mod, _ => break, }; let start = left.span.start; self.next(); let right = self.parse_unary_expr()?; let end = right.span.end; left = Expr { kind: ExprKind::BinOp(Box::new(left), op, Box::new(right)), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }; } Ok(left) } fn parse_unary_expr(&mut self) -> Result { let start = self.peek_span().unwrap_or(0..0).start; match self.peek() { Some(Token::Not) => { self.next(); let expr = self.parse_unary_expr()?; let end = expr.span.end; Ok(Expr { kind: ExprKind::UnOp(UnOp::Not, Box::new(expr)), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } Some(Token::Minus) => { self.next(); let expr = self.parse_unary_expr()?; let end = expr.span.end; Ok(Expr { kind: ExprKind::UnOp(UnOp::Neg, Box::new(expr)), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } _ => self.parse_postfix_expr(), } } fn parse_postfix_expr(&mut self) -> Result { let mut expr = self.parse_primary_expr()?; loop { match self.peek() { Some(Token::LParen) => { // Function call let start = expr.span.start; self.next(); let mut args = Vec::new(); loop { if matches!(self.peek(), Some(Token::RParen)) { self.next(); break; } args.push(self.parse_expr()?); if matches!(self.peek(), Some(Token::Comma)) { self.next(); } } let end = self.peek_span().unwrap_or(expr.span.end..expr.span.end).end; expr = Expr { kind: ExprKind::Call(Box::new(expr), args), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }; } Some(Token::LBracket) => { // Index let start = expr.span.start; self.next(); let index = self.parse_expr()?; self.expect(Token::RBracket)?; let end = self.peek_span().unwrap_or(expr.span.end..expr.span.end).end; expr = Expr { kind: ExprKind::Index(Box::new(expr), Box::new(index)), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }; } Some(Token::Dot) => { // Field access let start = expr.span.start; self.next(); let field = match self.next() { Some((Token::Variable(f), _)) => f, Some((_, span)) => { return self.error("Expected field name".to_string(), span); } None => return self.error("Expected field name".to_string(), start..start), }; let end = self.peek_span().unwrap_or(expr.span.end..expr.span.end).end; expr = Expr { kind: ExprKind::Dot(Box::new(expr), field), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }; } Some(Token::OptionalChain) => { // Optional chain let start = expr.span.start; self.next(); let field = match self.next() { Some((Token::Variable(f), _)) => f, Some((_, span)) => { return self.error("Expected field name".to_string(), span); } None => return self.error("Expected field name".to_string(), start..start), }; let end = self.peek_span().unwrap_or(expr.span.end..expr.span.end).end; expr = Expr { kind: ExprKind::OptionalChain(Some(Box::new(expr)), field), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }; } Some(Token::Unwrap) => { // Early return / unwrap let start = expr.span.start; self.next(); let end = self.peek_span().unwrap_or(expr.span.end..expr.span.end).end; expr = Expr { kind: ExprKind::EarlyReturn(Some(Box::new(expr))), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }; } Some(Token::KeywordAs) => { // Cast let start = expr.span.start; self.next(); let type_annot = self.parse_type_annot()?; let end = self.peek_span().unwrap_or(expr.span.end..expr.span.end).end; expr = Expr { kind: ExprKind::Cast(Box::new(expr), type_annot), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }; } _ => break, } } Ok(expr) } fn parse_primary_expr(&mut self) -> Result { let start = self.peek_span().unwrap_or(0..0).start; match self.peek().cloned() { Some(Token::Int(n)) => { self.next(); let end = self.peek_span().unwrap_or(start..start).end; Ok(Expr { kind: ExprKind::Int(n), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } Some(Token::Float(f)) => { self.next(); let end = self.peek_span().unwrap_or(start..start).end; Ok(Expr { kind: ExprKind::Float(f), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } Some(Token::Bool(b)) => { self.next(); let end = self.peek_span().unwrap_or(start..start).end; Ok(Expr { kind: ExprKind::Bool(b), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } Some(Token::String(s)) => { self.next(); let end = self.peek_span().unwrap_or(start..start).end; Ok(Expr { kind: ExprKind::String(s), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } Some(Token::Variable(name)) => { self.next(); // Check for struct literal or enum variant if matches!(self.peek(), Some(Token::LBrace)) { // Struct literal self.next(); let mut fields = Vec::new(); loop { if matches!(self.peek(), Some(Token::RBrace)) { self.next(); break; } let field_name = match self.next() { Some((Token::Variable(f), _)) => f, Some((_, span)) => { return self.error("Expected field name".to_string(), span); } None => { return self.error("Expected field name".to_string(), start..start); } }; self.expect(Token::Colon)?; let field_expr = self.parse_expr()?; fields.push((field_name, field_expr)); if matches!(self.peek(), Some(Token::Comma)) { self.next(); } } let end = self.peek_span().unwrap_or(start..start).end; Ok(Expr { kind: ExprKind::StructLit(name, fields), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } else if matches!(self.peek(), Some(Token::Access)) { // Enum variant self.next(); let variant = match self.next() { Some((Token::Variable(v), _)) => v, Some((_, span)) => { return self.error("Expected variant name".to_string(), span); } None => { return self.error("Expected variant name".to_string(), start..start); } }; let mut args = Vec::new(); if matches!(self.peek(), Some(Token::LParen)) { self.next(); loop { if matches!(self.peek(), Some(Token::RParen)) { self.next(); break; } args.push(self.parse_expr()?); if matches!(self.peek(), Some(Token::Comma)) { self.next(); } } } let end = self.peek_span().unwrap_or(start..start).end; Ok(Expr { kind: ExprKind::EnumLit(name, variant, args), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } else { let end = self.peek_span().unwrap_or(start..start).end; Ok(Expr { kind: ExprKind::Variable(name), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } } Some(Token::LParen) => { self.next(); if matches!(self.peek(), Some(Token::RParen)) { // Empty tuple self.next(); let end = self.peek_span().unwrap_or(start..start).end; Ok(Expr { kind: ExprKind::Tuple(vec![]), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } else { let first = self.parse_expr()?; if matches!(self.peek(), Some(Token::Comma)) { // Tuple let mut elements = vec![first]; self.next(); loop { if matches!(self.peek(), Some(Token::RParen)) { break; } elements.push(self.parse_expr()?); if matches!(self.peek(), Some(Token::Comma)) { self.next(); } } self.expect(Token::RParen)?; let end = self.peek_span().unwrap_or(start..start).end; Ok(Expr { kind: ExprKind::Tuple(elements), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } else { self.expect(Token::RParen)?; let end = self.peek_span().unwrap_or(start..start).end; Ok(Expr { kind: first.kind, span: Span::new(&(start..end), self.file.clone()), attributes: first.attributes, }) } } } Some(Token::LBracket) => { self.next(); let mut elements = Vec::new(); loop { if matches!(self.peek(), Some(Token::RBracket)) { self.next(); break; } elements.push(self.parse_expr()?); if matches!(self.peek(), Some(Token::Comma)) { self.next(); } } let end = self.peek_span().unwrap_or(start..start).end; Ok(Expr { kind: ExprKind::Array(elements), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } Some(Token::KeywordLet) => { self.next(); // Parse binding kind (mut, uniq, once) - comes AFTER let let binding_kind = match self.peek() { Some(Token::KeywordMut) => { self.next(); BindingKind::Mutable } Some(Token::KeywordUniq) => { self.next(); BindingKind::Affine } Some(Token::KeywordOnce) => { self.next(); BindingKind::Linear } _ => BindingKind::Default, }; // Now parse the variable name let var_name = match self.next() { Some((Token::Variable(n), _)) => n, Some((_, span)) => { return self.error("Expected variable name".to_string(), span); } None => return self.error("Expected variable name".to_string(), start..start), }; // Parse optional type annotation let type_annot = if matches!(self.peek(), Some(Token::Colon)) { self.next(); Some(self.parse_type_annot()?) } else { None }; self.expect(Token::Assign)?; let expr = self.parse_expr()?; let end = expr.span.end; Ok(Expr { kind: ExprKind::Let(var_name, binding_kind, type_annot, Box::new(expr)), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } Some(Token::KeywordIf) => { self.next(); let cond = self.parse_expr()?; let then_expr = self.parse_expr()?; let else_expr = if matches!(self.peek(), Some(Token::KeywordElse)) { self.next(); Some(Box::new(self.parse_expr()?)) } else { None }; let end = else_expr .as_ref() .map(|e| e.span.end) .unwrap_or(then_expr.span.end); Ok(Expr { kind: ExprKind::If(Box::new(cond), Box::new(then_expr), else_expr), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } Some(Token::KeywordMatch) => { self.next(); let expr = self.parse_expr()?; let mut arms = Vec::new(); loop { if matches!(self.peek(), Some(Token::KeywordEnd)) { self.next(); break; } let pattern = self.parse_pattern()?; self.expect(Token::FatArrow)?; let body = self.parse_expr()?; arms.push((pattern, body)); if matches!(self.peek(), Some(Token::Comma)) { self.next(); } } let end = self.peek_span().unwrap_or(start..start).end; Ok(Expr { kind: ExprKind::Match(Box::new(expr), arms), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } Some(Token::KeywordWhile) => { self.next(); let cond = self.parse_expr()?; let body = self.parse_expr()?; let end = body.span.end; Ok(Expr { kind: ExprKind::While(Box::new(cond), Box::new(body)), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } Some(Token::KeywordFor) => { self.next(); let var = match self.next() { Some((Token::Variable(v), _)) => v, Some((_, span)) => { return self.error("Expected variable name".to_string(), span); } None => return self.error("Expected variable name".to_string(), start..start), }; self.expect(Token::KeywordIn)?; let iterable = self.parse_expr()?; let body = self.parse_expr()?; let end = body.span.end; Ok(Expr { kind: ExprKind::For(var, Box::new(iterable), Box::new(body)), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } Some(Token::KeywordDo) => { self.next(); let mut exprs = Vec::new(); loop { if matches!(self.peek(), Some(Token::KeywordEnd)) { self.next(); break; } exprs.push(self.parse_expr()?); if matches!(self.peek(), Some(Token::Semicolon)) { self.next(); } } let end = self.peek_span().unwrap_or(start..start).end; Ok(Expr { kind: ExprKind::Do(exprs), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } Some(Token::KeywordLambda) => { let start = self.peek_span().unwrap_or(0..0).start; self.next(); self.expect(Token::LParen)?; let mut params = Vec::new(); loop { if matches!(self.peek(), Some(Token::RParen)) { self.next(); break; } let param_name = match self.next() { Some((Token::Variable(p), _)) => p, Some((_, span)) => { return self.error("Expected parameter name".to_string(), span); } None => { return self.error("Expected parameter name".to_string(), start..start); } }; // Check for optional type annotation let param_type = if matches!(self.peek(), Some(Token::Colon)) { self.next(); // consume ':' Some(self.parse_type_annot()?) } else { None }; params.push((param_name, param_type)); if matches!(self.peek(), Some(Token::Comma)) { self.next(); } } let body = self.parse_expr()?; let end = body.span.end; Ok(Expr { kind: ExprKind::Lambda(params, Box::new(body)), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } Some(Token::KeywordReturn) => { self.next(); let expr = if self.is_expr_end() { None } else { Some(Box::new(self.parse_expr()?)) }; let end = expr .as_ref() .map(|e| e.span.end) .unwrap_or(self.peek_span().unwrap_or(start..start).end); Ok(Expr { kind: ExprKind::Return(expr), span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } Some(Token::KeywordBreak) => { self.next(); let end = self.peek_span().unwrap_or(start..start).end; Ok(Expr { kind: ExprKind::Break, span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } Some(Token::KeywordContinue) => { self.next(); let end = self.peek_span().unwrap_or(start..start).end; Ok(Expr { kind: ExprKind::Continue, span: Span::new(&(start..end), self.file.clone()), attributes: Vec::new(), }) } Some(token) => { let span = self.peek_span().unwrap_or(start..start); self.error(format!("Unexpected token: {:?}", token), span) } None => self.error("Unexpected EOF".to_string(), start..start), } } fn parse_pattern(&mut self) -> Result { let start = self.peek_span().unwrap_or(0..0).start; match self.peek().cloned() { Some(Token::Variable(name)) => { self.next(); let end = self.peek_span().unwrap_or(start..start).end; // Check for struct or enum pattern if matches!(self.peek(), Some(Token::LBrace)) { // Struct pattern self.next(); let mut fields = Vec::new(); loop { if matches!(self.peek(), Some(Token::RBrace)) { self.next(); break; } let field_name = match self.next() { Some((Token::Variable(f), _)) => f, Some((_, span)) => { return self.error("Expected field name".to_string(), span); } None => { return self.error("Expected field name".to_string(), start..start); } }; self.expect(Token::Colon)?; let pattern = self.parse_pattern()?; fields.push((field_name, pattern)); if matches!(self.peek(), Some(Token::Comma)) { self.next(); } } let end = self.peek_span().unwrap_or(start..start).end; Ok(Pattern { kind: PatternKind::Struct(name, fields), span: Span::new(&(start..end), self.file.clone()), }) } else if matches!(self.peek(), Some(Token::Access)) { // Enum pattern self.next(); let variant = match self.next() { Some((Token::Variable(v), _)) => v, Some((_, span)) => { return self.error("Expected variant name".to_string(), span); } None => { return self.error("Expected variant name".to_string(), start..start); } }; let mut patterns = Vec::new(); if matches!(self.peek(), Some(Token::LParen)) { self.next(); loop { if matches!(self.peek(), Some(Token::RParen)) { self.next(); break; } patterns.push(self.parse_pattern()?); if matches!(self.peek(), Some(Token::Comma)) { self.next(); } } } let end = self.peek_span().unwrap_or(start..start).end; Ok(Pattern { kind: PatternKind::Enum(name, variant, patterns), span: Span::new(&(start..end), self.file.clone()), }) } else { Ok(Pattern { kind: PatternKind::Variable(name), span: Span::new(&(start..end), self.file.clone()), }) } } Some(Token::Union) => { self.next(); let end = self.peek_span().unwrap_or(start..start).end; Ok(Pattern { kind: PatternKind::Wildcard, span: Span::new(&(start..end), self.file.clone()), }) } Some(Token::LParen) => { self.next(); let mut patterns = Vec::new(); loop { if matches!(self.peek(), Some(Token::RParen)) { self.next(); break; } patterns.push(self.parse_pattern()?); if matches!(self.peek(), Some(Token::Comma)) { self.next(); } } let end = self.peek_span().unwrap_or(start..start).end; Ok(Pattern { kind: PatternKind::Tuple(patterns), span: Span::new(&(start..end), self.file.clone()), }) } Some(Token::String(s)) => { self.next(); let end = self.peek_span().unwrap_or(start..start).end; Ok(Pattern { kind: PatternKind::Literal(s), span: Span::new(&(start..end), self.file.clone()), }) } Some(Token::Int(n)) => { self.next(); let end = self.peek_span().unwrap_or(start..start).end; Ok(Pattern { kind: PatternKind::Literal(n.to_string()), span: Span::new(&(start..end), self.file.clone()), }) } Some(Token::Float(f)) => { self.next(); let end = self.peek_span().unwrap_or(start..start).end; Ok(Pattern { kind: PatternKind::Literal(f.to_string()), span: Span::new(&(start..end), self.file.clone()), }) } Some(Token::Bool(b)) => { self.next(); let end = self.peek_span().unwrap_or(start..start).end; Ok(Pattern { kind: PatternKind::Literal(b.to_string()), span: Span::new(&(start..end), self.file.clone()), }) } Some(token) => { let span = self.peek_span().unwrap_or(start..start); self.error(format!("Unexpected token in pattern: {:?}", token), span) } None => self.error("Unexpected EOF".to_string(), start..start), } } fn is_expr_end(&mut self) -> bool { matches!( self.peek(), Some(Token::RParen) | Some(Token::RBracket) | Some(Token::RBrace) | Some(Token::Comma) | Some(Token::Semicolon) | Some(Token::KeywordEnd) | Some(Token::FatArrow) ) } }