diff options
feat(assembler): Implemented semantic analysis
1 files changed, 46 insertions, 0 deletions
| -rw-r--r-- | assembler/src/parser/instruction.rs | 46 |
diff --git a/assembler/src/parser/instruction.rs b/assembler/src/parser/instruction.rs index c44c1de..18d67b7 100644 --- a/assembler/src/parser/instruction.rs +++ b/assembler/src/parser/instruction.rs @@ -1,5 +1,15 @@ use super::{ Instruction, Address }; +#[derive(Debug)] +pub(crate) enum ArgumentError { + UnknownInstruction, + TooMany, + TooFew, + NotLocation, + NotNumber, + NotString, +} + impl Instruction { fn new_subleq(a: &Address, b: &Address, c: &Address) -> Instruction { if let Address::Constants(_) = c { @@ -11,6 +21,42 @@ impl Instruction { } } + fn check_args_len(&self, expected: usize) -> Result<(), ArgumentError> { + if self.args.len() < expected { + return Err(ArgumentError::TooFew); + } + else if self.args.len() > 3 { + return Err(ArgumentError::TooMany); + } + Ok(()) + } + + pub(crate) fn check_args(&self) -> Result<(), ArgumentError> { + match &*self.name { + "subleq" => { + self.check_args_len(3)?; + + for arg in &self.args { + if ! arg.is_location() { + return Err(ArgumentError::NotLocation); + } + } + }, + "jmp" => { + self.check_args_len(1)?; + + if ! self.args[0].is_location() { + return Err(ArgumentError::NotLocation); + } + }, + "add" => { + self.check_args_len(2)?; + }, + _ => return Err(ArgumentError::UnknownInstruction), + } + Ok(()) + } + pub(crate) fn collapse(&mut self, next: usize) -> Vec<Instruction> { self.name = self.name.to_lowercase(); static Z: Address = Address::Memory(0); |
