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:
raphy 2023-11-13 00:06:16 +01:00
parent 9358bfa77f
commit 8f894174d9
7 changed files with 69 additions and 73 deletions

View File

@ -1,9 +1,8 @@
use super::AST::*; use super::ast::*;
use crate::cpu::get_num; use crate::cpu::get_num;
use log::{trace, warn}; use log::{trace, warn};
/// Trait to represent a format we can translate our assembly to. /// Trait to represent a format we can translate our assembly to.
pub trait CodeFormat { pub trait CodeFormat {
fn encode_op(op: &Operation, sy: &SymbolTable, current_pc: u16) -> Option<Self> fn encode_op(op: &Operation, sy: &SymbolTable, current_pc: u16) -> Option<Self>
@ -36,7 +35,7 @@ impl SymbolTable {
// query, sy // query, sy
// ); // );
warn!("Symbol {} not found in symbol table.", query); warn!("Symbol {} not found in symbol table.", query);
return None return None;
} }
} }

View File

@ -1,14 +1,13 @@
mod AST; mod ast;
pub mod encoder; pub mod encoder;
pub mod parser; pub mod parser;
mod tests;
use encoder::CodeFormat; use encoder::CodeFormat;
use encoder::SymbolTable; use encoder::SymbolTable;
pub use AST::print_op; pub use ast::print_op;
use log::{trace, debug}; use log::{debug, trace};
use parser::Section; use parser::Section;
@ -26,7 +25,7 @@ impl Section {
// UTF-8 strings are collections of 8-bit chunks, but they're // UTF-8 strings are collections of 8-bit chunks, but they're
// packed into words of 16 bits + 16 bit NULL. // 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. // we add a 8 bit empty padding and then the NULL byte.
SectionContent::CString(s) => { SectionContent::CString(s) => {
let c = s.len(); let c = s.len();
@ -41,7 +40,7 @@ impl Section {
} }
/// Converts this section to binary. Needs symbol table to /// 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. /// this own section.
fn to_binary(&self, sy: &SymbolTable) -> Option<crate::loader::Section> { fn to_binary(&self, sy: &SymbolTable) -> Option<crate::loader::Section> {
let own_address = sy.lookup(&self.name)?; let own_address = sy.lookup(&self.name)?;
@ -63,17 +62,19 @@ impl Section {
return Some(crate::loader::Section::new(self.name.clone(), &res)); return Some(crate::loader::Section::new(self.name.clone(), &res));
} }
SectionContent::CString(s) => { 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!(), SectionContent::CVec() => todo!(),
} }
} }
} }
/// Sorts a list of sections. /// Sorts a list of sections.
/// All .text sections containing code are /// 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, /// appear in the assembly file, except the "main" section,
/// which is the entrypoint of our program and must be put /// which is the entrypoint of our program and must be put
/// at the very beginning. /// at the very beginning.

View File

@ -1,4 +1,4 @@
use super::AST::{Const, Operation}; use super::ast::{Const, Operation};
use Operation::*; use Operation::*;
use log::*; use log::*;
@ -16,14 +16,12 @@ pub enum ParseError {
/// represents the state of our parser. /// represents the state of our parser.
/// Sadly parsing is stateless, /// Sadly parsing is stateless,
pub struct Parser { pub struct Parser {
input: Vec<String>, // input file input: Vec<String>, // input file
} }
impl Parser { impl Parser {
pub fn new(i: String) -> Self { pub fn new(i: String) -> Self {
Parser { Parser { input: sanitize(i) }
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); 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] #[test]
fn take_between_test() { fn take_between_test1() {
assert_eq!( assert_eq!(
take_between("\"wow\" etc", "\"", "\""), take_between("\"wow\" etc", "\"", "\""),
Some(("wow".to_string(), " etc".to_string())) 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 //// SECTION PARSING
/// Enum to represent possible section content. /// Enum to represent possible section content.
@ -121,7 +120,6 @@ pub struct Section {
pub content: SectionContent, pub content: SectionContent,
} }
impl Parser { impl Parser {
pub fn parse_sections(&self) -> Result<Vec<Section>, ParseError> { pub fn parse_sections(&self) -> Result<Vec<Section>, ParseError> {
let mut res = vec![]; let mut res = vec![];
@ -151,8 +149,12 @@ impl Parser {
}) })
} }
"asciiz" => { "asciiz" => {
let Some(s) = lines.next() else {return Err(ParseError::UnexpectedEOF)}; let Some(s) = lines.next() else {
let Some((s, _)) = take_between(s.trim(), "\"", "\"") else {return Err(ParseError::BadSectionContent)}; return Err(ParseError::UnexpectedEOF);
};
let Some((s, _)) = take_between(s.trim(), "\"", "\"") else {
return Err(ParseError::BadSectionContent);
};
res.push(Section { res.push(Section {
name: name.trim().to_owned(), name: name.trim().to_owned(),
content: CString(s), content: CString(s),
@ -200,7 +202,9 @@ fn parse_code_line(i: &str) -> Result<Operation, ParseError> {
// every operation has at most 3 arguments // every operation has at most 3 arguments
let mut bits = i.split_whitespace(); let mut bits = i.split_whitespace();
trace!("current parse code line: {}", i); 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 // no type
match op { match op {
@ -214,8 +218,12 @@ fn parse_code_line(i: &str) -> Result<Operation, ParseError> {
}; };
// I-type // I-type
let Some(r1) = bits.next() else {return Err(ParseError::BadInstruction)}; let Some(r1) = bits.next() else {
let Some(r2) = bits.next() else {return Err(ParseError::BadInstruction)}; return Err(ParseError::BadInstruction);
};
let Some(r2) = bits.next() else {
return Err(ParseError::BadInstruction);
};
match op { match op {
"addi" => { "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 // R-type
match op { match op {
@ -277,3 +287,17 @@ fn parse_const(i: &str) -> Result<Const, ParseError> {
}; };
return Ok(Const::C(num)); 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![]));
}

View File

@ -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);
}
}

View File

@ -6,7 +6,6 @@ pub mod cpu;
pub mod jit; pub mod jit;
pub mod loader; pub mod loader;
pub mod pretty_printers; pub mod pretty_printers;
//
pub fn interpret_as_signed(x: u16) -> i16 { pub fn interpret_as_signed(x: u16) -> i16 {
// the two types have the same size. // 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 bytes: Vec<u16> = {
let mut res = vec![]; let mut res = vec![];
// highly cursed: depends on the order in which the arguments of a tuple are // Depends on the order in which the arguments of a tuple are
// evaluated. Does its job! // evaluated. Rust guarantees to be left-to-right.
while let (Some(word0), Some(word1)) = (rb.next(), rb.next()) { while let (Some(word0), Some(word1)) = (rb.next(), rb.next()) {
// println!("Pair: {}, {}, word: {:?}", word0, word1, raw_bytes); // println!("Pair: {}, {}, word: {:?}", word0, word1, raw_bytes);
res.push(((*word0 as u16) << 8) + (*word1 as u16)); res.push(((*word0 as u16) << 8) + (*word1 as u16));

View File

@ -1,4 +1,3 @@
use dekejit::assembler::parser; use dekejit::assembler::parser;
use dekejit::cli::{Cli, Subc::*}; use dekejit::cli::{Cli, Subc::*};
use dekejit::cpu::IOBuffer; use dekejit::cpu::IOBuffer;
@ -6,10 +5,10 @@ use dekejit::cpu::CPU;
use dekejit::pretty_printers::*; use dekejit::pretty_printers::*;
use clap::Parser; use clap::Parser;
use dekejit::loader::loader::{prepare_memory, self};
use dekejit::loader::loader::read_binary; use dekejit::loader::loader::read_binary;
use dekejit::loader::loader::{self, prepare_memory};
use dekejit::transmute_to_vecu8_as_is; use dekejit::transmute_to_vecu8_as_is;
use log::{info, debug}; use log::{debug, info};
fn main() { fn main() {
let cli: Cli = Cli::parse(); let cli: Cli = Cli::parse();
@ -27,7 +26,6 @@ fn main() {
match cli.comm { match cli.comm {
Some(Run { filename }) => { Some(Run { filename }) => {
info!("Trying to read {}", filename); info!("Trying to read {}", filename);
let Ok(content) = std::fs::read(&filename) else { let Ok(content) = std::fs::read(&filename) else {
@ -35,7 +33,6 @@ fn main() {
return; return;
}; };
let bytes = dekejit::transmute_to_vecu16_as_is(content.to_vec()); let bytes = dekejit::transmute_to_vecu16_as_is(content.to_vec());
info!("Begin parsing file {}", &filename); info!("Begin parsing file {}", &filename);
@ -63,23 +60,21 @@ fn main() {
}; };
} }
Some(Build { filename, output }) => { Some(Build { filename, output }) => {
let Ok(inp_content) = std::fs::read_to_string(filename.clone()) else { let Ok(inp_content) = std::fs::read_to_string(filename.clone()) else {
println!("Could not read file {}", &filename); println!("Could not read file {}", &filename);
return; 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() { let sections = match prs.parse_sections() {
Ok(s) => s, Ok(s) => s,
Err(p_err) => { Err(p_err) => {
println!("Parser error: {:?}", p_err); println!("Parser error: {:?}", p_err);
return; return;
}, }
}; };
let Some(bin) = dekejit::assembler::to_binary(sections) else { let Some(bin) = dekejit::assembler::to_binary(sections) else {
println!("Unspecified error while converting file to binary. Must fix."); println!("Unspecified error while converting file to binary. Must fix.");
return; return;
@ -93,18 +88,16 @@ fn main() {
let out_bin = transmute_to_vecu8_as_is(out_bin); let out_bin = transmute_to_vecu8_as_is(out_bin);
info!("{:?}", out_bin); info!("{:?}", out_bin);
match std::fs::write(output.clone(), out_bin) { match std::fs::write(output.clone(), out_bin) {
Ok(_) => {}, Ok(_) => {}
Err(_) => { 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); info!("Trying to read {}", filename);
let Ok(content) = std::fs::read_to_string(&filename) else { let Ok(content) = std::fs::read_to_string(&filename) else {
@ -114,10 +107,12 @@ fn main() {
let p = parser::Parser::new(content); let p = parser::Parser::new(content);
let s = p.parse_sections().unwrap(); 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 { // let Ok(content) = std::fs::read(&filename) else {
// println!("File {} does not exist or cannot be read.", &filename); // println!("File {} does not exist or cannot be read.", &filename);
@ -139,15 +134,11 @@ fn main() {
// }; // };
// //
// println!("{:?}", sections); // println!("{:?}", sections);
} }
Some(Debug) => {}, Some(Debug) => {}
None => {} None => {}
} }
// let parser = parser::Parser::new(code); // let parser = parser::Parser::new(code);
// //
// let r = parser.parse_sections().unwrap(); // let r = parser.parse_sections().unwrap();