Another big parser refactor, collecting diagnostics better.

This commit is contained in:
Jesse Brault 2026-03-28 20:50:46 -05:00
parent 0df1252053
commit f95d504f88
8 changed files with 765 additions and 525 deletions

View File

@ -175,7 +175,10 @@ fn compile_expression(
constants_table: &mut ConstantsTable, constants_table: &mut ConstantsTable,
) -> Result<Function, Vec<Diagnostic>> { ) -> Result<Function, Vec<Diagnostic>> {
// parse // 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 // init scopes, if necessary
let container_scope = prepare_scopes(symbol_table, fn_body_scope_id); let container_scope = prepare_scopes(symbol_table, fn_body_scope_id);
@ -240,7 +243,11 @@ fn compile_let_statement(
constants_table: &mut ConstantsTable, constants_table: &mut ConstantsTable,
) -> Result<Function, Vec<Diagnostic>> { ) -> Result<Function, Vec<Diagnostic>> {
// parse // 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 // names
let container_scope_id = prepare_scopes(symbol_table, body_scope_id); let container_scope_id = prepare_scopes(symbol_table, body_scope_id);

View File

@ -7,7 +7,7 @@ use dmc_lib::constants_table::ConstantsTable;
use dmc_lib::diagnostic::Diagnostic; use dmc_lib::diagnostic::Diagnostic;
use dmc_lib::intrinsics::{insert_intrinsic_symbols, insert_intrinsic_types}; use dmc_lib::intrinsics::{insert_intrinsic_symbols, insert_intrinsic_types};
use dmc_lib::offset_counter::OffsetCounter; 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::symbol_table::SymbolTable;
use dmc_lib::types_table::TypesTable; use dmc_lib::types_table::TypesTable;
use dvm_lib::vm::constant::{Constant, StringConstant}; use dvm_lib::vm::constant::{Constant, StringConstant};
@ -41,7 +41,7 @@ fn run(
show_asm: bool, show_asm: bool,
register_count: usize, register_count: usize,
) -> Result<(), Vec<Diagnostic>> { ) -> Result<(), Vec<Diagnostic>> {
let mut compilation_unit = parse_compilation_unit(&input)?; let mut compilation_unit = get_compilation_unit(&input)?;
let mut symbol_table = SymbolTable::new(); let mut symbol_table = SymbolTable::new();
symbol_table.push_module_scope("global scope"); symbol_table.push_module_scope("global scope");

View File

@ -255,7 +255,7 @@ mod tests {
use crate::ast::compilation_unit::CompilationUnit; use crate::ast::compilation_unit::CompilationUnit;
use crate::diagnostic::Diagnostic; use crate::diagnostic::Diagnostic;
use crate::error_codes::{ASSIGN_LHS_IMMUTABLE, ASSIGN_MISMATCHED_TYPES, ASSIGN_NO_L_VALUE}; 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::symbol_table::SymbolTable;
use crate::types_table::TypesTable; use crate::types_table::TypesTable;
@ -272,15 +272,14 @@ mod tests {
#[test] #[test]
fn finds_mismatched_types() -> Result<(), Vec<Diagnostic>> { fn finds_mismatched_types() -> Result<(), Vec<Diagnostic>> {
let mut compilation_unit = parse_compilation_unit( let mut compilation_unit = get_compilation_unit(
" "
fn main() fn main()
let mut x = 4 let mut x = 4
x = \"Hello\" x = \"Hello\"
end end
", ",
) )?;
.unwrap();
let mut symbol_table = SymbolTable::new(); let mut symbol_table = SymbolTable::new();
let mut types_table = TypesTable::new(); let mut types_table = TypesTable::new();
compile_up_to_type_check(&mut compilation_unit, &mut symbol_table, &mut types_table)?; compile_up_to_type_check(&mut compilation_unit, &mut symbol_table, &mut types_table)?;
@ -297,7 +296,7 @@ mod tests {
#[test] #[test]
fn finds_no_l_value() -> Result<(), Vec<Diagnostic>> { fn finds_no_l_value() -> Result<(), Vec<Diagnostic>> {
let mut compilation_unit = parse_compilation_unit( let mut compilation_unit = get_compilation_unit(
" "
fn main() fn main()
42 = 42 42 = 42
@ -317,7 +316,7 @@ mod tests {
#[test] #[test]
fn finds_immutable_destination() -> Result<(), Vec<Diagnostic>> { fn finds_immutable_destination() -> Result<(), Vec<Diagnostic>> {
let mut compilation_unit = parse_compilation_unit( let mut compilation_unit = get_compilation_unit(
" "
fn main() fn main()
let x = 42 let x = 42

View File

@ -174,13 +174,13 @@ impl TypeUse {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::diagnostic::Diagnostic; use crate::diagnostic::Diagnostic;
use crate::parser::parse_compilation_unit; use crate::parser::get_compilation_unit;
use crate::symbol_table::SymbolTable; use crate::symbol_table::SymbolTable;
use crate::types_table::TypesTable; use crate::types_table::TypesTable;
#[test] #[test]
fn type_check_generics() -> Result<(), Vec<Diagnostic>> { fn type_check_generics() -> Result<(), Vec<Diagnostic>> {
let mut compilation_unit = parse_compilation_unit( let mut compilation_unit = get_compilation_unit(
" "
class String end class String end

View File

@ -14,14 +14,9 @@ fn parse_compilation_units(
let mut parse_diagnostics = Vec::new(); let mut parse_diagnostics = Vec::new();
let mut compilation_units = HashMap::new(); let mut compilation_units = HashMap::new();
for (file_name, source) in inputs { for (file_name, source) in inputs {
match parse_compilation_unit(source) { let (compilation_unit, mut ds) = parse_compilation_unit(source);
Ok(compilation_unit) => { parse_diagnostics.append(&mut ds);
compilation_units.insert(file_name.clone(), compilation_unit); compilation_units.insert(file_name.clone(), compilation_unit);
}
Err(mut ds) => {
parse_diagnostics.append(&mut ds);
}
}
} }
if parse_diagnostics.is_empty() { if parse_diagnostics.is_empty() {
Ok(compilation_units) Ok(compilation_units)

View File

@ -124,13 +124,13 @@ impl Display for IrBlock {
mod tests { mod tests {
use crate::diagnostic::Diagnostic; use crate::diagnostic::Diagnostic;
use crate::offset_counter::OffsetCounter; use crate::offset_counter::OffsetCounter;
use crate::parser::parse_compilation_unit; use crate::parser::get_compilation_unit;
use crate::symbol_table::SymbolTable; use crate::symbol_table::SymbolTable;
use crate::types_table::TypesTable; use crate::types_table::TypesTable;
#[test] #[test]
fn overlapping_assignments_bug_when_k_2() -> Result<(), Vec<Diagnostic>> { fn overlapping_assignments_bug_when_k_2() -> Result<(), Vec<Diagnostic>> {
let mut compilation_unit = parse_compilation_unit( let mut compilation_unit = get_compilation_unit(
" "
fn main() fn main()
let a = 1 let a = 1

File diff suppressed because it is too large Load Diff

View File

@ -29,13 +29,10 @@ mod e2e_tests {
} }
fn prepare_context(input: &str) -> Result<DvmContext, Vec<Diagnostic>> { fn prepare_context(input: &str) -> Result<DvmContext, Vec<Diagnostic>> {
let parse_result = parse_compilation_unit(input); let (mut compilation_unit, diagnostics) = parse_compilation_unit(input);
let mut compilation_unit = match parse_result { if !diagnostics.is_empty() {
Ok(compilation_unit) => compilation_unit, return Err(diagnostics);
Err(diagnostics) => { }
report_diagnostics(&diagnostics);
}
};
let mut symbol_table = SymbolTable::new(); let mut symbol_table = SymbolTable::new();
symbol_table.push_module_scope("global_scope"); symbol_table.push_module_scope("global_scope");