summaryrefslogtreecommitdiff
path: root/src/stages/semantic_tokens.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/stages/semantic_tokens.rs')
-rw-r--r--src/stages/semantic_tokens.rs101
1 files changed, 101 insertions, 0 deletions
diff --git a/src/stages/semantic_tokens.rs b/src/stages/semantic_tokens.rs
new file mode 100644
index 0000000..ca5b27a
--- /dev/null
+++ b/src/stages/semantic_tokens.rs
@@ -0,0 +1,101 @@
+use crate::*;
+
+use std::collections::HashMap;
+
+
+pub struct Program {
+ pub definitions: HashMap<String, Tracked<Definition>>,
+ pub tokens: Vec<Tracked<SemanticToken>>,
+}
+
+pub struct Definition {
+ pub kind: DefinitionKind,
+ pub definition: usize,
+ pub references: Vec<usize>,
+ pub deep_references: Vec<(usize, usize)>,
+}
+
+impl Definition {
+ pub fn new(i: usize, kind: DefinitionKind) -> Self {
+ Self {
+ kind,
+ definition: i,
+ references: Vec::new(),
+ deep_references: Vec::new(),
+ }
+ }
+}
+
+pub enum DefinitionKind {
+ MacroDefinition(Vec<Tracked<SemanticToken>>),
+ LabelDefinition,
+}
+
+pub enum SemanticToken {
+ Comment(String),
+
+ LabelDefinition(String),
+ MacroDefinition(Tracked<String>),
+
+ RawValue(Value),
+ Instruction(Instruction),
+ Invocation(String),
+
+ Padding(Value),
+ String(Vec<u8>),
+
+ BlockOpen(usize),
+ BlockClose(usize),
+}
+
+pub enum SemanticError {
+ InvocationBeforeDefinition,
+}
+
+
+pub fn report_semantic_errors(errors: &[Tracked<SemanticError>], source_code: &str) {
+ for error in errors {
+ report_semantic_error(error, source_code);
+ }
+}
+
+fn report_semantic_error(error: &Tracked<SemanticError>, source_code: &str) {
+ let context = Context { source_code: &source_code, source: &error.source };
+ let message = match &error.value {
+ SemanticError::InvocationBeforeDefinition =>
+ "Invocation before definition",
+ };
+
+ report_source_issue(LogLevel::Error, &context, message);
+}
+
+
+pub fn print_semantic_token(i: usize, token: &SemanticToken, definitions: &HashMap<String, Tracked<Definition>>) {
+ match token {
+ SemanticToken::Comment(_) =>
+ indent!(i, "Comment"),
+
+ SemanticToken::LabelDefinition(name) =>
+ indent!(i, "LabelDefinition({name})"),
+ SemanticToken::MacroDefinition(name) => {
+ indent!(i, "MacroDefinition({name})");
+ if let Some(definition) = definitions.get(name.as_str()) {
+ if let DefinitionKind::MacroDefinition(body) = &definition.kind {
+ for token in body {
+ print_semantic_token(i+1, token, definitions);
+ }
+ }
+ }
+ }
+
+ SemanticToken::RawValue(value) => indent!(i, "RawValue({value})"),
+ SemanticToken::Instruction(instruction) => indent!(i, "Instruction({instruction})"),
+ SemanticToken::Invocation(name) => indent!(i, "Invocation({name})"),
+
+ SemanticToken::Padding(value) => indent!(i, "Padding({value})"),
+ SemanticToken::String(bytes) => indent!(i, "String({})", String::from_utf8_lossy(bytes)),
+
+ SemanticToken::BlockOpen(pointer) => indent!(i, "BlockOpen(*{pointer})"),
+ SemanticToken::BlockClose(pointer) => indent!(i, "BlockOpen(*{pointer})"),
+ }
+}