summaryrefslogtreecommitdiff
path: root/src/tokens/semantic.rs
diff options
context:
space:
mode:
authorBen Bridle <bridle.benjamin@gmail.com>2025-02-15 08:20:18 +1300
committerBen Bridle <bridle.benjamin@gmail.com>2025-02-15 08:20:18 +1300
commit4e8fae09f0f7d6f3a4ddbe285aeb01ef0622b761 (patch)
tree79eab5ef0f5d3eee7949a317db50489dac2fce99 /src/tokens/semantic.rs
parente39505931b05be321ee2b04c41a9739f00c19208 (diff)
downloadtorque-asm-4e8fae09f0f7d6f3a4ddbe285aeb01ef0622b761.zip
Implement semantic error reporting
Diffstat (limited to 'src/tokens/semantic.rs')
-rw-r--r--src/tokens/semantic.rs89
1 files changed, 73 insertions, 16 deletions
diff --git a/src/tokens/semantic.rs b/src/tokens/semantic.rs
index 66db7b2..7d5d327 100644
--- a/src/tokens/semantic.rs
+++ b/src/tokens/semantic.rs
@@ -68,6 +68,7 @@ pub struct ReferenceDefinition {
pub struct Invocation {
pub name: String,
pub arguments: Vec<DefinitionVariant>,
+ pub errors: Vec<ParseError>,
}
pub struct ParseError {
@@ -76,7 +77,7 @@ pub struct ParseError {
}
pub enum ParseErrorVariant {
- UnterminatedMacroDefinition,
+ UnterminatedMacroDefinition(String),
UnterminatedBlockDefinition,
/// Name of the macro.
InvalidArgumentDefinition(String),
@@ -86,29 +87,85 @@ pub enum ParseErrorVariant {
// ------------------------------------------------------------------------ //
+macro_rules! indent {
+ ($indent:expr => $($tokens:tt)*) => {{
+ for _ in 0..$indent { print!(" "); }
+ println!($($tokens)*);
+ }};
+}
+
impl Program {
pub fn print_definitions(&self) {
for definition in &self.definitions {
- let variant = match definition.variant {
- DefinitionVariant::Integer(_) => "integer",
- DefinitionVariant::Block(_) => "block",
- DefinitionVariant::Reference(_) => "reference",
+ let variant = match &definition.variant {
+ DefinitionVariant::Integer(_) => "INTEGER",
+ DefinitionVariant::Block(_) => "BLOCK",
+ DefinitionVariant::Reference(_) => "REFERENCE",
};
- println!("DEFINE {} ({variant})", definition.name);
+ println!("DEFINE {variant} '{}'", definition.name);
for argument in &definition.arguments {
- let variant = match argument.variant {
- ArgumentDefinitionVariant::Integer => "integer",
- ArgumentDefinitionVariant::Block => "block",
- };
- println!(" ARGUMENT {} ({variant})", argument.name);
+ self.print_argument_definition(argument);
}
- let variant = match &definition.variant {
- DefinitionVariant::Integer(integer) => todo!(),
- DefinitionVariant::Block(block) => todo!(),
- DefinitionVariant::Reference(reference) => todo!()
+ match &definition.variant {
+ DefinitionVariant::Integer(integer) =>
+ self.print_integer_definition(1, integer),
+ DefinitionVariant::Block(block) =>
+ self.print_block_definition(1, block),
+ DefinitionVariant::Reference(reference) =>
+ indent!(1 => "REFERENCE '{}'", reference.name),
};
-
println!();
}
+
+ for invocation in &self.invocations {
+ self.print_invocation(0, invocation);
+ }
+ }
+
+ fn print_argument_definition(&self, argument: &ArgumentDefinition) {
+ let variant = match argument.variant {
+ ArgumentDefinitionVariant::Integer => "INTEGER",
+ ArgumentDefinitionVariant::Block => "BLOCK",
+ };
+ println!(" ARGUMENT {variant} '{}'", argument.name);
+ }
+
+ fn print_integer_definition(&self, indent: usize, definition: &IntegerDefinition) {
+ match &definition.variant {
+ IntegerDefinitionVariant::Literal(value) =>
+ indent!(indent => "LITERAL {value}"),
+ IntegerDefinitionVariant::Constant(expr) =>
+ indent!(indent => "CONSTANT [{expr:?}]"),
+ }
+ }
+
+ fn print_block_definition(&self, indent: usize, definition: &BlockDefinition) {
+ indent!(indent => "BLOCK");
+ let indent = indent + 1;
+ for token in &definition.tokens {
+ match &token.variant {
+ BlockTokenVariant::Invocation(invocation) =>
+ self.print_invocation(indent, invocation),
+ BlockTokenVariant::Comment(_) =>
+ indent!(indent => "COMMENT"),
+ BlockTokenVariant::Word(word) =>
+ indent!(indent => "WORD #{word}"),
+ }
+ }
+ }
+
+ fn print_invocation(&self, indent: usize, invocation: &Invocation) {
+ indent!(indent => "INVOCATION '{}'", invocation.name);
+ let indent = indent + 1;
+ for argument in &invocation.arguments {
+ match &argument {
+ DefinitionVariant::Integer(integer) =>
+ self.print_integer_definition(indent, integer),
+ DefinitionVariant::Block(block) =>
+ self.print_block_definition(indent, block),
+ DefinitionVariant::Reference(reference) =>
+ indent!(indent => "REFERENCE '{}'", reference.name),
+ };
+ }
}
}