From 806d5fe4fa6d923ee79bc6e22ee80aa6ae394b1e Mon Sep 17 00:00:00 2001 From: nulluser0 Date: Mon, 17 Jun 2024 00:06:31 +1000 Subject: [PATCH] better parsing error handling --- src/frontend/lexer.rs | 8 +- src/frontend/parser.rs | 450 +++++++++++++++++++++++++---------------- src/utils/run.rs | 2 +- 3 files changed, 277 insertions(+), 183 deletions(-) diff --git a/src/frontend/lexer.rs b/src/frontend/lexer.rs index 80dccb2..6e52729 100644 --- a/src/frontend/lexer.rs +++ b/src/frontend/lexer.rs @@ -6,7 +6,7 @@ use std::{ str::{Chars, FromStr}, }; -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum Token { // Keywords Keyword(Keyword), @@ -45,7 +45,7 @@ impl std::fmt::Display for Token { } // Keywords -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum Keyword { Import, // import Fn, // fn @@ -96,7 +96,7 @@ impl FromStr for Keyword { } // Operators -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum Operator { Assign, // = Add, // + @@ -119,7 +119,7 @@ pub enum Operator { } // Symbols/Delimiters -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum Symbol { LeftParen, // ( RightParen, // ) diff --git a/src/frontend/parser.rs b/src/frontend/parser.rs index 58cc6fa..c4b511e 100644 --- a/src/frontend/parser.rs +++ b/src/frontend/parser.rs @@ -1,8 +1,5 @@ // Parser -use core::panic; -use std::process; - use crate::frontend::ast::{BinaryOp, Program, Property}; use super::{ @@ -15,6 +12,7 @@ pub struct Parser { tokens: Vec, inside_loop: bool, inside_function: bool, + position: usize, } impl Default for Parser { @@ -29,6 +27,7 @@ impl Parser { tokens: Vec::new(), inside_loop: false, inside_function: false, + position: 0, } } @@ -41,19 +40,25 @@ impl Parser { } fn eat(&mut self) -> Token { + self.position += 1; self.tokens.remove(0) as Token } - fn expect(&mut self, token: Token, err: &str) -> Token { + fn expect(&mut self, token: Token, err: &str) -> Result { let prev = self.tokens.remove(0) as Token; if prev != token { - println!("Parser error:\n{} {:?} - Expecting: {:?}", err, prev, token); - process::exit(1); + return Err(ParserError::UnexpectedToken { + expected: token, + found: prev, + position: self.position, + message: err.to_string(), + }); } - prev + self.position += 1; + Ok(prev) } - fn parse_stmt(&mut self) -> Stmt { + fn parse_stmt(&mut self) -> Result { match self.at() { Token::Keyword(Keyword::Let) => self.parse_var_declaration(false), Token::Keyword(Keyword::Const) => self.parse_var_declaration(true), @@ -62,96 +67,88 @@ impl Parser { self.eat(); match self.at() { Token::Keyword(Keyword::Fn) => self.parse_fn_declaration(true), - _ => panic!("Async: `fn` missing!"), + _ => Err(ParserError::MissingAsyncFn), } } Token::Keyword(Keyword::Break) => self.parse_break_declaration(), Token::Keyword(Keyword::Return) => self.parse_return_declaration(), - // Token::Identifier(_) => todo!(), - // Token::IntegerLiteral(_) => todo!(), - // Token::StringLiteral(_) => todo!(), - // Token::Operator(_) => todo!(), - // Token::Symbol(_) => todo!(), - // Token::EOF => todo!(), - _ => Stmt::ExprStmt(self.parse_expr()), + _ => Ok(Stmt::ExprStmt(self.parse_expr()?)), } } - fn parse_break_declaration(&mut self) -> Stmt { + fn parse_break_declaration(&mut self) -> Result { self.eat(); if !self.inside_loop { - panic!("`break` statement found outside of a loop (while, for, loop) context.") + return Err(ParserError::BreakOutsideLoop(self.position)); } if *self.at() == Token::Symbol(Symbol::Semicolon) { self.eat(); - return Stmt::BreakStmt(None); + return Ok(Stmt::BreakStmt(None)); } - let expr = self.parse_expr(); + let expr = self.parse_expr()?; self.expect( Token::Symbol(Symbol::Semicolon), "break declaration is a statement. It must end with a semicolon.", - ); - Stmt::BreakStmt(Some(expr)) + )?; + Ok(Stmt::BreakStmt(Some(expr))) } - fn parse_return_declaration(&mut self) -> Stmt { + fn parse_return_declaration(&mut self) -> Result { self.eat(); if !self.inside_function { - panic!("`return` statement found outside of a function context.") + return Err(ParserError::ReturnOutsideFunction(self.position)); } if *self.at() == Token::Symbol(Symbol::Semicolon) { self.eat(); - return Stmt::ReturnStmt(None); + return Ok(Stmt::ReturnStmt(None)); } - let expr = self.parse_expr(); + let expr = self.parse_expr()?; self.expect( Token::Symbol(Symbol::Semicolon), "return declaration is a statement. It must end with a semicolon.", - ); - Stmt::ReturnStmt(Some(expr)) + )?; + Ok(Stmt::ReturnStmt(Some(expr))) } - fn parse_fn_declaration(&mut self, is_async: bool) -> Stmt { + fn parse_fn_declaration(&mut self, is_async: bool) -> Result { self.eat(); let name = match self.eat() { Token::Identifier(name) => name, - _ => panic!("No identifier for fn!"), + _ => return Err(ParserError::MissingFunctionIdentifier(self.position)), }; - let args: Vec = self.parse_args(); + let args: Vec = self.parse_args()?; let mut params: Vec = Vec::new(); for arg in args { match arg { Expr::Identifier(name) => params.push(name), - _ => panic!( - "Inside function declaration expected parameters to be one of type String." - ), + _ => return Err(ParserError::InvalidFunctionParameter(self.position)), } } self.expect( Token::Symbol(Symbol::LeftBrace), "Expected function body following declaration.", - ); + )?; let prev_inside_function = self.inside_function; self.inside_function = true; let mut body: Vec = Vec::new(); while self.not_eof() && *self.at() != Token::Symbol(Symbol::RightBrace) { - body.push(self.parse_stmt()); + body.push(self.parse_stmt()?); } self.inside_function = prev_inside_function; self.expect( Token::Symbol(Symbol::RightBrace), "Closing brace expected inside function declaration.", - ); - Stmt::FunctionDeclaration { + )?; + Ok(Stmt::FunctionDeclaration { parameters: params, name, body, is_async, - } + }) } // `let (global) (mut) ident(: type) = expr` - fn parse_var_declaration(&mut self, is_const: bool) -> Stmt { + fn parse_var_declaration(&mut self, is_const: bool) -> Result { let _ = self.eat(); // remove unneeded let/const token. let is_global = match self.at() { Token::Keyword(Keyword::Global) => { @@ -165,7 +162,7 @@ impl Parser { Token::Keyword(Keyword::Mut) => { let _ = self.eat(); // We now know mut keyword us used. Advance. if is_const { - panic!("Cannot apply mutability `mut` to a constant `const`!"); + return Err(ParserError::MutConstConflict(self.position)); } true } @@ -174,59 +171,57 @@ impl Parser { let identifier = match self.eat() { Token::Identifier(name) => Token::Identifier(name), - _ => panic!("Expected identifier name following let keyword."), + _ => return Err(ParserError::MissingIdentifier(self.position)), }; - // TODO: Implement type support! - if *self.at() == Token::Symbol(Symbol::Semicolon) { self.eat(); if is_const { - panic!("Must assign value to `const` expression. No value provided."); + return Err(ParserError::ConstWithoutValue(self.position)); } - return Stmt::DeclareStmt { + return Ok(Stmt::DeclareStmt { name: identifier.to_string(), is_mutable, is_global, expr: None, - }; + }); } self.expect( Token::Operator(Operator::Assign), "Expected assign token `=` following identifier in var declaration.", - ); + )?; let declaration = Stmt::DeclareStmt { name: identifier.to_string(), is_mutable, is_global, - expr: Some(self.parse_expr()), + expr: Some(self.parse_expr()?), }; self.expect( Token::Symbol(Symbol::Semicolon), "Variable declaration is a statement. It must end with a semicolon.", - ); - declaration + )?; + Ok(declaration) } - fn parse_expr(&mut self) -> Expr { + fn parse_expr(&mut self) -> Result { self.parse_assignment_expr() } - fn parse_assignment_expr(&mut self) -> Expr { - let left = self.parse_object_expr(); + fn parse_assignment_expr(&mut self) -> Result { + let left = self.parse_object_expr()?; if *self.at() == Token::Operator(Operator::Assign) { - let _ = self.eat(); // Advance after. - let value = self.parse_assignment_expr(); - return Expr::AssignmentExpr { + self.eat(); // Advance after. + let value = self.parse_assignment_expr()?; + return Ok(Expr::AssignmentExpr { assignee: Box::new(left), expr: Box::new(value), - }; + }); } - left + Ok(left) } - fn parse_object_expr(&mut self) -> Expr { + fn parse_object_expr(&mut self) -> Result { if *self.at() != Token::Symbol(Symbol::LeftBrace) { return self.parse_relational_expr(); } @@ -235,26 +230,23 @@ impl Parser { while self.not_eof() && *self.at() != Token::Symbol(Symbol::RightBrace) { let key = match self.eat() { Token::Identifier(name) => name, - _ => panic!("Object literal key expected."), + _ => return Err(ParserError::ObjectLiteralKeyExpected(self.position)), }; - // Allows shorthand key: pair -> { key, } if *self.at() == Token::Symbol(Symbol::Comma) { self.eat(); // Advance properties.push(Property { key, value: None }); break; - // Allows shorthand key: pair -> { key } } else if *self.at() == Token::Symbol(Symbol::RightBrace) { properties.push(Property { key, value: None }); break; } - // { key: val } self.expect( Token::Symbol(Symbol::Colon), "Missing colon following identifier in Object Expression", - ); - let value = self.parse_expr(); + )?; + let value = self.parse_expr()?; properties.push(Property { key, value: Some(value), @@ -263,18 +255,18 @@ impl Parser { self.expect( Token::Symbol(Symbol::Comma), "Expected comma or Right Brace following property.", - ); + )?; } } self.expect( Token::Symbol(Symbol::RightBrace), "Object literal missing right brace `}`.", - ); - Expr::Literal(Literal::Object(properties)) + )?; + Ok(Expr::Literal(Literal::Object(properties))) } - fn parse_relational_expr(&mut self) -> Expr { - let mut left = self.parse_concatenation_expr(); + fn parse_relational_expr(&mut self) -> Result { + let mut left = self.parse_concatenation_expr()?; while matches!( self.at(), Token::Operator(Operator::GreaterThan) @@ -293,36 +285,38 @@ impl Parser { Token::Operator(Operator::Equal) => BinaryOp::Equal, Token::Operator(Operator::NotEqual) => BinaryOp::NotEqual, _ => { - println!("Token is not an operator! {:#?}", operator_astoken); - process::exit(1); + return Err(ParserError::InvalidOperator( + self.position, + operator_astoken.clone(), + )); } }; - let right = self.parse_concatenation_expr(); + let right = self.parse_concatenation_expr()?; left = Expr::BinaryOp { op: operator, left: Box::new(left), right: Box::new(right), }; } - left + Ok(left) } - fn parse_concatenation_expr(&mut self) -> Expr { - let mut left = self.parse_additive_expr(); + fn parse_concatenation_expr(&mut self) -> Result { + let mut left = self.parse_additive_expr()?; while matches!(self.at(), Token::Operator(Operator::Concat)) { self.eat(); - let right = self.parse_additive_expr(); + let right = self.parse_additive_expr()?; left = Expr::ConcatOp { left: Box::new(left), right: Box::new(right), } } - left + Ok(left) } - fn parse_additive_expr(&mut self) -> Expr { - let mut left = self.parse_multiplicative_expr(); + fn parse_additive_expr(&mut self) -> Result { + let mut left = self.parse_multiplicative_expr()?; while matches!( self.at(), @@ -332,22 +326,24 @@ impl Parser { let operator: BinaryOp = match operator_astoken { Token::Operator(op) => op.into(), _ => { - println!("Token is not an operator! {:#?}", operator_astoken); - process::exit(1); + return Err(ParserError::InvalidOperator( + self.position, + operator_astoken.clone(), + )); } }; - let right = self.parse_multiplicative_expr(); + let right = self.parse_multiplicative_expr()?; left = Expr::BinaryOp { op: operator, left: Box::new(left), right: Box::new(right), }; } - left + Ok(left) } - fn parse_multiplicative_expr(&mut self) -> Expr { - let mut left = self.parse_call_member_expr(); + fn parse_multiplicative_expr(&mut self) -> Result { + let mut left = self.parse_call_member_expr()?; while matches!( self.at(), @@ -359,60 +355,62 @@ impl Parser { let operator: BinaryOp = match operator_astoken { Token::Operator(op) => op.into(), _ => { - println!("Token is not an operator! {:#?}", operator_astoken); - process::exit(1); + return Err(ParserError::InvalidOperator( + self.position, + operator_astoken.clone(), + )); } }; - let right = self.parse_call_member_expr(); + let right = self.parse_call_member_expr()?; left = Expr::BinaryOp { op: operator, left: Box::new(left), right: Box::new(right), }; } - left + Ok(left) } - fn parse_call_member_expr(&mut self) -> Expr { - let member = self.parse_member_expr(); + fn parse_call_member_expr(&mut self) -> Result { + let member = self.parse_member_expr()?; if *self.at() == Token::Symbol(Symbol::LeftParen) { return self.parse_call_expr(member); } - member + Ok(member) } - fn parse_call_expr(&mut self, caller: Expr) -> Expr { - let mut call_expr: Expr = Expr::FunctionCall(self.parse_args(), Box::new(caller)); + fn parse_call_expr(&mut self, caller: Expr) -> Result { + let mut call_expr: Expr = Expr::FunctionCall(self.parse_args()?, Box::new(caller)); if *self.at() == Token::Symbol(Symbol::LeftParen) { - call_expr = self.parse_call_expr(call_expr); + call_expr = self.parse_call_expr(call_expr)?; } - call_expr + Ok(call_expr) } - fn parse_args(&mut self) -> Vec { - self.expect(Token::Symbol(Symbol::LeftParen), "Expected left paren."); + fn parse_args(&mut self) -> Result, ParserError> { + self.expect(Token::Symbol(Symbol::LeftParen), "Expected left paren.")?; let args = match *self.at() == Token::Symbol(Symbol::RightParen) { true => vec![], - false => self.parse_arguments_list(), + false => self.parse_arguments_list()?, }; self.expect( Token::Symbol(Symbol::RightParen), "Missing right paren inside arguments list.", - ); - args + )?; + Ok(args) } - fn parse_arguments_list(&mut self) -> Vec { - let mut args = vec![self.parse_expr()]; + fn parse_arguments_list(&mut self) -> Result, ParserError> { + let mut args = vec![self.parse_expr()?]; while *self.at() == Token::Symbol(Symbol::Comma) && self.not_eof() { self.eat(); - args.push(self.parse_assignment_expr()); + args.push(self.parse_assignment_expr()?); } - args + Ok(args) } - fn parse_member_expr(&mut self) -> Expr { - let mut object = self.parse_primary_expr(); + fn parse_member_expr(&mut self) -> Result { + let mut object = self.parse_primary_expr()?; while *self.at() == Token::Symbol(Symbol::Dot) || *self.at() == Token::Symbol(Symbol::LeftBracket) { @@ -422,202 +420,298 @@ impl Parser { // obj.expr if operator == Token::Symbol(Symbol::Dot) { // Get identifier - property = self.parse_primary_expr(); + property = self.parse_primary_expr()?; match property { Expr::Identifier(_) => {} - _ => panic!( - "Cannot use dot operator without right hand side being an identifier." - ), + _ => { + return Err(ParserError::InvalidDotProperty( + self.position, + property.clone(), + )); + } } } else { // This allows obj[computed value] - property = self.parse_expr(); + property = self.parse_expr()?; self.expect( Token::Symbol(Symbol::RightBracket), "Missing right bracket in computed value.", - ); + )?; } object = Expr::Member(Box::new(object), Box::new(property)); } - object + Ok(object) } - fn parse_primary_expr(&mut self) -> Expr { + fn parse_primary_expr(&mut self) -> Result { let tk = self.eat(); match tk { // Keyword - Token::Keyword(Keyword::If) => self.parse_if_expr() as Expr, - Token::Keyword(Keyword::While) => self.parse_while_expr() as Expr, - Token::Keyword(Keyword::Loop) => self.parse_loop_expr() as Expr, - Token::Keyword(Keyword::Block) => self.parse_block_expr() as Expr, + Token::Keyword(Keyword::If) => self.parse_if_expr() as Result, + Token::Keyword(Keyword::While) => self.parse_while_expr() as Result, + Token::Keyword(Keyword::Loop) => self.parse_loop_expr() as Result, + Token::Keyword(Keyword::Block) => self.parse_block_expr() as Result, // Identifier - Token::Identifier(name) => Expr::Identifier(name.to_string()) as Expr, + Token::Identifier(name) => { + Ok(Expr::Identifier(name.to_string())) as Result + } // Literals - Token::StringLiteral(string) => Expr::Literal(Literal::String(string)) as Expr, - Token::IntegerLiteral(integer) => Expr::Literal(Literal::Integer(integer)) as Expr, - Token::FloatLiteral(float) => Expr::Literal(Literal::Float(float)) as Expr, - // Token::StringLiteral(_) => todo!(), + Token::StringLiteral(string) => { + Ok(Expr::Literal(Literal::String(string))) as Result + } + Token::IntegerLiteral(integer) => { + Ok(Expr::Literal(Literal::Integer(integer))) as Result + } + Token::FloatLiteral(float) => { + Ok(Expr::Literal(Literal::Float(float))) as Result + } // Unary Operators Token::Operator(Operator::LogicalNot) => { - let expr = self.parse_call_member_expr(); - Expr::UnaryOp(UnaryOp::LogicalNot, Box::new(expr)) + let expr = self.parse_call_member_expr()?; + Ok(Expr::UnaryOp(UnaryOp::LogicalNot, Box::new(expr))) } Token::Operator(Operator::Subtract) => { - let expr = self.parse_call_member_expr(); - Expr::UnaryOp(UnaryOp::ArithmeticNegative, Box::new(expr)) + let expr = self.parse_call_member_expr()?; + Ok(Expr::UnaryOp(UnaryOp::ArithmeticNegative, Box::new(expr))) } Token::Operator(Operator::Add) => { - let expr = self.parse_call_member_expr(); - Expr::UnaryOp(UnaryOp::ArithmeticPositive, Box::new(expr)) + let expr = self.parse_call_member_expr()?; + Ok(Expr::UnaryOp(UnaryOp::ArithmeticPositive, Box::new(expr))) } Token::Operator(Operator::BitwiseNot) => { - let expr = self.parse_call_member_expr(); - Expr::UnaryOp(UnaryOp::BitwiseNot, Box::new(expr)) + let expr = self.parse_call_member_expr()?; + Ok(Expr::UnaryOp(UnaryOp::BitwiseNot, Box::new(expr))) } // Symbols Token::Symbol(Symbol::LeftParen) => { - let value = self.parse_expr(); + let value = self.parse_expr()?; self.expect( Token::Symbol(Symbol::RightParen), "Unexpected token found inside parenthesised expression. Expected closing parenthesis." - ); // rightParen - value + )?; // rightParen + Ok(value) } Token::Symbol(Symbol::LeftBracket) => { let mut elements: Vec = Vec::new(); if self.not_eof() && *self.at() != Token::Symbol(Symbol::RightBracket) { // Parse elements - elements.push(self.parse_expr()); + elements.push(self.parse_expr()?); while *self.at() == Token::Symbol(Symbol::Comma) { self.eat(); // Consume comma - elements.push(self.parse_expr()); + elements.push(self.parse_expr()?); } } self.expect( Token::Symbol(Symbol::RightBracket), "Expected right bracket after array literal.", - ); - Expr::Array(elements) - } - Token::Symbol(Symbol::Semicolon) => Expr::SpecialNull, - // Token::EOF => todo!(), - _ => { - println!("Unexpected token found during parsing! {:#?}", tk); - process::exit(1); + )?; + Ok(Expr::Array(elements)) } + Token::Symbol(Symbol::Semicolon) => Ok(Expr::SpecialNull), + _ => Err(ParserError::UnexpectedToken { + expected: Token::EOF, + found: tk.clone(), + position: self.position, + message: format!("Unexpected token found during parsing! {:?}", tk), + }), } } - fn parse_while_expr(&mut self) -> Expr { - let condition = self.parse_expr(); + fn parse_while_expr(&mut self) -> Result { + let condition = self.parse_expr()?; self.expect( Token::Symbol(Symbol::LeftBrace), "Expected left brace before `while` expression.", - ); + )?; let prev_inside_loop = self.inside_loop; // Save previous context. self.inside_loop = true; // We are now in a loop context. Modify parser. let mut statements: Vec = Vec::new(); while self.not_eof() && *self.at() != Token::Symbol(Symbol::RightBrace) { - statements.push(self.parse_stmt()); + statements.push(self.parse_stmt()?); } self.inside_loop = prev_inside_loop; // Restore previous context self.expect( Token::Symbol(Symbol::RightBrace), "Expected right brace after `while` expression.", - ); - Expr::WhileExpr { + )?; + Ok(Expr::WhileExpr { condition: Box::new(condition), then: statements, - } + }) } - fn parse_block_expr(&mut self) -> Expr { + fn parse_block_expr(&mut self) -> Result { self.expect( Token::Symbol(Symbol::LeftBrace), "Expected left brace before `block` expression.", - ); + )?; let mut statements: Vec = Vec::new(); while self.not_eof() && *self.at() != Token::Symbol(Symbol::RightBrace) { - statements.push(self.parse_stmt()); + statements.push(self.parse_stmt()?); } self.expect( Token::Symbol(Symbol::RightBrace), - "Expected right brace after `while` expression.", - ); - Expr::BlockExpr(statements) + "Expected right brace after `block` expression.", + )?; + Ok(Expr::BlockExpr(statements)) } - fn parse_loop_expr(&mut self) -> Expr { + fn parse_loop_expr(&mut self) -> Result { self.expect( Token::Symbol(Symbol::LeftBrace), "Expected left brace before `loop` expression.", - ); + )?; let prev_inside_loop = self.inside_loop; // Save previous context. self.inside_loop = true; // We are now in a loop context. Modify parser. let mut statements: Vec = Vec::new(); while self.not_eof() && *self.at() != Token::Symbol(Symbol::RightBrace) { - statements.push(self.parse_stmt()); + statements.push(self.parse_stmt()?); } self.inside_loop = prev_inside_loop; // Restore previous context self.expect( Token::Symbol(Symbol::RightBrace), "Expected right brace after `loop` expression.", - ); - Expr::ForeverLoopExpr(statements) + )?; + Ok(Expr::ForeverLoopExpr(statements)) } - fn parse_if_expr(&mut self) -> Expr { - let condition = self.parse_expr(); + fn parse_if_expr(&mut self) -> Result { + let condition = self.parse_expr()?; self.expect( Token::Symbol(Symbol::LeftBrace), "Expected left brace before `if` expression.", - ); + )?; let mut consequent: Vec = Vec::new(); while self.not_eof() && *self.at() != Token::Symbol(Symbol::RightBrace) { - consequent.push(self.parse_stmt()); + consequent.push(self.parse_stmt()?); } self.expect( Token::Symbol(Symbol::RightBrace), "Expected right brace after `if` expression.", - ); + )?; let mut alternative: Option> = None; if *self.at() == Token::Keyword(Keyword::Else) { self.eat(); // Advance from else if *self.at() == Token::Keyword(Keyword::If) { self.eat(); - alternative = Some(vec![Stmt::ExprStmt(self.parse_if_expr())]) + alternative = Some(vec![Stmt::ExprStmt(self.parse_if_expr()?)]) } else { self.expect( Token::Symbol(Symbol::LeftBrace), "Expected left brace before `else` expression.", - ); + )?; let mut else_block: Vec = Vec::new(); while self.not_eof() && *self.at() != Token::Symbol(Symbol::RightBrace) { - else_block.push(self.parse_stmt()); + else_block.push(self.parse_stmt()?); } self.expect( Token::Symbol(Symbol::RightBrace), "Expected right brace after `else` expression.", - ); + )?; alternative = Some(else_block); } } - Expr::IfExpr { + Ok(Expr::IfExpr { condition: Box::new(condition), then: consequent, else_stmt: alternative, - } + }) } - pub fn produce_ast(&mut self, source_code: String) -> Result { + pub fn produce_ast(&mut self, source_code: String) -> Result { self.tokens = tokenize(&source_code); let mut program = Program::new(Vec::new()); while self.not_eof() { - program.statements.push(self.parse_stmt()) // SHOULD BE PARSE_STMT!!! + program.statements.push(self.parse_stmt()?); // SHOULD BE PARSE_STMT!!! } Ok(program) } } + +#[derive(Debug)] +pub enum ParserError { + UnexpectedToken { + expected: Token, + found: Token, + position: usize, + message: String, + }, + MissingAsyncFn, + BreakOutsideLoop(usize), + ReturnOutsideFunction(usize), + MissingFunctionIdentifier(usize), + InvalidFunctionParameter(usize), + MutConstConflict(usize), + MissingIdentifier(usize), + ConstWithoutValue(usize), + ObjectLiteralKeyExpected(usize), + InvalidOperator(usize, Token), + InvalidDotProperty(usize, Expr), + // ... other error variants +} + +impl std::fmt::Display for ParserError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ParserError::UnexpectedToken { + expected, + found, + position, + message, + } => { + write!( + f, + "Error at position {}: {}. Expected {:?}, but found {:?}", + position, message, expected, found + ) + } + ParserError::MissingAsyncFn => write!(f, "Error: `async` must be followed by `fn`"), + ParserError::BreakOutsideLoop(pos) => write!( + f, + "Error at position {}: `break` found outside of loop context", + pos + ), + ParserError::ReturnOutsideFunction(pos) => write!( + f, + "Error at position {}: `return` found outside of function context", + pos + ), + ParserError::MissingFunctionIdentifier(pos) => { + write!(f, "Error at position {}: Missing function identifier", pos) + } + ParserError::InvalidFunctionParameter(pos) => { + write!(f, "Error at position {}: Invalid function parameter", pos) + } + ParserError::MutConstConflict(pos) => write!( + f, + "Error at position {}: Cannot use `mut` with `const`", + pos + ), + ParserError::MissingIdentifier(pos) => { + write!(f, "Error at position {}: Missing identifier", pos) + } + ParserError::ConstWithoutValue(pos) => write!( + f, + "Error at position {}: `const` must have an assigned value", + pos + ), + ParserError::ObjectLiteralKeyExpected(pos) => { + write!(f, "Error at position {}: Object literal key expected", pos) + } + ParserError::InvalidOperator(pos, token) => { + write!(f, "Error at position {}: Invalid operator {:?}", pos, token) + } + ParserError::InvalidDotProperty(pos, expr) => write!( + f, + "Error at position {}: Invalid property access using dot operator {:?}", + pos, expr + ), + // ... other error variants + } + } +} + +impl std::error::Error for ParserError {} diff --git a/src/utils/run.rs b/src/utils/run.rs index 1f15ff9..80e161c 100644 --- a/src/utils/run.rs +++ b/src/utils/run.rs @@ -20,7 +20,7 @@ pub fn run(input: String, env: &Rc>) { } } Err(e) => { - println!("Error: {:?}", e); + println!("Error: {}", e); } } }