assembler updates

This commit is contained in:
2025-06-17 23:48:06 +01:00
parent 87fbd6c362
commit b0670d1e6c
3 changed files with 268 additions and 161 deletions
+111 -6
View File
@@ -11,11 +11,13 @@ use common::prelude::Instruction;
use crate::{
model::{Node, Token, TokenType},
parser::{Parser, Program},
resolver::resolve_dependencies,
};
pub mod lexer;
pub mod model;
pub mod parser;
pub mod resolver;
pub fn assemble(src: &PathBuf) -> Vec<Instruction> {
let mut modules = HashSet::<u64>::new();
@@ -59,14 +61,19 @@ fn prepare_dependency(
let tokens = lexer::lexer(src, file_hash)?;
log(&format!("{:20} {:20}", "Parsing", filename));
let mut parser = Parser::new(tokens);
let parsed = Parser::parse_nodes(tokens)?;
log(&format!("{:20} {:20}", "Resolving Deps", filename));
let deps = parser
.parse_nodes()?
.resolve_dependencies()?
.get_dependencies()?;
program.add_module(parser.get());
let nodes = resolve_dependencies(parsed)?;
let deps = Parser::get_dependencies(&nodes)?;
log(&format!(
"{:20} {:20}",
"Expanding PseudoInstructions", filename
));
let nodes = Parser::expand_pseudo_ops(nodes, file_hash)?;
program.add_module(nodes);
for dep in deps {
log(&format!(
@@ -100,6 +107,7 @@ pub fn disassemble(_: Vec<Instruction>) -> String {
#[derive(Debug)]
pub enum AssembleError {
Generic,
UnexpectedEof,
InvalidFile(PathBuf),
UnexpectedToken(Token, TokenType),
}
@@ -111,6 +119,7 @@ impl fmt::Display for AssembleError {
AssembleError::UnexpectedToken(tok, expected) => {
write!(f, "Unexpected token {tok:?}, expected {expected:?}")
}
AssembleError::UnexpectedEof => write!(f, "Unexpected end of file"),
AssembleError::InvalidFile(path) => write!(f, "Invalid file {path:?}"),
}
}
@@ -125,3 +134,99 @@ fn quick_hash(value: &PathBuf) -> u64 {
fn log(message: &str) {
println!("\x1b[32mINFO:\x1b[0m {}", message);
}
// create a macro that lexes and parses the input string into Nodes
#[macro_export]
#[macro_use]
macro_rules! dsa {
// Version with formatting arguments
($hash:expr, $input:expr, $($args:expr),+) => {{
let input = format!($input, $($args),+);
let tokens = crate::lexer::lexer(input, $hash)?;
let parsed = crate::parser::Parser::parse_nodes(tokens)?;
parsed
}};
// Version without formatting
($hash:expr, $input:expr) => {{
let input = String::from($input);
let tokens = crate::lexer::lexer(input, $hash)?;
let parsed = crate::parser::Parser::parse_nodes(tokens)?;
parsed
}};
}
#[macro_export]
#[macro_use]
macro_rules! expect_token {
($token:expr, Symbol) => {
match $token {
Token::Symbol(value) => Ok(value.clone()),
other => Err(AssembleError::UnexpectedToken(
other.clone(),
TokenType::Symbol,
)),
}
};
($token:expr, Register) => {
match $token {
Token::Register(value) => Ok(value.clone()),
other => Err(AssembleError::UnexpectedToken(
other.clone(),
TokenType::Register,
)),
}
};
($token:expr, Immediate) => {
match $token {
Token::Immediate(value) => Ok(value.clone()),
other => Err(AssembleError::UnexpectedToken(
other.clone(),
TokenType::Immediate,
)),
}
};
($token:expr, StringLit) => {
match $token {
Token::StringLit(value) => Ok(value.clone()),
other => Err(AssembleError::UnexpectedToken(
other.clone(),
TokenType::StringLit,
)),
}
};
($token:expr, Opcode) => {
match $token {
Token::Opcode(value) => Ok(value.clone()),
other => Err(AssembleError::UnexpectedToken(
other.clone(),
TokenType::Opcode,
)),
}
};
}
#[macro_export]
#[macro_use]
macro_rules! expect_type {
($token:expr, $($variant:ident),+) => {{
let token = $token;
match &token {
$(
Token::$variant(_) => Ok(token.clone()),
)+
other => {
let expected_type = expect_type!(@get_first_type $($variant),+);
Err(AssembleError::UnexpectedToken(
other.clone(),
expected_type,
))
}
}
}};
(@get_first_type Symbol $(, $rest:ident)*) => { TokenType::Symbol };
(@get_first_type Register $(, $rest:ident)*) => { TokenType::Register };
(@get_first_type Immediate $(, $rest:ident)*) => { TokenType::Immediate };
(@get_first_type StringLit $(, $rest:ident)*) => { TokenType::StringLit };
(@get_first_type Opcode $(, $rest:ident)*) => { TokenType::Opcode };
}