summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs85
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);
+ }
+}