diff options
Diffstat (limited to 'src/semantic_token.rs')
-rw-r--r-- | src/semantic_token.rs | 74 |
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() } + } +} |