diff options
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 85 |
1 files changed, 81 insertions, 4 deletions
diff --git a/src/main.rs b/src/main.rs index 342057d..e7e52d9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,6 @@ pub use environment::*; pub use parsers::*; pub use tokens::*; - pub use assembler::*; use log::{info, fatal}; use switchboard::{Switchboard, SwitchQuery}; @@ -87,8 +86,6 @@ fn main() { std::process::exit(1); } - compiler.resolver.unused().report(); - let merged_source = compiler.get_compiled_source().unwrap_or_else( |error| { error.report(); std::process::exit(1); } ); @@ -105,7 +102,7 @@ fn main() { report_syntactic_errors(&syntactic_tokens, &merged_source); let program = ProgramParser::new(syntactic_tokens).parse(); - program.print_definitions(); + report_semantic_errors(&program, &merged_source); } @@ -173,3 +170,83 @@ fn report_syntactic_errors(syntactic_tokens: &[syntactic::Token], source_code: & } } } + + +fn report_semantic_errors(program: &semantic::Program, source_code: &str) { + for error in &program.errors { + report_parse_error(error, source_code); + } + for definition in &program.definitions { + report_definition_errors(&definition.variant, source_code); + } + for invocation in &program.invocations { + report_invocation_errors(invocation, source_code); + } +} + +fn report_parse_error(error: &semantic::ParseError, source_code: &str) { + use semantic::*; + let message = match &error.variant { + ParseErrorVariant::UnterminatedMacroDefinition(name) => + format!("The macro definition '{name}' is missing a terminating ';' character"), + ParseErrorVariant::UnterminatedBlockDefinition => + format!("Block literal is missing a terminating '}}' character"), + ParseErrorVariant::InvalidArgumentDefinition(name) => + format!("The macro definition '{name}' has an invalid argument definition"), + ParseErrorVariant::InvalidToken => + format!("Invalid token"), + }; + let context = Context { source: &error.source, source_code}; + report_source_issue(LogLevel::Error, &context, &message); +} + +fn report_definition_errors(definition: &semantic::DefinitionVariant, source_code: &str) { + use semantic::*; + match definition { + DefinitionVariant::Integer(integer) => match &integer.variant { + IntegerDefinitionVariant::Constant(expr) => for token in &expr.tokens { + if let ConstantExpressionTokenVariant::Error(error) = &token.variant { + let message = match error { + ConstantExpressionParseError::InvalidHexadecimalLiteral(hex) => + format!("Invalid hexadecimal literal '{hex}' in constant expression"), + }; + let context = Context { source: &token.source, source_code}; + report_source_issue(LogLevel::Error, &context, &message); + } + } + _ => (), + } + DefinitionVariant::Block(block) => { + for error in &block.errors { + report_parse_error(&error, source_code); + } + for token in &block.tokens { + match &token.variant { + BlockTokenVariant::Word(pbl) => for error in &pbl.errors { + let message = match error.variant { + PackedBinaryLiteralParseErrorVariant::DuplicateFieldName(name) => + format!("Duplicate field name '{name}' in packed binary literal"), + PackedBinaryLiteralParseErrorVariant::InvalidCharacter(c) => + format!("Invalid character '{c}' in packed binary literal"), + }; + let context = Context { source: &error.source, source_code }; + report_source_issue(LogLevel::Error, &context, &message); + } + BlockTokenVariant::Invocation(invocation) => + report_invocation_errors(invocation, source_code), + BlockTokenVariant::Comment(_) => (), + } + } + } + DefinitionVariant::Reference(_) => (), + } +} + +fn report_invocation_errors(invocation: &semantic::Invocation, source_code: &str) { + for error in &invocation.errors { + report_parse_error(&error, source_code); + } + for argument in &invocation.arguments { + report_definition_errors(argument, source_code); + } +} |