From f95d504f88e013f9a101ec0f5c3026f96c16b79c Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Sat, 28 Mar 2026 20:50:46 -0500 Subject: [PATCH] Another big parser refactor, collecting diagnostics better. --- dm/src/repl.rs | 11 +- dm/src/run.rs | 4 +- dmc-lib/src/ast/assign_statement.rs | 11 +- dmc-lib/src/ast/type_use.rs | 4 +- dmc-lib/src/compile_pipeline.rs | 11 +- dmc-lib/src/ir/ir_block.rs | 4 +- dmc-lib/src/parser.rs | 1234 ++++++++++++++++----------- e2e-tests/src/lib.rs | 11 +- 8 files changed, 765 insertions(+), 525 deletions(-) diff --git a/dm/src/repl.rs b/dm/src/repl.rs index 27f109d..d83c827 100644 --- a/dm/src/repl.rs +++ b/dm/src/repl.rs @@ -175,7 +175,10 @@ fn compile_expression( constants_table: &mut ConstantsTable, ) -> Result> { // parse - let mut expression = parse_expression(input)?; + let (mut expression, parse_diagnostics) = parse_expression(input); + if !parse_diagnostics.is_empty() { + return Err(parse_diagnostics); + } // init scopes, if necessary let container_scope = prepare_scopes(symbol_table, fn_body_scope_id); @@ -240,7 +243,11 @@ fn compile_let_statement( constants_table: &mut ConstantsTable, ) -> Result> { // parse - let mut let_statement = parse_let_statement(input)?; + let (maybe_let_statement, parse_diagnostics) = parse_let_statement(input); + if !parse_diagnostics.is_empty() { + return Err(parse_diagnostics); + } + let mut let_statement = maybe_let_statement.unwrap(); // names let container_scope_id = prepare_scopes(symbol_table, body_scope_id); diff --git a/dm/src/run.rs b/dm/src/run.rs index 5a3fcc7..32b2e38 100644 --- a/dm/src/run.rs +++ b/dm/src/run.rs @@ -7,7 +7,7 @@ use dmc_lib::constants_table::ConstantsTable; use dmc_lib::diagnostic::Diagnostic; use dmc_lib::intrinsics::{insert_intrinsic_symbols, insert_intrinsic_types}; use dmc_lib::offset_counter::OffsetCounter; -use dmc_lib::parser::parse_compilation_unit; +use dmc_lib::parser::get_compilation_unit; use dmc_lib::symbol_table::SymbolTable; use dmc_lib::types_table::TypesTable; use dvm_lib::vm::constant::{Constant, StringConstant}; @@ -41,7 +41,7 @@ fn run( show_asm: bool, register_count: usize, ) -> Result<(), Vec> { - let mut compilation_unit = parse_compilation_unit(&input)?; + let mut compilation_unit = get_compilation_unit(&input)?; let mut symbol_table = SymbolTable::new(); symbol_table.push_module_scope("global scope"); diff --git a/dmc-lib/src/ast/assign_statement.rs b/dmc-lib/src/ast/assign_statement.rs index 654eec8..0750989 100644 --- a/dmc-lib/src/ast/assign_statement.rs +++ b/dmc-lib/src/ast/assign_statement.rs @@ -255,7 +255,7 @@ mod tests { use crate::ast::compilation_unit::CompilationUnit; use crate::diagnostic::Diagnostic; use crate::error_codes::{ASSIGN_LHS_IMMUTABLE, ASSIGN_MISMATCHED_TYPES, ASSIGN_NO_L_VALUE}; - use crate::parser::parse_compilation_unit; + use crate::parser::get_compilation_unit; use crate::symbol_table::SymbolTable; use crate::types_table::TypesTable; @@ -272,15 +272,14 @@ mod tests { #[test] fn finds_mismatched_types() -> Result<(), Vec> { - let mut compilation_unit = parse_compilation_unit( + let mut compilation_unit = get_compilation_unit( " fn main() let mut x = 4 x = \"Hello\" end ", - ) - .unwrap(); + )?; let mut symbol_table = SymbolTable::new(); let mut types_table = TypesTable::new(); compile_up_to_type_check(&mut compilation_unit, &mut symbol_table, &mut types_table)?; @@ -297,7 +296,7 @@ mod tests { #[test] fn finds_no_l_value() -> Result<(), Vec> { - let mut compilation_unit = parse_compilation_unit( + let mut compilation_unit = get_compilation_unit( " fn main() 42 = 42 @@ -317,7 +316,7 @@ mod tests { #[test] fn finds_immutable_destination() -> Result<(), Vec> { - let mut compilation_unit = parse_compilation_unit( + let mut compilation_unit = get_compilation_unit( " fn main() let x = 42 diff --git a/dmc-lib/src/ast/type_use.rs b/dmc-lib/src/ast/type_use.rs index 9ca5940..7adee34 100644 --- a/dmc-lib/src/ast/type_use.rs +++ b/dmc-lib/src/ast/type_use.rs @@ -174,13 +174,13 @@ impl TypeUse { #[cfg(test)] mod tests { use crate::diagnostic::Diagnostic; - use crate::parser::parse_compilation_unit; + use crate::parser::get_compilation_unit; use crate::symbol_table::SymbolTable; use crate::types_table::TypesTable; #[test] fn type_check_generics() -> Result<(), Vec> { - let mut compilation_unit = parse_compilation_unit( + let mut compilation_unit = get_compilation_unit( " class String end diff --git a/dmc-lib/src/compile_pipeline.rs b/dmc-lib/src/compile_pipeline.rs index 0d17db3..92d4961 100644 --- a/dmc-lib/src/compile_pipeline.rs +++ b/dmc-lib/src/compile_pipeline.rs @@ -14,14 +14,9 @@ fn parse_compilation_units( let mut parse_diagnostics = Vec::new(); let mut compilation_units = HashMap::new(); for (file_name, source) in inputs { - match parse_compilation_unit(source) { - Ok(compilation_unit) => { - compilation_units.insert(file_name.clone(), compilation_unit); - } - Err(mut ds) => { - parse_diagnostics.append(&mut ds); - } - } + let (compilation_unit, mut ds) = parse_compilation_unit(source); + parse_diagnostics.append(&mut ds); + compilation_units.insert(file_name.clone(), compilation_unit); } if parse_diagnostics.is_empty() { Ok(compilation_units) diff --git a/dmc-lib/src/ir/ir_block.rs b/dmc-lib/src/ir/ir_block.rs index 9d3f25c..684a5bc 100644 --- a/dmc-lib/src/ir/ir_block.rs +++ b/dmc-lib/src/ir/ir_block.rs @@ -124,13 +124,13 @@ impl Display for IrBlock { mod tests { use crate::diagnostic::Diagnostic; use crate::offset_counter::OffsetCounter; - use crate::parser::parse_compilation_unit; + use crate::parser::get_compilation_unit; use crate::symbol_table::SymbolTable; use crate::types_table::TypesTable; #[test] fn overlapping_assignments_bug_when_k_2() -> Result<(), Vec> { - let mut compilation_unit = parse_compilation_unit( + let mut compilation_unit = get_compilation_unit( " fn main() let a = 1 diff --git a/dmc-lib/src/parser.rs b/dmc-lib/src/parser.rs index ab0e46b..9bc5941 100644 --- a/dmc-lib/src/parser.rs +++ b/dmc-lib/src/parser.rs @@ -24,27 +24,44 @@ use crate::error_codes::{LEXER_ERROR, PARSE_ERROR}; use crate::lexer::{Lexer, LexerErrorKind}; use crate::source_range::SourceRange; use crate::token::{Token, TokenKind}; -use crate::{handle_diagnostics, ok_or_err_diagnostics}; use std::str::FromStr; -pub type ParseResult = Result; +pub type ParseResult = (T, Diagnostics); + +pub fn get_compilation_unit(input: &str) -> Result { + let (compilation_unit, diagnostics) = parse_compilation_unit(input); + if diagnostics.is_empty() { + Ok(compilation_unit) + } else { + Err(diagnostics) + } +} pub fn parse_compilation_unit(input: &str) -> ParseResult { let mut parser = Parser::new(input); - parser.advance()?; // get started - parser.compilation_unit() + let mut diagnostics = Vec::new(); + diagnostics.append(&mut parser.advance()); + let (compilation_unit, mut ds) = parser.compilation_unit(); + diagnostics.append(&mut ds); + (compilation_unit, diagnostics) } pub fn parse_expression(input: &str) -> ParseResult { let mut parser = Parser::new(input); - parser.advance()?; // get started - parser.expression() + let mut diagnostics = Vec::new(); + diagnostics.append(&mut parser.advance()); + let (expression, mut ds) = parser.expression(); + diagnostics.append(&mut ds); + (expression, diagnostics) } -pub fn parse_let_statement(input: &str) -> ParseResult { +pub fn parse_let_statement(input: &str) -> ParseResult> { let mut parser = Parser::new(input); - parser.advance()?; - parser.let_statement() + let mut diagnostics = Vec::new(); + diagnostics.append(&mut parser.advance()); + let (let_statement, mut ds) = parser.let_statement(); + diagnostics.append(&mut ds); + (let_statement, diagnostics) } macro_rules! matches_expression_first { @@ -79,6 +96,7 @@ struct Parser<'a> { lexer: Lexer<'a>, current: Option, lookahead: Option, + node_index: usize, } impl<'a> Parser<'a> { @@ -88,12 +106,15 @@ impl<'a> Parser<'a> { lexer: Lexer::new(input), current: None, lookahead: None, + node_index: 0, } } - fn advance_until(&mut self, token_kinds: &[TokenKind]) { + #[must_use] + fn advance_until(&mut self, token_kinds: &[TokenKind]) -> Diagnostics { + let mut diagnostics = Vec::new(); while self.current.is_some() { - self.advance(); + diagnostics.append(&mut self.advance()); match &self.current { None => { // reached eoi @@ -105,10 +126,13 @@ impl<'a> Parser<'a> { } } } + diagnostics } - fn advance(&mut self) -> Result<(), Diagnostics> { - fn fetch(lexer: &mut Lexer) -> Result, Diagnostics> { + #[must_use] + fn advance(&mut self) -> Diagnostics { + #[must_use] + fn fetch(lexer: &mut Lexer) -> (Option, Diagnostics) { let mut diagnostics = vec![]; let mut maybe_token: Option = None; while let Some(lexer_result) = lexer.next() { @@ -136,24 +160,32 @@ impl<'a> Parser<'a> { } } } - ok_or_err_diagnostics!(maybe_token, diagnostics) + (maybe_token, diagnostics) } + let mut diagnostics = Vec::new(); + if self.lookahead.is_some() { // we've advanced at least once self.current = self.lookahead.take(); - self.lookahead = fetch(&mut self.lexer)?; - Ok(()) + let (lookahead, mut ds) = fetch(&mut self.lexer); + self.lookahead = lookahead; + diagnostics.append(&mut ds); } else if self.lookahead.is_none() && self.current.is_some() { // we're on the last token self.current = None; - Ok(()) } else { // we've not yet advanced, so fetch both - self.current = fetch(&mut self.lexer)?; - self.lookahead = fetch(&mut self.lexer)?; - Ok(()) + let (current, mut ds) = fetch(&mut self.lexer); + self.current = current; + diagnostics.append(&mut ds); + + let (lookahead, mut ds) = fetch(&mut self.lexer); + self.lookahead = lookahead; + diagnostics.append(&mut ds); } + + diagnostics } fn join_kinds(kinds: &[TokenKind]) -> String { @@ -180,44 +212,57 @@ impl<'a> Parser<'a> { .with_primary_label_message(&format!("Expected {}.", Self::join_kinds(kinds))) } - fn expect_advance(&mut self, token_kind: TokenKind) -> Result { + fn expect_advance(&mut self, token_kind: TokenKind) -> (Option, Diagnostics) { match self.current.take() { - None => Err(vec![Self::get_expected_but_found_eoi( - &[token_kind], - self.input.len(), - )]), + None => ( + None, + vec![Self::get_expected_but_found_eoi( + &[token_kind], + self.input.len(), + )], + ), Some(token) => { + let mut diagnostics = Vec::new(); if token.kind() == token_kind { - self.advance()?; - Ok(token) + diagnostics.append(&mut self.advance()); + (Some(token), diagnostics) } else { - self.advance_until(&[token_kind]); - Err(vec![Self::get_expected_but_found(&[token_kind], &token)]) + ( + None, + vec![Self::get_expected_but_found(&[token_kind], &token)], + ) } } } } + #[must_use] fn expect_immediately_after_advance( &mut self, token_kind: TokenKind, previous_token: &Token, - ) -> Result { - let matched = self.expect_advance(token_kind)?; - if matched.start() == previous_token.end() { - Ok(matched) - } else { - Err(vec![ - Diagnostic::new( - &format!( - "Expected {:?} immediately after previous token.", - token_kind - ), - matched.start(), - matched.end(), - ) - .with_error_code(PARSE_ERROR), - ]) + ) -> (Option, Diagnostics) { + let (maybe_matched, mut diagnostics) = self.expect_advance(token_kind); + match maybe_matched { + None => (None, diagnostics), + Some(matched) => { + if matched.start() == previous_token.end() { + (Some(matched), diagnostics) + } else { + diagnostics.push( + Diagnostic::new( + &format!( + "Expected {:?} immediately after previous token.", + token_kind + ), + matched.start(), + matched.end(), + ) + .with_error_code(PARSE_ERROR), + ); + (None, diagnostics) + } + } } } @@ -245,7 +290,7 @@ impl<'a> Parser<'a> { self.sample_input(token.start(), token.end()) } - fn compilation_unit(&mut self) -> Result> { + fn compilation_unit(&mut self) -> ParseResult { let mut functions: Vec = vec![]; let mut extern_functions: Vec = vec![]; let mut classes: Vec = vec![]; @@ -256,28 +301,30 @@ impl<'a> Parser<'a> { let current = self.get_current(); match current.kind() { TokenKind::Fn | TokenKind::Extern | TokenKind::Class => { - handle_diagnostics!( - self.module_level_declaration( - &mut functions, - &mut extern_functions, - &mut classes - ), - diagnostics + let (_, mut ds) = self.module_level_declaration( + &mut functions, + &mut extern_functions, + &mut classes, ); + diagnostics.append(&mut ds); } _ => { diagnostics.push(Self::get_expected_but_found( &[TokenKind::Fn, TokenKind::Extern, TokenKind::Class], current, )); - self.advance_until(&[TokenKind::Fn, TokenKind::Extern, TokenKind::Class]); + diagnostics.append(&mut self.advance_until(&[ + TokenKind::Fn, + TokenKind::Extern, + TokenKind::Class, + ])); } } } - ok_or_err_diagnostics!( + ( CompilationUnit::new(functions, extern_functions, classes), - diagnostics + diagnostics, ) } @@ -286,332 +333,405 @@ impl<'a> Parser<'a> { functions: &mut Vec, extern_functions: &mut Vec, classes: &mut Vec, - ) -> Result<(), Vec> { + ) -> ParseResult<()> { + let mut diagnostics = Vec::new(); let current = self.get_current(); match current.kind() { TokenKind::Fn => { - let function_result = self.function(); - match function_result { - Ok(function) => { - functions.push(function); - Ok(()) - } - Err(function_diagnostics) => Err(function_diagnostics), + let (maybe_function, mut ds) = self.function(); + diagnostics.append(&mut ds); + if let Some(function) = maybe_function { + functions.push(function); } } TokenKind::Extern => { - let extern_function_result = self.extern_function(); - match extern_function_result { - Ok(extern_function) => { - extern_functions.push(extern_function); - Ok(()) - } - Err(extern_function_diagnostics) => Err(extern_function_diagnostics), + let (maybe_extern_function, mut ds) = self.extern_function(); + diagnostics.append(&mut ds); + if let Some(extern_function) = maybe_extern_function { + extern_functions.push(extern_function); } } - TokenKind::Class => match self.class() { - Ok(class) => { + TokenKind::Class => { + let (maybe_class, mut ds) = self.class(); + diagnostics.append(&mut ds); + if let Some(class) = maybe_class { classes.push(class); - Ok(()) } - Err(class_diagnostics) => Err(class_diagnostics), - }, + } _ => unreachable!(), } + + ((), diagnostics) } - fn function(&mut self) -> Result> { + fn function(&mut self) -> ParseResult> { + let mut diagnostics = Vec::new(); + let is_public = if self.current.is_some() && self.peek_current(TokenKind::Public) { - self.advance()?; // pub + diagnostics.append(&mut self.advance()); // pub true } else { false }; - self.expect_advance(TokenKind::Fn)?; - let identifier_token = self.expect_advance(TokenKind::Identifier)?; + let (_, mut ds) = self.expect_advance(TokenKind::Fn); + diagnostics.append(&mut ds); - self.expect_advance(TokenKind::LeftParentheses)?; - let parameters = self.parameter_list()?; - self.expect_advance(TokenKind::RightParentheses)?; + let (maybe_identifier, mut ds) = self.expect_advance(TokenKind::Identifier); + diagnostics.append(&mut ds); - let mut diagnostics = vec![]; + let (_, mut ds) = self.expect_advance(TokenKind::LeftParentheses); + diagnostics.append(&mut ds); + + let (parameters, mut ds) = self.parameter_list(); + diagnostics.append(&mut ds); + + let (_, mut ds) = self.expect_advance(TokenKind::RightParentheses); + diagnostics.append(&mut ds); let return_type = if self.current.is_some() && self.peek_current(TokenKind::RightArrow) { - match self.return_type() { - Ok(type_use) => Some(type_use), - Err(mut return_type_diagnostics) => { - diagnostics.append(&mut return_type_diagnostics); - None - } - } + let (maybe_type_use, mut ds) = self.return_type(); + diagnostics.append(&mut ds); + maybe_type_use } else { None }; let mut statements = vec![]; while self.current.is_some() && !self.peek_current(TokenKind::End) { - let statement_result = self.statement(); - match statement_result { - Ok(statement) => { - statements.push(statement); - } - Err(mut statement_diagnostics) => { - diagnostics.append(&mut statement_diagnostics); - } + let (maybe_statement, mut ds) = self.statement(); + diagnostics.append(&mut ds); + if let Some(statement) = maybe_statement { + statements.push(statement); } } - // if we're missing "end", append it to the other statement diagnostics - let end_result = self.expect_advance(TokenKind::End); - match end_result { - Err(mut end_diagnostics) => { - diagnostics.append(&mut end_diagnostics); - } - _ => {} - } + let (_, mut ds) = self.expect_advance(TokenKind::End); + diagnostics.append(&mut ds); - ok_or_err_diagnostics!( - Function::new( - self.token_text(&identifier_token), - SourceRange::new(identifier_token.start(), identifier_token.end()), + if let Some(identifier) = maybe_identifier { + let function = Function::new( + self.token_text(&identifier), + SourceRange::new(identifier.start(), identifier.end()), is_public, parameters, return_type, statements, - ), - diagnostics - ) + ); + (Some(function), diagnostics) + } else { + (None, diagnostics) + } } - fn extern_function(&mut self) -> Result> { - self.expect_advance(TokenKind::Extern)?; - self.expect_advance(TokenKind::Fn)?; - let identifier_token = self.expect_advance(TokenKind::Identifier)?; - self.expect_advance(TokenKind::LeftParentheses)?; + fn extern_function(&mut self) -> ParseResult> { + let mut diagnostics = Vec::new(); - let mut diagnostics = vec![]; + let (_, mut ds) = self.expect_advance(TokenKind::Extern); + diagnostics.append(&mut ds); - let mut maybe_parameters: Option> = None; - let params_result = self.parameter_list(); - match params_result { - Ok(parameters) => { - maybe_parameters = Some(parameters); - } - Err(mut parameter_list_diagnostics) => { - diagnostics.append(&mut parameter_list_diagnostics); - } + let (_, mut ds) = self.expect_advance(TokenKind::Fn); + diagnostics.append(&mut ds); + + let (maybe_identifier, mut ds) = self.expect_advance(TokenKind::Identifier); + diagnostics.append(&mut ds); + + let (_, mut ds) = self.expect_advance(TokenKind::LeftParentheses); + diagnostics.append(&mut ds); + + let (parameters, mut ds) = self.parameter_list(); + diagnostics.append(&mut ds); + + let (_, mut ds) = self.expect_advance(TokenKind::RightParentheses); + diagnostics.append(&mut ds); + + let (return_type, mut ds) = self.return_type(); + diagnostics.append(&mut ds); + + if let Some(identifier) = maybe_identifier + && let Some(type_use) = return_type + { + let extern_function = ExternFunction::new( + self.token_text(&identifier), + SourceRange::new(identifier.start(), identifier.end()), + parameters, + type_use, + ); + (Some(extern_function), diagnostics) + } else { + (None, diagnostics) } - - let right_parentheses_result = self.expect_advance(TokenKind::RightParentheses); - match right_parentheses_result { - Err(mut right_parentheses_diagnostics) => { - diagnostics.append(&mut right_parentheses_diagnostics); - } - Ok(_) => {} - } - - let return_type = self.return_type()?; - - ok_or_err_diagnostics!( - ExternFunction::new( - self.token_text(&identifier_token), - SourceRange::new(identifier_token.start(), identifier_token.end()), - maybe_parameters.unwrap(), - return_type, - ), - diagnostics - ) } - fn class(&mut self) -> Result> { - self.expect_advance(TokenKind::Class)?; - let identifier_token = self.expect_advance(TokenKind::Identifier)?; - let mut generic_parameters: Vec = vec![]; + fn class(&mut self) -> ParseResult> { + let mut diagnostics = Vec::new(); + + let (_, mut ds) = self.expect_advance(TokenKind::Class); + diagnostics.append(&mut ds); + + let (maybe_identifier, mut ds) = self.expect_advance(TokenKind::Identifier); + diagnostics.append(&mut ds); + + let generic_parameters: Vec = + if self.current.is_some() && self.peek_current(TokenKind::Lt) { + let (gps, mut ds) = self.generic_parameters(); + diagnostics.append(&mut ds); + gps + } else { + Vec::new() + }; + let mut fields = vec![]; let mut functions = vec![]; let mut maybe_constructor: Option = None; - let mut diagnostics = vec![]; - while self.current.is_some() && !self.peek_current(TokenKind::End) { match self.get_current().kind() { - TokenKind::Public => match self.public_class_member( - &mut fields, - &mut functions, - &mut maybe_constructor, - ) { - Ok(_) => {} - Err(mut member_diagnostics) => diagnostics.append(&mut member_diagnostics), - }, - TokenKind::Mut | TokenKind::Identifier => match self.field() { - Ok(field) => fields.push(field), - Err(mut field_diagnostics) => diagnostics.append(&mut field_diagnostics), - }, - TokenKind::Fn => match self.function() { - Ok(function) => functions.push(function), - Err(mut function_diagnostics) => diagnostics.append(&mut function_diagnostics), - }, - TokenKind::Ctor => match self.constructor() { - Ok(constructor) => { + TokenKind::Public => { + let (_, mut ds) = self.public_class_member( + &mut fields, + &mut functions, + &mut maybe_constructor, + ); + diagnostics.append(&mut ds); + } + TokenKind::Mut | TokenKind::Identifier => { + let (maybe_field, mut ds) = self.field(); + diagnostics.append(&mut ds); + if let Some(field) = maybe_field { + fields.push(field); + } + } + TokenKind::Fn => { + let (maybe_function, mut ds) = self.function(); + diagnostics.append(&mut ds); + if let Some(function) = maybe_function { + functions.push(function); + } + } + TokenKind::Ctor => { + let (constructor, mut ds) = self.constructor(); + diagnostics.append(&mut ds); + if let Some(constructor) = constructor { maybe_constructor = Some(constructor); } - Err(mut ctor_diagnostics) => diagnostics.append(&mut ctor_diagnostics), - }, - TokenKind::Lt => match self.generic_parameters() { - Ok(parsed_params) => { - generic_parameters = parsed_params; - } - Err(mut generic_parameters_diagnostics) => { - diagnostics.append(&mut generic_parameters_diagnostics); - } - }, + } _ => unreachable!(), } } - self.expect_advance(TokenKind::End)?; + let (_, mut ds) = self.expect_advance(TokenKind::End); + diagnostics.append(&mut ds); - ok_or_err_diagnostics!( - Class::new( - self.token_text(&identifier_token), - SourceRange::new(identifier_token.start(), identifier_token.end()), + if let Some(identifier) = maybe_identifier { + let class = Class::new( + self.token_text(&identifier), + SourceRange::new(identifier.start(), identifier.end()), generic_parameters, maybe_constructor, fields, functions, - ), - diagnostics - ) + ); + (Some(class), diagnostics) + } else { + (None, diagnostics) + } } - fn parameter_list(&mut self) -> Result, Vec> { + fn parameter_list(&mut self) -> ParseResult> { let mut parameters = vec![]; let mut diagnostics = vec![]; while self.current.is_some() && self.peek_current(TokenKind::Identifier) { - let parameter_result = self.parameter(); - match parameter_result { - Ok(parameter) => { - parameters.push(parameter); - } - Err(mut parameter_diagnostics) => { - diagnostics.append(&mut parameter_diagnostics); - } + let (maybe_parameter, mut ds) = self.parameter(); + diagnostics.append(&mut ds); + if let Some(parameter) = maybe_parameter { + parameters.push(parameter); } + if self.current.is_some() && self.peek_current(TokenKind::Comma) { - match self.advance() { - Ok(_) => {} - Err(mut ds) => { - diagnostics.append(&mut ds); - } - }; + diagnostics.append(&mut self.advance()); } } - ok_or_err_diagnostics!(parameters, diagnostics) + + (parameters, diagnostics) } - fn parameter(&mut self) -> Result> { - let identifier_token = self.expect_advance(TokenKind::Identifier)?; - self.expect_advance(TokenKind::Colon)?; - let type_use = self.type_use()?; - Ok(Parameter::new( - self.token_text(&identifier_token), - SourceRange::new(identifier_token.start(), identifier_token.end()), - type_use, - )) + fn parameter(&mut self) -> ParseResult> { + let mut diagnostics = Vec::new(); + + let (maybe_identifier, mut ds) = self.expect_advance(TokenKind::Identifier); + diagnostics.append(&mut ds); + + let (_, mut ds) = self.expect_advance(TokenKind::Colon); + diagnostics.append(&mut ds); + + let (maybe_type_use, mut ds) = self.type_use(); + diagnostics.append(&mut ds); + + if let Some(identifier) = maybe_identifier + && let Some(type_use) = maybe_type_use + { + let parameter = Parameter::new( + self.token_text(&identifier), + SourceRange::new(identifier.start(), identifier.end()), + type_use, + ); + (Some(parameter), diagnostics) + } else { + (None, diagnostics) + } } - fn return_type(&mut self) -> Result> { - self.expect_advance(TokenKind::RightArrow)?; - self.type_use() + fn return_type(&mut self) -> ParseResult> { + let mut diagnostics = Vec::new(); + let (_, mut ds) = self.expect_advance(TokenKind::RightArrow); + diagnostics.append(&mut ds); + let (maybe_type_use, mut ds) = self.type_use(); + diagnostics.append(&mut ds); + (maybe_type_use, diagnostics) } - fn type_use(&mut self) -> Result> { + fn type_use(&mut self) -> ParseResult> { + let mut diagnostics = Vec::new(); + if self.current.is_some() { let current = self.get_current(); return match current.kind() { TokenKind::LeftSquare => { - self.advance()?; // [ - let inner_type_use = self.type_use()?; - self.expect_advance(TokenKind::RightSquare)?; + diagnostics.append(&mut self.advance()); // [ + let (inner_type_use, mut ds) = self.type_use(); + diagnostics.append(&mut ds); + + let (_, mut ds) = self.expect_advance(TokenKind::RightSquare); + diagnostics.append(&mut ds); + todo!() } TokenKind::Identifier => { - let identifier_token = self.expect_advance(TokenKind::Identifier)?; + let (maybe_identifier, mut ds) = self.expect_advance(TokenKind::Identifier); + diagnostics.append(&mut ds); + let generic_arguments = if self.current.is_some() && self.peek_current(TokenKind::Lt) { - self.advance()?; // < - let generic_arguments = self.generic_arguments_list()?; - self.expect_advance(TokenKind::Gt)?; // > + diagnostics.append(&mut self.advance()); // < + let (generic_arguments, mut ds) = self.generic_arguments_list(); + diagnostics.append(&mut ds); + + let (_, mut ds) = self.expect_advance(TokenKind::Gt); // > + diagnostics.append(&mut ds); + generic_arguments } else { vec![] }; - Ok(TypeUse::new( - self.token_text(&identifier_token), - SourceRange::new(identifier_token.start(), identifier_token.end()), - generic_arguments, - )) + + if let Some(identifier) = maybe_identifier { + let type_use = TypeUse::new( + self.token_text(&identifier), + SourceRange::new(identifier.start(), identifier.end()), + generic_arguments, + ); + (Some(type_use), diagnostics) + } else { + (None, diagnostics) + } + } + _ => { + diagnostics.push(Self::get_expected_but_found( + &[TokenKind::LeftSquare, TokenKind::Identifier], + current, + )); + (None, diagnostics) } - _ => Err(vec![Self::get_expected_but_found( - &[TokenKind::LeftSquare, TokenKind::Identifier], - current, - )]), }; } - Err(vec![Self::get_expected_but_found_eoi( + diagnostics.push(Self::get_expected_but_found_eoi( &[TokenKind::LeftSquare, TokenKind::Identifier], self.input.len(), - )]) + )); + (None, diagnostics) } - fn generic_arguments_list(&mut self) -> Result, Vec> { + fn generic_arguments_list(&mut self) -> ParseResult> { + let mut diagnostics = Vec::new(); let mut generic_arguments: Vec = vec![]; + while self.current.is_some() && matches_type_use_first!(self.get_current().kind()) { - generic_arguments.push(self.type_use()?); + let (type_use, mut ds) = self.type_use(); + diagnostics.append(&mut ds); + if let Some(type_use) = type_use { + generic_arguments.push(type_use); + } + if self.current.is_some() && self.peek_current(TokenKind::Comma) { - self.advance()?; // comma + diagnostics.append(&mut self.advance()); // comma } else { break; } } - Ok(generic_arguments) + + (generic_arguments, diagnostics) } - fn generic_parameters(&mut self) -> Result, Vec> { - self.expect_advance(TokenKind::Lt)?; + fn generic_parameters(&mut self) -> ParseResult> { + let mut diagnostics = Vec::new(); + + let (_, mut ds) = self.expect_advance(TokenKind::Lt); + diagnostics.append(&mut ds); + let mut parameters: Vec = vec![]; while self.current.is_some() && self.peek_current(TokenKind::Identifier) { - parameters.push(self.generic_parameter()?); + let (maybe_generic_parameter, mut ds) = self.generic_parameter(); + diagnostics.append(&mut ds); + if let Some(generic_parameter) = maybe_generic_parameter { + parameters.push(generic_parameter); + } + if self.current.is_some() && self.peek_current(TokenKind::Plus) { - self.advance()?; // + + diagnostics.append(&mut self.advance()); // + } else { break; } } - self.expect_advance(TokenKind::Gt)?; - Ok(parameters) + let (_, mut ds) = self.expect_advance(TokenKind::Gt); + diagnostics.append(&mut ds); + + (parameters, diagnostics) } - fn generic_parameter(&mut self) -> Result> { - let identifier = self.expect_advance(TokenKind::Identifier)?; + fn generic_parameter(&mut self) -> ParseResult> { + let mut diagnostics = Vec::new(); + let (identifier, mut ds) = self.expect_advance(TokenKind::Identifier); + diagnostics.append(&mut ds); + let mut extends_list: Vec = vec![]; if self.current.is_some() && self.peek_current(TokenKind::Colon) { - self.advance()?; // : + diagnostics.append(&mut self.advance()); // : while self.current.is_some() && matches_type_use_first!(self.get_current().kind()) { - extends_list.push(self.type_use()?); + let (maybe_type_use, mut ds) = self.type_use(); + diagnostics.append(&mut ds); + if let Some(type_use) = maybe_type_use { + extends_list.push(type_use); + } + if self.current.is_some() && self.peek_current(TokenKind::Comma) { - self.advance()?; // , + diagnostics.append(&mut self.advance()); // , } else { break; } } } - Ok(GenericParameter::new( - self.token_text(&identifier), - SourceRange::new(identifier.start(), identifier.end()), - extends_list, - )) + + if let Some(identifier) = identifier { + let generic_parameter = GenericParameter::new( + self.token_text(&identifier), + SourceRange::new(identifier.start(), identifier.end()), + extends_list, + ); + (Some(generic_parameter), diagnostics) + } else { + (None, diagnostics) + } } fn public_class_member( @@ -619,52 +739,76 @@ impl<'a> Parser<'a> { fields: &mut Vec, functions: &mut Vec, maybe_ctor: &mut Option, - ) -> Result<(), Vec> { + ) -> ParseResult<()> { + let mut diagnostics = Vec::new(); if self.lookahead.is_some() { match self.lookahead.as_ref().unwrap().kind() { TokenKind::Mut | TokenKind::Identifier => { - fields.push(self.field()?); + let (maybe_field, mut ds) = self.field(); + diagnostics.append(&mut ds); + if let Some(field) = maybe_field { + fields.push(field); + } + } + TokenKind::Fn => { + let (maybe_function, mut ds) = self.function(); + diagnostics.append(&mut ds); + if let Some(function) = maybe_function { + functions.push(function); + } } - TokenKind::Fn => functions.push(self.function()?), TokenKind::Ctor => { - maybe_ctor.replace(self.constructor()?); + let (ctor, mut ds) = self.constructor(); + diagnostics.append(&mut ds); + if let Some(ctor) = ctor { + maybe_ctor.replace(ctor); + } } _ => { let lookahead = self.lookahead.as_ref().unwrap(); - return Err(vec![Self::get_expected_but_found( + diagnostics.push(Self::get_expected_but_found( &[TokenKind::Mut, TokenKind::Identifier, TokenKind::Fn], lookahead, - )]); + )); } } - Ok(()) } else { let current = self.current.as_ref().unwrap(); - Err(vec![Self::get_expected_but_found( + diagnostics.push(Self::get_expected_but_found( &[TokenKind::Mut, TokenKind::Identifier, TokenKind::Fn], current, - )]) + )); } + + ((), diagnostics) } - fn constructor(&mut self) -> Result> { + fn constructor(&mut self) -> ParseResult> { + let mut diagnostics = Vec::new(); + let is_public = if self.current.is_some() && self.peek_current(TokenKind::Public) { - self.advance()?; + diagnostics.append(&mut self.advance()); true } else { false }; - let ctor_keyword = self.expect_advance(TokenKind::Ctor)?; - self.expect_advance(TokenKind::LeftParentheses)?; + let (ctor_keyword, mut ds) = self.expect_advance(TokenKind::Ctor); + diagnostics.append(&mut ds); + + let (_, mut ds) = self.expect_advance(TokenKind::LeftParentheses); + diagnostics.append(&mut ds); let parameters = if self.current.is_some() && self.peek_current(TokenKind::Identifier) { - self.parameter_list()? + let (parameters, mut ds) = self.parameter_list(); + diagnostics.append(&mut ds); + parameters } else { vec![] }; - self.expect_advance(TokenKind::RightParentheses)?; + let (_, mut ds) = self.expect_advance(TokenKind::RightParentheses); + diagnostics.append(&mut ds); // statements let mut statements: Vec = vec![]; @@ -673,184 +817,256 @@ impl<'a> Parser<'a> { while self.current.is_some() && matches_statement_first!(self.current.as_ref().unwrap().kind()) { - match self.statement() { - Ok(statement) => { - statements.push(statement); - } - Err(mut statement_diagnostics) => { - diagnostics.append(&mut statement_diagnostics); - } + let (maybe_statement, mut ds) = self.statement(); + diagnostics.append(&mut ds); + if let Some(statement) = maybe_statement { + statements.push(statement); } } - self.expect_advance(TokenKind::End)?; + let (_, mut ds) = self.expect_advance(TokenKind::End); + diagnostics.append(&mut ds); - if diagnostics.is_empty() { - Ok(Constructor::new( + if let Some(ctor_keyword) = ctor_keyword { + let constructor = Constructor::new( is_public, SourceRange::new(ctor_keyword.start(), ctor_keyword.end()), parameters, statements, - )) + ); + (Some(constructor), diagnostics) } else { - Err(diagnostics) + (None, diagnostics) } } - fn field(&mut self) -> Result> { + fn field(&mut self) -> ParseResult> { + let mut diagnostics = Vec::new(); + let is_public = if self.current.is_some() && self.peek_current(TokenKind::Public) { - self.advance()?; + diagnostics.append(&mut self.advance()); true } else { false }; let is_mut = if self.current.is_some() && self.peek_current(TokenKind::Mut) { - self.advance()?; + diagnostics.append(&mut self.advance()); true } else { false }; - let identifier = self.expect_advance(TokenKind::Identifier)?; + let (identifier, mut ds) = self.expect_advance(TokenKind::Identifier); + diagnostics.append(&mut ds); let declared_type = if self.current.is_some() && self.peek_current(TokenKind::Colon) { - self.advance()?; // colon - Some(self.type_use()?) + diagnostics.append(&mut self.advance()); // colon + let (type_use, mut ds) = self.type_use(); + diagnostics.append(&mut ds); + type_use } else { None }; let initializer = if self.current.is_some() && self.peek_current(TokenKind::Equals) { - self.advance()?; // equals - Some(self.expression()?) + diagnostics.append(&mut self.advance()); // equals + let (expression, mut ds) = self.expression(); + diagnostics.append(&mut ds); + Some(expression) } else { None }; - Ok(Field::new( - self.token_text(&identifier), - SourceRange::new(identifier.start(), identifier.end()), - is_public, - is_mut, - declared_type, - initializer, - )) - } - - fn statement(&mut self) -> Result> { - let current = self.get_current(); - match current.kind() { - TokenKind::Let => Ok(Statement::Let(self.let_statement()?)), - _ => self.expression_statement_or_assign_statement(), + if let Some(identifier) = identifier { + let field = Field::new( + self.token_text(&identifier), + SourceRange::new(identifier.start(), identifier.end()), + is_public, + is_mut, + declared_type, + initializer, + ); + (Some(field), diagnostics) + } else { + (None, diagnostics) } } - fn let_statement(&mut self) -> Result> { - self.expect_advance(TokenKind::Let)?; + fn statement(&mut self) -> ParseResult> { + let current = self.get_current(); + match current.kind() { + TokenKind::Let => { + let (maybe_let_statement, diagnostics) = self.let_statement(); + match maybe_let_statement { + None => (None, diagnostics), + Some(let_statement) => (Some(Statement::Let(let_statement)), diagnostics), + } + } + _ => { + let (statement, diagnostics) = self.expression_statement_or_assign_statement(); + (Some(statement), diagnostics) + } + } + } + + fn let_statement(&mut self) -> ParseResult> { + let mut diagnostics = Vec::new(); + + let (_, mut ds) = self.expect_advance(TokenKind::Let); + diagnostics.append(&mut ds); let is_mut = if self.current.is_some() && self.peek_current(TokenKind::Mut) { - self.advance()?; + diagnostics.append(&mut self.advance()); true } else { false }; - let identifier = self.expect_advance(TokenKind::Identifier)?; - self.expect_advance(TokenKind::Equals)?; - let expression = self.expression()?; - Ok(LetStatement::new( - self.token_text(&identifier), - SourceRange::new(identifier.start(), identifier.end()), - is_mut, - expression, - )) - } + let (maybe_identifier, mut ds) = self.expect_advance(TokenKind::Identifier); + diagnostics.append(&mut ds); - fn expression_statement_or_assign_statement(&mut self) -> Result> { - let base = self.expression()?; - if self.current.is_some() && self.peek_current(TokenKind::Equals) { - Ok(Statement::Assign(self.assign_rhs(base)?)) + let (_, mut ds) = self.expect_advance(TokenKind::Equals); + diagnostics.append(&mut ds); + + let (expression, mut ds) = self.expression(); + diagnostics.append(&mut ds); + + if let Some(identifier) = maybe_identifier { + let let_statement = LetStatement::new( + self.token_text(&identifier), + SourceRange::new(identifier.start(), identifier.end()), + is_mut, + expression, + ); + (Some(let_statement), diagnostics) } else { - Ok(Statement::Expression(ExpressionStatement::new(base))) + (None, diagnostics) } } - fn assign_rhs(&mut self, destination: Expression) -> Result> { - self.expect_advance(TokenKind::Equals)?; - let value = self.expression()?; - Ok(AssignStatement::new(destination, value)) + fn expression_statement_or_assign_statement(&mut self) -> ParseResult { + let mut diagnostics = Vec::new(); + let (base, mut ds) = self.expression(); + diagnostics.append(&mut ds); + + if self.current.is_some() && self.peek_current(TokenKind::Equals) { + let (assign_statement, mut ds) = self.assign_rhs(base); + diagnostics.append(&mut ds); + (Statement::Assign(assign_statement), diagnostics) + } else { + ( + Statement::Expression(ExpressionStatement::new(base)), + diagnostics, + ) + } } - fn expression(&mut self) -> Result> { + fn assign_rhs(&mut self, destination: Expression) -> ParseResult { + let mut diagnostics = Vec::new(); + let (_, mut ds) = self.expect_advance(TokenKind::Equals); + diagnostics.append(&mut ds); + + let (value, mut ds) = self.expression(); + diagnostics.append(&mut ds); + + (AssignStatement::new(destination, value), diagnostics) + } + + fn expression(&mut self) -> ParseResult { self.bitwise_or_expression() } - fn bitwise_or_expression(&mut self) -> Result> { - let mut result = self.bitwise_xor_expression()?; + fn bitwise_or_expression(&mut self) -> ParseResult { + let mut diagnostics = Vec::new(); + + let (mut base, mut ds) = self.bitwise_xor_expression(); + diagnostics.append(&mut ds); + while self.current.is_some() && self.peek_current(TokenKind::Bar) { - self.advance()?; // | - let rhs = self.bitwise_xor_expression()?; + diagnostics.append(&mut self.advance()); // | + let (rhs, mut ds) = self.bitwise_xor_expression(); + diagnostics.append(&mut ds); let source_range = - SourceRange::new(result.source_range().start(), rhs.source_range().end()); - result = Expression::Binary(BinaryExpression::new( - result, + SourceRange::new(base.source_range().start(), rhs.source_range().end()); + base = Expression::Binary(BinaryExpression::new( + base, rhs, BinaryOperation::BitwiseOr, source_range, )); } - Ok(result) + (base, diagnostics) } - fn bitwise_xor_expression(&mut self) -> Result> { - let mut result = self.bitwise_and_expression()?; + fn bitwise_xor_expression(&mut self) -> ParseResult { + let mut diagnostics = Vec::new(); + + let (mut base, mut ds) = self.bitwise_and_expression(); + diagnostics.append(&mut ds); + while self.current.is_some() && self.peek_current(TokenKind::Caret) { - self.advance()?; // ^ - let rhs = self.bitwise_and_expression()?; + diagnostics.append(&mut self.advance()); // ^ + let (rhs, mut ds) = self.bitwise_and_expression(); + diagnostics.append(&mut ds); let source_range = - SourceRange::new(result.source_range().start(), rhs.source_range().end()); - result = Expression::Binary(BinaryExpression::new( - result, + SourceRange::new(base.source_range().start(), rhs.source_range().end()); + base = Expression::Binary(BinaryExpression::new( + base, rhs, BinaryOperation::BitwiseXor, source_range, )); } - Ok(result) + (base, diagnostics) } - fn bitwise_and_expression(&mut self) -> Result> { - let mut result = self.shift_expression()?; + fn bitwise_and_expression(&mut self) -> ParseResult { + let mut diagnostics = Vec::new(); + + let (mut base, mut ds) = self.shift_expression(); + diagnostics.append(&mut ds); + while self.current.is_some() && self.peek_current(TokenKind::Ampersand) { - self.advance()?; // & - let rhs = self.shift_expression()?; + diagnostics.append(&mut self.advance()); // & + let (rhs, mut ds) = self.shift_expression(); + diagnostics.append(&mut ds); + let source_range = - SourceRange::new(result.source_range().start(), rhs.source_range().end()); - result = Expression::Binary(BinaryExpression::new( - result, + SourceRange::new(base.source_range().start(), rhs.source_range().end()); + base = Expression::Binary(BinaryExpression::new( + base, rhs, BinaryOperation::BitwiseAnd, source_range, )); } - Ok(result) + (base, diagnostics) } - fn shift_expression(&mut self) -> Result> { - let mut result = self.additive_expression()?; + fn shift_expression(&mut self) -> ParseResult { + let mut diagnostics = Vec::new(); + + let (mut base, mut ds) = self.additive_expression(); + diagnostics.append(&mut ds); + while self.current.is_some() { let current = self.get_current(); match current.kind() { TokenKind::Lt => { let previous_cloned = current.clone(); - self.advance()?; // first < - self.expect_immediately_after_advance(TokenKind::Lt, &previous_cloned)?; // second < - let rhs = self.additive_expression()?; + diagnostics.append(&mut self.advance()); // first < + let (_, mut ds) = + self.expect_immediately_after_advance(TokenKind::Lt, &previous_cloned); // second < + diagnostics.append(&mut ds); + + let (rhs, mut ds) = self.additive_expression(); + diagnostics.append(&mut ds); + let source_range = - SourceRange::new(result.source_range().start(), rhs.source_range().end()); - result = Expression::Binary(BinaryExpression::new( - result, + SourceRange::new(base.source_range().start(), rhs.source_range().end()); + base = Expression::Binary(BinaryExpression::new( + base, rhs, BinaryOperation::LeftShift, source_range, @@ -858,13 +1074,18 @@ impl<'a> Parser<'a> { } TokenKind::Gt => { let previous_cloned = current.clone(); - self.advance()?; // first > - self.expect_immediately_after_advance(TokenKind::Gt, &previous_cloned)?; // second gt - let rhs = self.additive_expression()?; + diagnostics.append(&mut self.advance()); // first > + let (_, mut ds) = + self.expect_immediately_after_advance(TokenKind::Gt, &previous_cloned); // second > + diagnostics.append(&mut ds); + + let (rhs, mut ds) = self.additive_expression(); + diagnostics.append(&mut ds); + let source_range = - SourceRange::new(result.source_range().start(), rhs.source_range().end()); - result = Expression::Binary(BinaryExpression::new( - result, + SourceRange::new(base.source_range().start(), rhs.source_range().end()); + base = Expression::Binary(BinaryExpression::new( + base, rhs, BinaryOperation::RightShift, source_range, @@ -873,33 +1094,42 @@ impl<'a> Parser<'a> { _ => break, } } - Ok(result) + + (base, diagnostics) } - fn additive_expression(&mut self) -> Result> { - let mut result = self.multiplicative_expression()?; + fn additive_expression(&mut self) -> ParseResult { + let mut diagnostics = Vec::new(); + + let (mut base, mut ds) = self.multiplicative_expression(); + diagnostics.append(&mut ds); + while self.current.is_some() { let current = self.get_current(); match current.kind() { TokenKind::Plus => { - self.advance()?; // plus - let rhs = self.multiplicative_expression()?; + diagnostics.append(&mut self.advance()); // plus + let (rhs, mut ds) = self.multiplicative_expression(); + diagnostics.append(&mut ds); + let source_range = - SourceRange::new(result.source_range().start(), rhs.source_range().end()); - result = Expression::Binary(BinaryExpression::new( - result, + SourceRange::new(base.source_range().start(), rhs.source_range().end()); + base = Expression::Binary(BinaryExpression::new( + base, rhs, BinaryOperation::Add, source_range, )); } TokenKind::Minus => { - self.advance()?; // minus - let rhs = self.multiplicative_expression()?; + diagnostics.append(&mut self.advance()); // minus + let (rhs, mut ds) = self.multiplicative_expression(); + diagnostics.append(&mut ds); + let source_range = - SourceRange::new(result.source_range().start(), rhs.source_range().end()); - result = Expression::Binary(BinaryExpression::new( - result, + SourceRange::new(base.source_range().start(), rhs.source_range().end()); + base = Expression::Binary(BinaryExpression::new( + base, rhs, BinaryOperation::Subtract, source_range, @@ -908,45 +1138,55 @@ impl<'a> Parser<'a> { _ => break, } } - Ok(result) + (base, diagnostics) } - fn multiplicative_expression(&mut self) -> Result> { - let mut result = self.prefix_expression()?; + fn multiplicative_expression(&mut self) -> ParseResult { + let mut diagnostics = Vec::new(); + + let (mut base, mut ds) = self.prefix_expression(); + diagnostics.append(&mut ds); + while self.current.is_some() { let current = self.get_current(); match current.kind() { TokenKind::Star => { - self.advance()?; // multiply - let rhs = self.prefix_expression()?; + diagnostics.append(&mut self.advance()); // multiply + let (rhs, mut ds) = self.prefix_expression(); + diagnostics.append(&mut ds); + let source_range = - SourceRange::new(result.source_range().start(), rhs.source_range().end()); - result = Expression::Binary(BinaryExpression::new( - result, + SourceRange::new(base.source_range().start(), rhs.source_range().end()); + base = Expression::Binary(BinaryExpression::new( + base, rhs, BinaryOperation::Multiply, source_range, )); } TokenKind::Slash => { - self.advance()?; // slash - let rhs = self.prefix_expression()?; + diagnostics.append(&mut self.advance()); // slash + let (rhs, mut ds) = self.prefix_expression(); + diagnostics.append(&mut ds); + let source_range = - SourceRange::new(result.source_range().start(), rhs.source_range().end()); - result = Expression::Binary(BinaryExpression::new( - result, + SourceRange::new(base.source_range().start(), rhs.source_range().end()); + base = Expression::Binary(BinaryExpression::new( + base, rhs, BinaryOperation::Divide, source_range, )) } TokenKind::Modulo => { - self.advance()?; // modulo - let rhs = self.prefix_expression()?; + diagnostics.append(&mut self.advance()); // modulo + let (rhs, mut ds) = self.prefix_expression(); + diagnostics.append(&mut ds); + let source_range = - SourceRange::new(result.source_range().start(), rhs.source_range().end()); - result = Expression::Binary(BinaryExpression::new( - result, + SourceRange::new(base.source_range().start(), rhs.source_range().end()); + base = Expression::Binary(BinaryExpression::new( + base, rhs, BinaryOperation::Modulo, source_range, @@ -955,10 +1195,12 @@ impl<'a> Parser<'a> { _ => break, } } - Ok(result) + (base, diagnostics) } - fn prefix_expression(&mut self) -> Result> { + fn prefix_expression(&mut self) -> ParseResult { + let mut diagnostics = Vec::new(); + // first, collect all consecutive operators let mut operator_tokens = vec![]; while self.current.is_some() { @@ -966,7 +1208,7 @@ impl<'a> Parser<'a> { match current.kind() { TokenKind::Minus => { operator_tokens.push(current.clone()); // unfortunately necessary - self.advance()?; + diagnostics.append(&mut self.advance()); } _ => break, } @@ -975,99 +1217,138 @@ impl<'a> Parser<'a> { // now go in reverse and build up expressions // the parser is currently just after the prefix operators, so we need a suffix expression // as a base - let mut result = self.suffix_expression()?; + let (mut base, mut ds) = self.suffix_expression(); + diagnostics.append(&mut ds); + while let Some(operator_token) = operator_tokens.pop() { - let source_range = - SourceRange::new(operator_token.start(), result.source_range().end()); + let source_range = SourceRange::new(operator_token.start(), base.source_range().end()); match operator_token.kind() { TokenKind::Minus => { - result = Expression::Negative(NegativeExpression::new(result, source_range)); + base = Expression::Negative(NegativeExpression::new(base, source_range)); } _ => unreachable!(), } } - Ok(result) + (base, diagnostics) } - fn suffix_expression(&mut self) -> Result> { - let mut result = self.expression_base()?; + fn suffix_expression(&mut self) -> ParseResult { + let mut diagnostics = Vec::new(); + + let (mut base, mut ds) = self.expression_base(); + diagnostics.append(&mut ds); + while self.current.is_some() { let current = self.get_current(); match current.kind() { TokenKind::LeftParentheses => { - result = Expression::Call(self.call(result)?); + let (call, mut ds) = self.call(base); + diagnostics.append(&mut ds); + base = Expression::Call(call); } _ => break, } } - Ok(result) + + (base, diagnostics) } - fn expression_base(&mut self) -> Result> { + fn expression_base(&mut self) -> ParseResult { let current = self.get_current(); + let mut diagnostics = Vec::new(); match current.kind() { TokenKind::IntegerLiteral => { let raw = self.token_text(¤t); let source_range = SourceRange::new(current.start(), current.end()); - self.advance()?; - Ok(Expression::Integer(IntegerLiteral::new( - i32::from_str(raw).unwrap(), - source_range, - ))) + diagnostics.append(&mut self.advance()); + ( + Expression::Integer(IntegerLiteral::new( + i32::from_str(raw).unwrap(), + source_range, + )), + diagnostics, + ) } TokenKind::DoubleLiteral => { let raw = self.token_text(¤t); let source_range = SourceRange::new(current.start(), current.end()); - self.advance()?; - Ok(Expression::Double(DoubleLiteral::new( - f64::from_str(raw).unwrap(), - source_range, - ))) + diagnostics.append(&mut self.advance()); + ( + Expression::Double(DoubleLiteral::new( + f64::from_str(raw).unwrap(), + source_range, + )), + diagnostics, + ) } TokenKind::String => { let with_quotes = self.token_text(¤t); let source_range = SourceRange::new(current.start(), current.end()); - self.advance()?; - Ok(Expression::String(StringLiteral::new( - &with_quotes[1..with_quotes.len() - 1], - source_range, - ))) + diagnostics.append(&mut self.advance()); + ( + Expression::String(StringLiteral::new( + &with_quotes[1..with_quotes.len() - 1], + source_range, + )), + diagnostics, + ) } TokenKind::Identifier => { let declared_name = self.token_text(¤t); let source_range = SourceRange::new(current.start(), current.end()); - self.advance()?; - Ok(Expression::Identifier(Identifier::new( - declared_name, - source_range, - ))) + diagnostics.append(&mut self.advance()); + ( + Expression::Identifier(Identifier::new(declared_name, source_range)), + diagnostics, + ) } _ => unreachable!("Unreachable token type found: {:?}", current.kind()), } } - fn call(&mut self, callee: Expression) -> Result> { - self.expect_advance(TokenKind::LeftParentheses)?; + fn call(&mut self, callee: Expression) -> ParseResult { + let mut diagnostics = Vec::new(); + let (_, mut ds) = self.expect_advance(TokenKind::LeftParentheses); + diagnostics.append(&mut ds); + let mut arguments = vec![]; if let Some(current) = &self.current { if matches_expression_first!(current.kind()) { - arguments.append(&mut self.expression_list()?); + let (mut expressions, mut ds) = self.expression_list(); + arguments.append(&mut expressions); + diagnostics.append(&mut ds); } } - let right_parentheses_token = self.expect_advance(TokenKind::RightParentheses)?; - let source_range = - SourceRange::new(callee.source_range().start(), right_parentheses_token.end()); - Ok(Call::new(callee, arguments, source_range)) + + let (maybe_right_parenthesis, mut ds) = self.expect_advance(TokenKind::RightParentheses); + diagnostics.append(&mut ds); + + let source_range = if let Some(token) = maybe_right_parenthesis { + SourceRange::new(callee.source_range().start(), token.end()) + } else { + // This should be good enough for error reporting if we're missing the right parenthesis + SourceRange::new(callee.source_range().start(), callee.source_range().end()) + }; + + (Call::new(callee, arguments, source_range), diagnostics) } - fn expression_list(&mut self) -> Result, Vec> { + fn expression_list(&mut self) -> ParseResult> { let mut expressions = vec![]; - expressions.push(self.expression()?); + let mut diagnostics = Vec::new(); + + let (expression, mut ds) = self.expression(); + expressions.push(expression); + diagnostics.append(&mut ds); + while self.current.is_some() && self.peek_current(TokenKind::Comma) { - self.advance()?; // comma - expressions.push(self.expression()?); + diagnostics.append(&mut self.advance()); // comma + let (expression, mut ds) = self.expression(); + expressions.push(expression); + diagnostics.append(&mut ds); } - Ok(expressions) + + (expressions, diagnostics) } } @@ -1076,13 +1357,10 @@ mod smoke_tests { use super::*; fn smoke_test(input: &str) { - let parse_result = parse_compilation_unit(input); - match parse_result { - Ok(_) => {} - Err(diagnostics) => { - eprintln!("{:#?}", diagnostics); - panic!("There were diagnostics during parsing"); - } + let (_, diagnostics) = parse_compilation_unit(input); + if !diagnostics.is_empty() { + eprintln!("{:#?}", diagnostics); + panic!("There were diagnostics during parsing"); } } @@ -1298,23 +1576,19 @@ mod concrete_tests { } fn assert_compilation_unit(input: &str) -> CompilationUnit { - let parse_result = parse_compilation_unit(input); - match parse_result { - Ok(compilation_unit) => compilation_unit, - Err(diagnostics) => { - report_diagnostics(&diagnostics); - } + let (compilation_unit, diagnostics) = parse_compilation_unit(input); + if !diagnostics.is_empty() { + report_diagnostics(&diagnostics); } + compilation_unit } fn assert_expression(input: &str) -> Expression { - let parse_result = parse_expression(input); - match parse_result { - Ok(expression) => expression, - Err(diagnostics) => { - report_diagnostics(&diagnostics); - } + let (expression, diagnostics) = parse_expression(input); + if !diagnostics.is_empty() { + report_diagnostics(&diagnostics); } + expression } fn assert_function_in<'a>( @@ -1434,35 +1708,3 @@ mod concrete_tests { } } } - -#[cfg(test)] -mod parse_failure_tests { - use super::*; - - #[test] - fn lone_end() { - let parse_result = parse_compilation_unit("end"); - match parse_result { - Err(diagnostics) => { - assert_eq!(diagnostics.len(), 1); - for diagnostic in &diagnostics { - println!("{:?}", diagnostic) - } - } - Ok(_) => panic!(), - } - } - - #[test] - fn two_ends() { - let parse_result = parse_compilation_unit("end end"); - match parse_result { - Err(diagnostics) => { - // Should only have an error on the first end, since we advance until we find a - // token we can recover from (fn or extern) - assert_eq!(diagnostics.len(), 1); - } - Ok(_) => panic!(), - } - } -} diff --git a/e2e-tests/src/lib.rs b/e2e-tests/src/lib.rs index 34b8c2b..6b28d35 100644 --- a/e2e-tests/src/lib.rs +++ b/e2e-tests/src/lib.rs @@ -29,13 +29,10 @@ mod e2e_tests { } fn prepare_context(input: &str) -> Result> { - let parse_result = parse_compilation_unit(input); - let mut compilation_unit = match parse_result { - Ok(compilation_unit) => compilation_unit, - Err(diagnostics) => { - report_diagnostics(&diagnostics); - } - }; + let (mut compilation_unit, diagnostics) = parse_compilation_unit(input); + if !diagnostics.is_empty() { + return Err(diagnostics); + } let mut symbol_table = SymbolTable::new(); symbol_table.push_module_scope("global_scope");