preparing to refactor
renamed AST to ast, following rust naming convention, removed some useless test files and moved the tests to the appropriate files.
This commit is contained in:
parent
9358bfa77f
commit
8f894174d9
@ -1,9 +1,8 @@
|
||||
use super::AST::*;
|
||||
use super::ast::*;
|
||||
use crate::cpu::get_num;
|
||||
|
||||
use log::{trace, warn};
|
||||
|
||||
|
||||
/// Trait to represent a format we can translate our assembly to.
|
||||
pub trait CodeFormat {
|
||||
fn encode_op(op: &Operation, sy: &SymbolTable, current_pc: u16) -> Option<Self>
|
||||
@ -36,7 +35,7 @@ impl SymbolTable {
|
||||
// query, sy
|
||||
// );
|
||||
warn!("Symbol {} not found in symbol table.", query);
|
||||
return None
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,13 @@
|
||||
mod AST;
|
||||
mod ast;
|
||||
pub mod encoder;
|
||||
pub mod parser;
|
||||
mod tests;
|
||||
|
||||
use encoder::CodeFormat;
|
||||
use encoder::SymbolTable;
|
||||
|
||||
pub use AST::print_op;
|
||||
pub use ast::print_op;
|
||||
|
||||
use log::{trace, debug};
|
||||
use log::{debug, trace};
|
||||
|
||||
use parser::Section;
|
||||
|
||||
@ -26,7 +25,7 @@ impl Section {
|
||||
// UTF-8 strings are collections of 8-bit chunks, but they're
|
||||
// packed into words of 16 bits + 16 bit NULL.
|
||||
//
|
||||
// If there's an uneven number of bytes in a string,
|
||||
// If there's an uneven number of bytes in a string,
|
||||
// we add a 8 bit empty padding and then the NULL byte.
|
||||
SectionContent::CString(s) => {
|
||||
let c = s.len();
|
||||
@ -41,7 +40,7 @@ impl Section {
|
||||
}
|
||||
|
||||
/// Converts this section to binary. Needs symbol table to
|
||||
/// resolve labels, and to quickly get the address of
|
||||
/// resolve labels, and to quickly get the address of
|
||||
/// this own section.
|
||||
fn to_binary(&self, sy: &SymbolTable) -> Option<crate::loader::Section> {
|
||||
let own_address = sy.lookup(&self.name)?;
|
||||
@ -63,17 +62,19 @@ impl Section {
|
||||
return Some(crate::loader::Section::new(self.name.clone(), &res));
|
||||
}
|
||||
SectionContent::CString(s) => {
|
||||
return Some(crate::loader::Section::new(self.name.clone(), &make_string(s)));
|
||||
return Some(crate::loader::Section::new(
|
||||
self.name.clone(),
|
||||
&make_string(s),
|
||||
));
|
||||
}
|
||||
SectionContent::CVec() => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Sorts a list of sections.
|
||||
/// All .text sections containing code are
|
||||
/// put at the beginning of the binary file, in the order they
|
||||
/// put at the beginning of the binary file, in the order they
|
||||
/// appear in the assembly file, except the "main" section,
|
||||
/// which is the entrypoint of our program and must be put
|
||||
/// at the very beginning.
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::AST::{Const, Operation};
|
||||
use super::ast::{Const, Operation};
|
||||
use Operation::*;
|
||||
|
||||
use log::*;
|
||||
@ -16,14 +16,12 @@ pub enum ParseError {
|
||||
/// represents the state of our parser.
|
||||
/// Sadly parsing is stateless,
|
||||
pub struct Parser {
|
||||
input: Vec<String>, // input file
|
||||
input: Vec<String>, // input file
|
||||
}
|
||||
|
||||
impl Parser {
|
||||
pub fn new(i: String) -> Self {
|
||||
Parser {
|
||||
input: sanitize(i),
|
||||
}
|
||||
Parser { input: sanitize(i) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,19 +87,20 @@ fn take_between(i: &str, start: &str, stop: &str) -> Option<(String, String)> {
|
||||
return take_alpha_till(&s1, stop);
|
||||
}
|
||||
|
||||
/// finds special escaped characters in a string
|
||||
/// (such as \n) and replaces them with the actual special
|
||||
/// character
|
||||
fn escaped_codes() {}
|
||||
|
||||
#[test]
|
||||
fn take_between_test() {
|
||||
fn take_between_test1() {
|
||||
assert_eq!(
|
||||
take_between("\"wow\" etc", "\"", "\""),
|
||||
Some(("wow".to_string(), " etc".to_string()))
|
||||
);
|
||||
}
|
||||
|
||||
/// finds special escaped characters in a string
|
||||
/// (such as \n) and replaces them with the actual special
|
||||
/// character
|
||||
/// #TODO: do we need this? I forgot.
|
||||
fn _escaped_codes() {}
|
||||
|
||||
//// SECTION PARSING
|
||||
|
||||
/// Enum to represent possible section content.
|
||||
@ -121,7 +120,6 @@ pub struct Section {
|
||||
pub content: SectionContent,
|
||||
}
|
||||
|
||||
|
||||
impl Parser {
|
||||
pub fn parse_sections(&self) -> Result<Vec<Section>, ParseError> {
|
||||
let mut res = vec![];
|
||||
@ -151,8 +149,12 @@ impl Parser {
|
||||
})
|
||||
}
|
||||
"asciiz" => {
|
||||
let Some(s) = lines.next() else {return Err(ParseError::UnexpectedEOF)};
|
||||
let Some((s, _)) = take_between(s.trim(), "\"", "\"") else {return Err(ParseError::BadSectionContent)};
|
||||
let Some(s) = lines.next() else {
|
||||
return Err(ParseError::UnexpectedEOF);
|
||||
};
|
||||
let Some((s, _)) = take_between(s.trim(), "\"", "\"") else {
|
||||
return Err(ParseError::BadSectionContent);
|
||||
};
|
||||
res.push(Section {
|
||||
name: name.trim().to_owned(),
|
||||
content: CString(s),
|
||||
@ -200,7 +202,9 @@ fn parse_code_line(i: &str) -> Result<Operation, ParseError> {
|
||||
// every operation has at most 3 arguments
|
||||
let mut bits = i.split_whitespace();
|
||||
trace!("current parse code line: {}", i);
|
||||
let Some(op) = bits.next() else {return Err(ParseError::BadInstruction)};
|
||||
let Some(op) = bits.next() else {
|
||||
return Err(ParseError::BadInstruction);
|
||||
};
|
||||
|
||||
// no type
|
||||
match op {
|
||||
@ -214,8 +218,12 @@ fn parse_code_line(i: &str) -> Result<Operation, ParseError> {
|
||||
};
|
||||
|
||||
// I-type
|
||||
let Some(r1) = bits.next() else {return Err(ParseError::BadInstruction)};
|
||||
let Some(r2) = bits.next() else {return Err(ParseError::BadInstruction)};
|
||||
let Some(r1) = bits.next() else {
|
||||
return Err(ParseError::BadInstruction);
|
||||
};
|
||||
let Some(r2) = bits.next() else {
|
||||
return Err(ParseError::BadInstruction);
|
||||
};
|
||||
|
||||
match op {
|
||||
"addi" => {
|
||||
@ -230,7 +238,9 @@ fn parse_code_line(i: &str) -> Result<Operation, ParseError> {
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let Some(r3) = bits.next() else {return Err(ParseError::BadInstruction)};
|
||||
let Some(r3) = bits.next() else {
|
||||
return Err(ParseError::BadInstruction);
|
||||
};
|
||||
|
||||
// R-type
|
||||
match op {
|
||||
@ -277,3 +287,17 @@ fn parse_const(i: &str) -> Result<Const, ParseError> {
|
||||
};
|
||||
return Ok(Const::C(num));
|
||||
}
|
||||
|
||||
/// TESTS
|
||||
|
||||
#[test]
|
||||
fn parser_test() {
|
||||
let code = std::fs::read_to_string("./tests/assembly/hello_world.grasm").unwrap();
|
||||
|
||||
let parser = Parser::new(code);
|
||||
|
||||
let _r = parser.parse_sections();
|
||||
|
||||
// #TODO: WRITE PARSER TEST SUITE!
|
||||
//assert_eq!(r, Ok(vec![]));
|
||||
}
|
||||
|
@ -1,18 +0,0 @@
|
||||
// use super::*;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::assembler::parser;
|
||||
|
||||
#[test]
|
||||
fn parser_test() {
|
||||
println!("Parser test begins");
|
||||
let code = std::fs::read_to_string("./tests/assembly/hello_world.grasm").unwrap();
|
||||
|
||||
let parser = parser::Parser::new(code);
|
||||
|
||||
let r = parser.parse_sections().unwrap();
|
||||
|
||||
println!("Parsed sections: {:?}", r);
|
||||
}
|
||||
}
|
@ -6,7 +6,6 @@ pub mod cpu;
|
||||
pub mod jit;
|
||||
pub mod loader;
|
||||
pub mod pretty_printers;
|
||||
//
|
||||
|
||||
pub fn interpret_as_signed(x: u16) -> i16 {
|
||||
// the two types have the same size.
|
||||
@ -28,8 +27,8 @@ pub fn transmute_to_vecu16_as_is(x: Vec<u8>) -> Vec<u16> {
|
||||
//
|
||||
let bytes: Vec<u16> = {
|
||||
let mut res = vec![];
|
||||
// highly cursed: depends on the order in which the arguments of a tuple are
|
||||
// evaluated. Does its job!
|
||||
// Depends on the order in which the arguments of a tuple are
|
||||
// evaluated. Rust guarantees to be left-to-right.
|
||||
while let (Some(word0), Some(word1)) = (rb.next(), rb.next()) {
|
||||
// println!("Pair: {}, {}, word: {:?}", word0, word1, raw_bytes);
|
||||
res.push(((*word0 as u16) << 8) + (*word1 as u16));
|
||||
|
35
src/main.rs
35
src/main.rs
@ -1,4 +1,3 @@
|
||||
|
||||
use dekejit::assembler::parser;
|
||||
use dekejit::cli::{Cli, Subc::*};
|
||||
use dekejit::cpu::IOBuffer;
|
||||
@ -6,10 +5,10 @@ use dekejit::cpu::CPU;
|
||||
use dekejit::pretty_printers::*;
|
||||
|
||||
use clap::Parser;
|
||||
use dekejit::loader::loader::{prepare_memory, self};
|
||||
use dekejit::loader::loader::read_binary;
|
||||
use dekejit::loader::loader::{self, prepare_memory};
|
||||
use dekejit::transmute_to_vecu8_as_is;
|
||||
use log::{info, debug};
|
||||
use log::{debug, info};
|
||||
|
||||
fn main() {
|
||||
let cli: Cli = Cli::parse();
|
||||
@ -27,7 +26,6 @@ fn main() {
|
||||
|
||||
match cli.comm {
|
||||
Some(Run { filename }) => {
|
||||
|
||||
info!("Trying to read {}", filename);
|
||||
|
||||
let Ok(content) = std::fs::read(&filename) else {
|
||||
@ -35,7 +33,6 @@ fn main() {
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
let bytes = dekejit::transmute_to_vecu16_as_is(content.to_vec());
|
||||
|
||||
info!("Begin parsing file {}", &filename);
|
||||
@ -63,23 +60,21 @@ fn main() {
|
||||
};
|
||||
}
|
||||
Some(Build { filename, output }) => {
|
||||
|
||||
let Ok(inp_content) = std::fs::read_to_string(filename.clone()) else {
|
||||
println!("Could not read file {}", &filename);
|
||||
return;
|
||||
};
|
||||
|
||||
let prs = dekejit::assembler::parser::Parser::new(inp_content);
|
||||
let prs = dekejit::assembler::parser::Parser::new(inp_content);
|
||||
|
||||
let sections = match prs.parse_sections() {
|
||||
Ok(s) => s,
|
||||
Err(p_err) => {
|
||||
println!("Parser error: {:?}", p_err);
|
||||
return;
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
let Some(bin) = dekejit::assembler::to_binary(sections) else {
|
||||
println!("Unspecified error while converting file to binary. Must fix.");
|
||||
return;
|
||||
@ -93,18 +88,16 @@ fn main() {
|
||||
|
||||
let out_bin = transmute_to_vecu8_as_is(out_bin);
|
||||
|
||||
|
||||
info!("{:?}", out_bin);
|
||||
|
||||
match std::fs::write(output.clone(), out_bin) {
|
||||
Ok(_) => {},
|
||||
Ok(_) => {}
|
||||
Err(_) => {
|
||||
println!("could not write file {}", output);},
|
||||
println!("could not write file {}", output);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
Some(View {filename, format}) => {
|
||||
|
||||
Some(View { filename, format }) => {
|
||||
info!("Trying to read {}", filename);
|
||||
|
||||
let Ok(content) = std::fs::read_to_string(&filename) else {
|
||||
@ -114,10 +107,12 @@ fn main() {
|
||||
|
||||
let p = parser::Parser::new(content);
|
||||
|
||||
|
||||
let s = p.parse_sections().unwrap();
|
||||
|
||||
println!("{}", format_code(dekejit::pretty_printers::CodeWrapper::Asm(s), format).unwrap());
|
||||
println!(
|
||||
"{}",
|
||||
format_code(dekejit::pretty_printers::CodeWrapper::Asm(s), format).unwrap()
|
||||
);
|
||||
|
||||
// let Ok(content) = std::fs::read(&filename) else {
|
||||
// println!("File {} does not exist or cannot be read.", &filename);
|
||||
@ -139,15 +134,11 @@ fn main() {
|
||||
// };
|
||||
//
|
||||
// println!("{:?}", sections);
|
||||
|
||||
|
||||
}
|
||||
Some(Debug) => {},
|
||||
Some(Debug) => {}
|
||||
None => {}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// let parser = parser::Parser::new(code);
|
||||
//
|
||||
// let r = parser.parse_sections().unwrap();
|
||||
|
Loading…
Reference in New Issue
Block a user