diff options
author | Ben Bridle <bridle.benjamin@gmail.com> | 2025-02-15 08:20:18 +1300 |
---|---|---|
committer | Ben Bridle <bridle.benjamin@gmail.com> | 2025-02-15 08:20:18 +1300 |
commit | 4e8fae09f0f7d6f3a4ddbe285aeb01ef0622b761 (patch) | |
tree | 79eab5ef0f5d3eee7949a317db50489dac2fce99 /src/tokens/semantic.rs | |
parent | e39505931b05be321ee2b04c41a9739f00c19208 (diff) | |
download | torque-asm-4e8fae09f0f7d6f3a4ddbe285aeb01ef0622b761.zip |
Implement semantic error reporting
Diffstat (limited to 'src/tokens/semantic.rs')
-rw-r--r-- | src/tokens/semantic.rs | 89 |
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), + }; + } } } |