summaryrefslogtreecommitdiff
path: root/src/semantic_token.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/semantic_token.rs')
-rw-r--r--src/semantic_token.rs74
1 files changed, 70 insertions, 4 deletions
diff --git a/src/semantic_token.rs b/src/semantic_token.rs
index cac82a9..3d08b25 100644
--- a/src/semantic_token.rs
+++ b/src/semantic_token.rs
@@ -7,12 +7,12 @@ pub enum SemanticTokenType {
LabelDefinition(LabelDefinition),
MacroDefinition(MacroDefinition),
- Pad(u16),
- Byte(u8),
- Short(u16),
+ Padding(u16),
+ ByteLiteral(u8),
+ ShortLiteral(u16),
Instruction(u8),
- MacroTerminator,
+ MacroDefinitionTerminator,
Comment,
Error(SyntacticTokenType, Error),
}
@@ -23,16 +23,82 @@ pub struct SemanticToken {
pub bytecode_location: BytecodeLocation,
}
+impl SemanticToken {
+ pub fn print_error(&self, source_code: &str) {
+ macro_rules! red {()=>{eprint!("\x1b[31m")};}
+ macro_rules! normal {()=>{eprint!("\x1b[0m")};}
+
+ if let SemanticTokenType::Error(token, error) = &self.r#type {
+ red!(); eprint!("[ERROR] "); normal!();
+ let source = &self.source_location.source;
+ match error {
+ Error::UnresolvedReference => {
+ eprintln!("Unresolved reference, no label or macro has been defined with the name '{source}'") }
+ Error::DuplicateDefinition => {
+ eprintln!("Duplicate definition, a label or macro has already been defined with the name '{source}'") }
+ Error::OrphanedMacroDefinitionTerminator => {
+ eprintln!("Unmatched macro definition terminator, no macro definition is in progress") }
+ Error::InvalidPaddingValue => {
+ eprintln!("Invalid value for padding, the value must be at least one and at most four hexadecimal characters") }
+ Error::CyclicMacroReference => {
+ eprintln!("Cyclic macro reference, this macro reference contains a reference to the macro being defined") }
+ Error::InvalidTypeInMacroDefinition => {
+ let name = match token {
+ SyntacticTokenType::Reference(_) => "references",
+ SyntacticTokenType::LabelDefinition(_) => "label definitions",
+ SyntacticTokenType::MacroDefinition(_) => "macro definitions",
+ SyntacticTokenType::MacroDefinitionTerminator => "macro definition terminators",
+ SyntacticTokenType::Padding(_) => "padding",
+ SyntacticTokenType::ByteLiteral(_) => "byte literals",
+ SyntacticTokenType::ShortLiteral(_) => "short literals",
+ SyntacticTokenType::Instruction(_) => "instructions",
+ SyntacticTokenType::Comment => "comments",
+ };
+ eprintln!("Invalid token in macro definition, macro definitions are not allowed to contain {name}") }
+ }
+ let line = source_code.split('\n').nth(self.source_location.start.line).unwrap();
+ eprint!("{:>5} ", self.source_location.start.line+1);
+ red!(); eprint!("| "); normal!();
+ for (i, c) in line.chars().enumerate() {
+ if i == self.source_location.start.column { red!() }
+ eprint!("{c}");
+ if i == self.source_location.end.column { normal!() }
+ }
+ eprintln!(); red!(); eprint!(" | ");
+ for i in 0..=self.source_location.end.column {
+ if i < self.source_location.start.column { eprint!(" ") } else { eprint!("^") };
+ }
+ normal!(); eprintln!();
+ }
+ if let SemanticTokenType::MacroDefinition(definition) = &self.r#type {
+ for token in &definition.body_tokens {
+ token.print_error(source_code);
+ }
+ }
+ }
+}
+
pub struct LabelDefinition {
pub name: String,
pub address: u16,
/// A list of pointers to label reference tokens
pub references: Vec<usize>,
}
+impl LabelDefinition {
+ pub fn new(name: String) -> Self {
+ Self { name, address:0, references:Vec::new() }
+ }
+}
+
pub struct MacroDefinition {
pub name: String,
pub body_tokens: Vec<SemanticToken>,
/// A list of pointers to macro reference tokens
pub references: Vec<usize>,
}
+impl MacroDefinition {
+ pub fn new(name: String) -> Self {
+ Self { name, body_tokens:Vec::new(), references:Vec::new() }
+ }
+}