140 lines
4.6 KiB
Rust
140 lines
4.6 KiB
Rust
//! Macros used throughout the assembler
|
|
|
|
use crate::assembler::model::{Node, Opcode, Symbol, Token};
|
|
|
|
/// Parse DSA assembly code with optional formatting
|
|
///
|
|
/// # Examples
|
|
/// ```
|
|
/// // With formatting:
|
|
/// let nodes = dsa!(hash, "mov r1, {}", 42)?;
|
|
///
|
|
/// // Without formatting:
|
|
/// let nodes = dsa!(hash, "mov r1, 42")?;
|
|
/// ```
|
|
#[macro_export]
|
|
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
|
|
}};
|
|
}
|
|
|
|
/// Creates a new Node with the given symbol, opcode, and tokens
|
|
#[macro_export]
|
|
macro_rules! node {
|
|
($symbol: expr, $opcode: expr, args: $tokens: expr) => {
|
|
$crate::assembler::model::Node::new($symbol.clone(), $opcode.clone(), $tokens.clone())
|
|
};
|
|
|
|
($symbol: expr, $opcode: expr, $($tokens: expr),+) => {
|
|
$crate::assembler::model::Node::new(
|
|
$symbol.clone(),
|
|
$opcode.clone(),
|
|
vec![$(node!(@convert_token $tokens)),+]
|
|
)
|
|
};
|
|
|
|
($symbol: expr, $opcode: expr) => {
|
|
$crate::assembler::model::Node::new(
|
|
$symbol.clone(),
|
|
$opcode.clone(),
|
|
Vec::new()
|
|
)
|
|
};
|
|
|
|
(@convert_token $token: literal) => {
|
|
$crate::assembler::model::Token::Immediate($token)
|
|
};
|
|
|
|
(@convert_token $token: expr) => {
|
|
$token.clone()
|
|
};
|
|
}
|
|
|
|
/// Extracts a specific token type from a token
|
|
#[macro_export]
|
|
macro_rules! expect_token {
|
|
($token:expr, Symbol) => {
|
|
match $token {
|
|
$crate::assembler::model::Token::Symbol(value) => Ok(value.clone()),
|
|
other => Err($crate::assembler::AssembleError::UnexpectedToken(
|
|
other.clone(),
|
|
$crate::assembler::model::TokenType::Symbol,
|
|
)),
|
|
}
|
|
};
|
|
($token:expr, Register) => {
|
|
match $token {
|
|
$crate::assembler::model::Token::Register(value) => Ok(value.clone()),
|
|
other => Err($crate::assembler::AssembleError::UnexpectedToken(
|
|
other.clone(),
|
|
$crate::assembler::model::TokenType::Register,
|
|
)),
|
|
}
|
|
};
|
|
($token:expr, Immediate) => {
|
|
match $token {
|
|
$crate::assembler::model::Token::Immediate(value) => Ok(value.clone()),
|
|
other => Err($crate::assembler::AssembleError::UnexpectedToken(
|
|
other.clone(),
|
|
$crate::assembler::model::TokenType::Immediate,
|
|
)),
|
|
}
|
|
};
|
|
($token:expr, StringLit) => {
|
|
match $token {
|
|
$crate::assembler::model::Token::StringLit(value) => Ok(value.clone()),
|
|
other => Err($crate::assembler::AssembleError::UnexpectedToken(
|
|
other.clone(),
|
|
$crate::assembler::model::TokenType::StringLit,
|
|
)),
|
|
}
|
|
};
|
|
($token:expr, Opcode) => {
|
|
match $token {
|
|
$crate::assembler::model::Token::Opcode(value) => Ok(value.clone()),
|
|
other => Err($crate::assembler::AssembleError::UnexpectedToken(
|
|
other.clone(),
|
|
$crate::assembler::model::TokenType::Opcode,
|
|
)),
|
|
}
|
|
};
|
|
}
|
|
|
|
/// Checks if a token matches any of the specified types
|
|
#[macro_export]
|
|
macro_rules! expect_type {
|
|
($token:expr, $($variant:ident),+) => {{
|
|
let token = $token;
|
|
match &token {
|
|
$(
|
|
$crate::assembler::model::Token::$variant(_) => Ok(token.clone()),
|
|
)+
|
|
other => {
|
|
let expected_type = expect_type!(@get_first_type $($variant),+);
|
|
Err($crate::assembler::AssembleError::UnexpectedToken(
|
|
other.clone().clone(),
|
|
expected_type,
|
|
))
|
|
}
|
|
}
|
|
}};
|
|
|
|
(@get_first_type Symbol $(, $rest:ident)*) => { $crate::assembler::model::TokenType::Symbol };
|
|
(@get_first_type Register $(, $rest:ident)*) => { $crate::assembler::model::TokenType::Register };
|
|
(@get_first_type Immediate $(, $rest:ident)*) => { $crate::assembler::model::TokenType::Immediate };
|
|
(@get_first_type StringLit $(, $rest:ident)*) => { $crate::assembler::model::TokenType::StringLit };
|
|
(@get_first_type Opcode $(, $rest:ident)*) => { $crate::assembler::model::TokenType::Opcode };
|
|
}
|