assembler updates
This commit is contained in:
+111
-6
@@ -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 };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user