cargo fmt
This commit is contained in:
parent
18a5f17b80
commit
0186f99678
@ -1,5 +1,5 @@
|
|||||||
mod AST;
|
mod AST;
|
||||||
mod tests;
|
|
||||||
mod parser;
|
mod parser;
|
||||||
|
mod tests;
|
||||||
|
|
||||||
struct Assembler {}
|
struct Assembler {}
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
use crate::cpu::Registers;
|
use super::AST::{Const, Operation};
|
||||||
|
|
||||||
use super::AST::{Operation, Const};
|
|
||||||
use Operation::*;
|
use Operation::*;
|
||||||
|
|
||||||
type Loc = u16;
|
type Loc = u16;
|
||||||
@ -11,7 +9,7 @@ pub enum ParseError {
|
|||||||
UnknownSectionKind,
|
UnknownSectionKind,
|
||||||
UnexpectedEOF,
|
UnexpectedEOF,
|
||||||
BadSectionContent,
|
BadSectionContent,
|
||||||
BadInstruction
|
BadInstruction,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// represents the state of our parser.
|
/// represents the state of our parser.
|
||||||
@ -49,27 +47,23 @@ fn remove_comments(i: &str) -> &str {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Checks if the string i starts with pat.
|
/// Checks if the string i starts with pat.
|
||||||
/// Returns the rest of the input string on success
|
/// Returns the rest of the input string on success
|
||||||
/// else, returns None
|
/// else, returns None
|
||||||
fn match_string(i: &str, pat: &str) -> Option<String> {
|
fn match_string(i: &str, pat: &str) -> Option<String> {
|
||||||
|
|
||||||
let mut in_chars = i.chars();
|
let mut in_chars = i.chars();
|
||||||
|
|
||||||
for pat_c in pat.chars() {
|
for pat_c in pat.chars() {
|
||||||
if let Some(c) = in_chars.next() {
|
if let Some(c) = in_chars.next() {
|
||||||
if c != pat_c {
|
if c != pat_c {
|
||||||
return None
|
return None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let rest = in_chars.collect();
|
let rest = in_chars.collect();
|
||||||
|
|
||||||
return Some(rest);
|
return Some(rest);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Matches till the "stop" string is found.
|
/// Matches till the "stop" string is found.
|
||||||
@ -79,41 +73,38 @@ fn match_string(i: &str, pat: &str) -> Option<String> {
|
|||||||
/// Ex: assert_eq!(Ok("Lorem ", " Ipsum"), match_alpha_till("Lorem X Ipsum", "X") );
|
/// Ex: assert_eq!(Ok("Lorem ", " Ipsum"), match_alpha_till("Lorem X Ipsum", "X") );
|
||||||
///
|
///
|
||||||
fn take_alpha_till(i: &str, stop: &str) -> Option<(String, String)> {
|
fn take_alpha_till(i: &str, stop: &str) -> Option<(String, String)> {
|
||||||
|
|
||||||
//
|
//
|
||||||
if let Some((matched, rest)) = i.split_once(stop) {
|
if let Some((matched, rest)) = i.split_once(stop) {
|
||||||
return Some((matched.to_string(), rest.to_string()))
|
return Some((matched.to_string(), rest.to_string()));
|
||||||
} else {
|
} else {
|
||||||
return None
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Matches inside the `start` and `stop` delimiters.
|
/// Matches inside the `start` and `stop` delimiters.
|
||||||
/// Return a tuple with the string in between the two
|
/// Return a tuple with the string in between the two
|
||||||
/// togheter with the rest of the string.
|
/// togheter with the rest of the string.
|
||||||
fn take_between(i: &str, start: &str, stop: &str) -> Option<(String, String)> {
|
fn take_between(i: &str, start: &str, stop: &str) -> Option<(String, String)> {
|
||||||
|
|
||||||
let s1 = match_string(i, start)?;
|
let s1 = match_string(i, start)?;
|
||||||
|
|
||||||
return take_alpha_till(&s1, stop);
|
return take_alpha_till(&s1, stop);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn take_between_test() {
|
fn take_between_test() {
|
||||||
assert_eq!(take_between("\"wow\" etc", "\"", "\""), Some(("wow".to_string(), " etc".to_string())));
|
assert_eq!(
|
||||||
|
take_between("\"wow\" etc", "\"", "\""),
|
||||||
|
Some(("wow".to_string(), " etc".to_string()))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//// SECTION PARSING
|
//// SECTION PARSING
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum SectionContent {
|
enum SectionContent {
|
||||||
Code(Vec<Operation>),
|
Code(Vec<Operation>),
|
||||||
CString(String),
|
CString(String),
|
||||||
CVec()
|
CVec(),
|
||||||
}
|
}
|
||||||
|
|
||||||
use SectionContent::*;
|
use SectionContent::*;
|
||||||
@ -126,7 +117,6 @@ pub struct Section {
|
|||||||
|
|
||||||
// A .section has a name and variable content.
|
// A .section has a name and variable content.
|
||||||
impl Parser {
|
impl Parser {
|
||||||
|
|
||||||
pub fn parse_sections(&mut self) -> Result<Vec<Section>, ParseError> {
|
pub fn parse_sections(&mut self) -> Result<Vec<Section>, ParseError> {
|
||||||
let mut res = vec![];
|
let mut res = vec![];
|
||||||
|
|
||||||
@ -141,50 +131,48 @@ impl Parser {
|
|||||||
|
|
||||||
match kind.as_str() {
|
match kind.as_str() {
|
||||||
"text" => {
|
"text" => {
|
||||||
let s : Vec<&str> = lines.clone().take_while(|&x| !(x).starts_with(".")).map(|x| x).collect();
|
let s: Vec<&str> = lines
|
||||||
res.push(Section { name: name.trim().to_owned(), content: Code(parse_code(&s)?)})
|
.clone()
|
||||||
|
.take_while(|&x| !(x).starts_with("."))
|
||||||
|
.map(|x| x)
|
||||||
|
.collect();
|
||||||
|
res.push(Section {
|
||||||
|
name: name.trim().to_owned(),
|
||||||
|
content: Code(parse_code(&s)?),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
"asciiz" => {
|
"asciiz" => {
|
||||||
let Some(s) = lines.next() else {return Err(ParseError::UnexpectedEOF)};
|
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, _)) = take_between(s.trim(), "\"", "\"") else {return Err(ParseError::BadSectionContent)};
|
||||||
res.push(Section { name: name.trim().to_owned(), content: CString(s)})
|
res.push(Section {
|
||||||
|
name: name.trim().to_owned(),
|
||||||
|
content: CString(s),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
"i16" => {
|
"i16" => {
|
||||||
let s = lines.next();
|
let _s = lines.next();
|
||||||
|
|
||||||
}
|
}
|
||||||
"u16" => {
|
"u16" => {
|
||||||
let s = lines.next();
|
let _s = lines.next();
|
||||||
|
|
||||||
}
|
}
|
||||||
"vi16" => {
|
"vi16" => {
|
||||||
let s = lines.next();
|
let _s = lines.next();
|
||||||
|
|
||||||
}
|
}
|
||||||
"vu16" => {
|
"vu16" => {
|
||||||
let s = lines.next();
|
let _s = lines.next();
|
||||||
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ParseError::UnknownSectionKind);
|
return Err(ParseError::UnknownSectionKind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
return Ok(res);
|
return Ok(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn parse_code(i: &[&str]) -> Result<Vec<Operation>, ParseError> {
|
fn parse_code(i: &[&str]) -> Result<Vec<Operation>, ParseError> {
|
||||||
|
|
||||||
let mut res = vec![];
|
let mut res = vec![];
|
||||||
|
|
||||||
for line in i {
|
for line in i {
|
||||||
@ -194,9 +182,7 @@ fn parse_code(i: &[&str]) -> Result<Vec<Operation>, ParseError> {
|
|||||||
return Ok(res);
|
return Ok(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn parse_code_line(i: &str) -> Result<Operation, ParseError> {
|
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();
|
||||||
println!("current parse code line: {}", i);
|
println!("current parse code line: {}", i);
|
||||||
@ -204,8 +190,12 @@ fn parse_code_line(i: &str) -> Result<Operation, ParseError> {
|
|||||||
|
|
||||||
// no type
|
// no type
|
||||||
match op {
|
match op {
|
||||||
"nop" => {return Ok(NOP);},
|
"nop" => {
|
||||||
"halt" => {return Ok(HALT);},
|
return Ok(NOP);
|
||||||
|
}
|
||||||
|
"halt" => {
|
||||||
|
return Ok(HALT);
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -219,28 +209,20 @@ fn parse_code_line(i: &str) -> Result<Operation, ParseError> {
|
|||||||
}
|
}
|
||||||
"sli" => {
|
"sli" => {
|
||||||
return Ok(SLI(r1.to_owned(), parse_const(r2)?));
|
return Ok(SLI(r1.to_owned(), parse_const(r2)?));
|
||||||
|
|
||||||
}
|
}
|
||||||
"call" => {
|
"call" => {
|
||||||
|
|
||||||
return Ok(CALL(r1.to_owned(), parse_const(r2)?));
|
return Ok(CALL(r1.to_owned(), parse_const(r2)?));
|
||||||
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return Err(ParseError::BadInstruction);
|
return Err(ParseError::BadInstruction);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_const(i: &str) -> Result<Const, ParseError> {
|
fn parse_const(i: &str) -> Result<Const, ParseError> {
|
||||||
|
|
||||||
// we try to parse the number, if we fail, we treat it as a string.
|
// we try to parse the number, if we fail, we treat it as a string.
|
||||||
let Ok(num) = i.parse() else {
|
let Ok(num) = i.parse() else {
|
||||||
return Ok(Const::CS(i.to_owned()));
|
return Ok(Const::CS(i.to_owned()));
|
||||||
};
|
};
|
||||||
return Ok(Const::C(num));
|
return Ok(Const::C(num));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
// use super::*;
|
// use super::*;
|
||||||
|
|
||||||
use crate::assembler::parser;
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
#[test]
|
use crate::assembler::parser;
|
||||||
fn parser_test() {
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parser_test() {
|
||||||
println!("Parser test begins");
|
println!("Parser test begins");
|
||||||
let code = std::fs::read_to_string("./tests/assembly/hello_world.grasm").unwrap();
|
let code = std::fs::read_to_string("./tests/assembly/hello_world.grasm").unwrap();
|
||||||
|
|
||||||
@ -13,4 +14,5 @@ fn parser_test() {
|
|||||||
let r = parser.parse_sections().unwrap();
|
let r = parser.parse_sections().unwrap();
|
||||||
|
|
||||||
println!("Parsed sections: {:?}", r);
|
println!("Parsed sections: {:?}", r);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,9 @@ mod decoder;
|
|||||||
mod ram;
|
mod ram;
|
||||||
mod registers;
|
mod registers;
|
||||||
mod sysenv;
|
mod sysenv;
|
||||||
|
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
pub use sysenv::*;
|
pub use sysenv::*;
|
||||||
|
|
||||||
pub use registers::*;
|
pub use registers::*;
|
||||||
|
@ -70,7 +70,7 @@ impl Sys for IOBuffer {
|
|||||||
.slice(pos, MAX_MEM as Word - 1)
|
.slice(pos, MAX_MEM as Word - 1)
|
||||||
.ok_or(ExecErr::InvalidMemoryAddr)?;
|
.ok_or(ExecErr::InvalidMemoryAddr)?;
|
||||||
let (s, _) = find_and_read_string(&data)
|
let (s, _) = find_and_read_string(&data)
|
||||||
.map_err(|p| ExecErr::SyscallError("parse error!".to_owned()))?;
|
.map_err(|_p| ExecErr::SyscallError("parse error!".to_owned()))?;
|
||||||
cpu.env.output.push_str(&s);
|
cpu.env.output.push_str(&s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
use super::*;
|
use crate::{
|
||||||
|
cpu::{IOBuffer, CPU},
|
||||||
use crate::loader::unloader::*;
|
loader::unloader::make_string,
|
||||||
|
};
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn hello_world_binary_test() {
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hello_world_binary_test() {
|
||||||
let hw = String::from("Hello world!");
|
let hw = String::from("Hello world!");
|
||||||
|
|
||||||
let mut k = make_string(&hw);
|
let mut k = make_string(&hw);
|
||||||
@ -30,6 +31,5 @@ fn hello_world_binary_test() {
|
|||||||
cpu.run_code_raw(&code);
|
cpu.run_code_raw(&code);
|
||||||
|
|
||||||
assert_eq!(hw, cpu.env.output);
|
assert_eq!(hw, cpu.env.output);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ pub mod loader;
|
|||||||
pub mod assembler;
|
pub mod assembler;
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
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.
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::cpu::Word;
|
use crate::cpu::Word;
|
||||||
|
|
||||||
use super::{constants::MAGIC, Section};
|
use super::Section;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ParseError {
|
pub enum ParseError {
|
||||||
@ -71,7 +71,7 @@ pub fn read_binary(b: &[u16]) -> Result<Vec<Section>, ParseError> {
|
|||||||
|
|
||||||
/// Parses binary headers
|
/// Parses binary headers
|
||||||
fn parse_header(b: &[Word]) -> Result<Vec<(u16, u16)>, ParseError> {
|
fn parse_header(b: &[Word]) -> Result<Vec<(u16, u16)>, ParseError> {
|
||||||
let Some([m, s]) = b.get(0..2) else {return Err(ParseError::EmptyHeader)};
|
let Some([_m, s]) = b.get(0..2) else {return Err(ParseError::EmptyHeader)};
|
||||||
|
|
||||||
// Magic number check. Can go unchecked, check spec.
|
// Magic number check. Can go unchecked, check spec.
|
||||||
// if (*m != MAGIC) {
|
// if (*m != MAGIC) {
|
||||||
|
@ -1,28 +1,31 @@
|
|||||||
use super::loader::*;
|
#[cfg(test)]
|
||||||
use super::unloader::*;
|
mod tests {
|
||||||
use super::*;
|
use crate::loader::Section;
|
||||||
|
|
||||||
// fuzzable, TODO
|
use super::super::loader::*;
|
||||||
fn write_read_str_identity(s: &str) {
|
use super::super::unloader::*;
|
||||||
let mut bytes = make_string(s);
|
|
||||||
|
// fuzzable, TODO
|
||||||
|
fn write_read_str_identity(s: &str) {
|
||||||
|
let bytes = make_string(s);
|
||||||
|
|
||||||
// pop null-terminator;
|
// pop null-terminator;
|
||||||
// bytes.pop().expect("String doesn't even have a single byte?");
|
// bytes.pop().expect("String doesn't even have a single byte?");
|
||||||
// println!("w-r s: {:?}, b: {:?}", s, bytes);
|
// println!("w-r s: {:?}, b: {:?}", s, bytes);
|
||||||
let (s0, _) = find_and_read_string(&bytes).unwrap();
|
let (s0, _) = find_and_read_string(&bytes).unwrap();
|
||||||
assert_eq!(s, &s0);
|
assert_eq!(s, &s0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_write_str_identity(b: Vec<u16>) {
|
fn read_write_str_identity(b: Vec<u16>) {
|
||||||
let (string, _) = find_and_read_string(&b).unwrap();
|
let (string, _) = find_and_read_string(&b).unwrap();
|
||||||
let mut n_term = b.clone();
|
let n_term = b.clone();
|
||||||
// n_term.push(0);
|
// n_term.push(0);
|
||||||
// println!("r-w s: {:?}, b: {:?}", string, n_term);
|
// println!("r-w s: {:?}, b: {:?}", string, n_term);
|
||||||
assert_eq!(n_term, make_string(&string));
|
assert_eq!(n_term, make_string(&string));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn label_parse_identity() {
|
fn label_parse_identity() {
|
||||||
let testwords = vec!["Hello,", "main", "è", "Hello,,", "v", "main", "pi"]; // should support utf-8
|
let testwords = vec!["Hello,", "main", "è", "Hello,,", "v", "main", "pi"]; // should support utf-8
|
||||||
//
|
//
|
||||||
for word in testwords {
|
for word in testwords {
|
||||||
@ -40,12 +43,12 @@ fn label_parse_identity() {
|
|||||||
read_write_str_identity(bytes);
|
read_write_str_identity(bytes);
|
||||||
println!("Done with {:?}", word);
|
println!("Done with {:?}", word);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Symbol table test
|
// Symbol table test
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn sy_test() {
|
fn sy_test() {
|
||||||
let fake_symbol_table: Vec<Section> = vec![
|
let fake_symbol_table: Vec<Section> = vec![
|
||||||
Section::new("v".to_owned(), &[1, 2, 3]),
|
Section::new("v".to_owned(), &[1, 2, 3]),
|
||||||
Section::new("pi".to_owned(), &[3]),
|
Section::new("pi".to_owned(), &[3]),
|
||||||
@ -58,4 +61,5 @@ fn sy_test() {
|
|||||||
|
|
||||||
let parsed_symbol_table = read_binary(&bin).expect("Wtf! We got error!");
|
let parsed_symbol_table = read_binary(&bin).expect("Wtf! We got error!");
|
||||||
println!("{:?}", parsed_symbol_table);
|
println!("{:?}", parsed_symbol_table);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,4 @@ fn main() {
|
|||||||
}
|
}
|
||||||
Err(e) => println!("Err: {:?}", e),
|
Err(e) => println!("Err: {:?}", e),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user