diff options
| Commit | 1395b9eac37187227874c2bf4e768680c7dffd32 (patch) | |
|---|---|---|
| Author | 2025-02-13 21:53:10 +0200 | |
| Committer | 2025-02-13 21:53:10 +0200 | |
| Files | 50ad9f0c614e1ff07e20964a170b1f27116069ea /assembler/src/parser/mod.rs | |
| tonkobali-1395b9eac37187227874c2bf4e768680c7dffd32.tar tonkobali-1395b9eac37187227874c2bf4e768680c7dffd32.tar.gz tonkobali-1395b9eac37187227874c2bf4e768680c7dffd32.zip | ||
| Parent | 3ea01bbd75cc252453cd21074f56eb9cc6cff317 (diff) | |
feat(assembler): Implement first step of parser
1 files changed, 104 insertions, 0 deletions
| -rw-r--r-- | assembler/src/parser/mod.rs | 104 |
diff --git a/assembler/src/parser/mod.rs b/assembler/src/parser/mod.rs new file mode 100644 index 0000000..7061286 --- /dev/null +++ b/assembler/src/parser/mod.rs @@ -0,0 +1,104 @@ +use std::collections::HashMap; +use crate::{ Word, lexer::Token }; + +#[derive(Debug, Default)] +pub(crate) struct Instruction { + name: String, + args: Vec<Address>, +} + +#[derive(Debug, Default, PartialEq, Eq, Clone)] +pub(crate) enum Address { + Memory(usize), + Constants(usize), + Definitions(String), + Instruction(usize), + #[default] + None, +} + +impl Address { + fn take(&mut self) -> Address { + let val = self.clone(); + *self = Address::None; + val + } +} + +#[derive(Debug, Default)] +pub(crate) struct Program { + definitions: HashMap<String, Address>, + constants: Vec<Word>, + instructions: Vec<Instruction>, +} + +impl Program { + pub(crate) fn new(tokens: Vec<Token>) -> Program { + let mut prog = Program {..Default::default() }; + + let mut op_name = String::new(); + let mut op_args = Vec::new(); + let mut value = Address::None; + let mut symbol_def = String::new(); + + for token in tokens { + match token { + /* Names (lvalue) */ + Token::Operator(name) => { + if ! op_name.is_empty() { + prog.instructions.push(Instruction { + name: op_name, + args: op_args.clone(), + }); + } + op_name = name; + op_args.clear(); + }, + Token::Label(name) => { + // Predicting the index + let index = prog.instructions.len() + !op_name.is_empty() as usize; + prog.definitions.insert(name, Address::Instruction(index)); + }, + Token::SymbolDef(name) => symbol_def = name, + + /* Values (rvalue) */ + Token::Address(num) => { + value = Address::Memory(num as usize); + }, + Token::Number(num) => { + prog.constants.push(num); + value = Address::Constants(prog.constants.len() - 1); + }, + Token::String(str) => { + let index = prog.constants.len(); + for c in str.chars() { + prog.constants.push(c as Word); + } + value = Address::Constants(index); + }, + Token::Symbol(name) => { + value = Address::Definitions(name); + }, + } + + if value != Address::None { + if ! symbol_def.is_empty() { + prog.definitions.insert(symbol_def.clone(), value.take()); + symbol_def.clear(); + } + else { + op_args.push(value.take()); + } + } + } + + if ! op_name.is_empty() { + prog.instructions.push(Instruction { + name: op_name, + args: op_args.clone(), + }); + } + + prog + } +} |
