91 lines
2.2 KiB
Rust
91 lines
2.2 KiB
Rust
use std::collections::VecDeque;
|
|
|
|
use crate::tokenizer::{Token, TokenType};
|
|
|
|
pub fn generate(tokens: Vec<Token>) -> String {
|
|
let mut output = String::new();
|
|
|
|
// reserving mem
|
|
output.push_str(
|
|
"section .bss\n\
|
|
data: resb 65536\n",
|
|
);
|
|
|
|
// global start label
|
|
output.push_str(
|
|
"global _start\n\
|
|
section .text\n\
|
|
_start:\n",
|
|
);
|
|
|
|
// create the pointer for our data
|
|
output.push_str("mov rdx, data\n");
|
|
|
|
let mut loops = 0;
|
|
let mut stack: VecDeque<usize> = VecDeque::new();
|
|
for token in tokens {
|
|
match token.r#type {
|
|
TokenType::Plus(x) => {
|
|
output.push_str(&format!("add byte[rdx], {x}\n"));
|
|
}
|
|
TokenType::Minus(x) => {
|
|
output.push_str(&format!("sub byte[rdx], {x}\n"));
|
|
}
|
|
TokenType::MoveRight(x) => {
|
|
output.push_str(&format!("add rdx, {x}\n"));
|
|
}
|
|
TokenType::MoveLeft(x) => {
|
|
output.push_str(&format!("sub rdx, {x}\n"));
|
|
}
|
|
TokenType::Output => {
|
|
output.push_str(
|
|
"push rdx\n\
|
|
mov rax, 1\n\
|
|
mov rdi, 1\n\
|
|
mov rsi, rdx\n\
|
|
mov rdx, 1\n\
|
|
syscall\n\
|
|
pop rdx\n",
|
|
);
|
|
}
|
|
TokenType::Input => {
|
|
output.push_str(
|
|
"push rdx\n\
|
|
mov rax, 0\n\
|
|
mov rdi, 0\n\
|
|
mov rsi, rdx\n\
|
|
mov rdx, 1\n\
|
|
syscall\n\
|
|
pop rdx\n",
|
|
);
|
|
}
|
|
TokenType::BracketOpen => {
|
|
output.push_str(&format!(
|
|
".loop_{loops}_start:\n\
|
|
cmp byte[rdx], 0\n\
|
|
je .loop_{loops}_end\n"
|
|
));
|
|
stack.push_back(loops);
|
|
loops += 1;
|
|
}
|
|
TokenType::BracketClose => {
|
|
let current_loop = stack.pop_back().unwrap();
|
|
output.push_str(&format!(
|
|
"cmp byte[rdx], 0\n\
|
|
jne .loop_{current_loop}_start\n\
|
|
.loop_{current_loop}_end:\n",
|
|
));
|
|
}
|
|
}
|
|
}
|
|
|
|
// exit syscall
|
|
output.push_str(
|
|
"mov rax, 60\n\
|
|
mov rdi, 0\n\
|
|
syscall\n",
|
|
);
|
|
|
|
output
|
|
}
|