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

View File

@ -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.

View File

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

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

View File

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