Reformatting and cleanup

This commit is contained in:
2022-03-14 19:13:14 -05:00
parent d1e2c8ab6a
commit abf184f6fc
2 changed files with 137 additions and 63 deletions
+34 -17
View File
@@ -5,11 +5,16 @@ use pest::iterators::Pair;
use vcore::opcodes::Opcode; use vcore::opcodes::Opcode;
use crate::vasm_parser::*; use crate::parse_error::ParseError;
use crate::vasm_parser::{Rule, VASMParser};
/// A non-opcode directive to the assembler /// A non-opcode directive to the assembler
#[derive(Debug, PartialEq, Copy, Clone)] #[derive(Debug, PartialEq, Copy, Clone)]
pub enum Directive { Db, Equ, Org } pub enum Directive {
Db,
Equ,
Org,
}
impl From<Pair<'_, Rule>> for Directive { impl From<Pair<'_, Rule>> for Directive {
fn from(value: Pair<Rule>) -> Self { fn from(value: Pair<Rule>) -> Self {
@@ -18,7 +23,7 @@ impl From<Pair<'_, Rule>> for Directive {
".db" => Db, ".db" => Db,
".equ" => Equ, ".equ" => Equ,
".org" => Org, ".org" => Org,
_ => unreachable!() _ => unreachable!(),
} }
} }
} }
@@ -38,14 +43,20 @@ impl<'a> TryFrom<Pair<'a, Rule>> for Instruction {
match pair.as_rule() { match pair.as_rule() {
Rule::opcode => Ok(Instruction::Opcode(Opcode::try_from(pair.as_str())?)), Rule::opcode => Ok(Instruction::Opcode(Opcode::try_from(pair.as_str())?)),
Rule::directive => Ok(Instruction::Directive(Directive::from(pair))), Rule::directive => Ok(Instruction::Directive(Directive::from(pair))),
_ => Err(ParseError::InvalidInstruction(pair.as_str())) _ => Err(ParseError::InvalidInstruction(pair.as_str())),
} }
} }
} }
/// One of the five arithmetical operators /// One of the five arithmetical operators
#[derive(Debug, PartialEq, Copy, Clone)] #[derive(Debug, PartialEq, Copy, Clone)]
pub enum Operator { Add, Sub, Mul, Div, Mod } pub enum Operator {
Add,
Sub,
Mul,
Div,
Mod,
}
impl From<Pair<'_, Rule>> for Operator { impl From<Pair<'_, Rule>> for Operator {
fn from(s: Pair<Rule>) -> Self { fn from(s: Pair<Rule>) -> Self {
@@ -56,7 +67,7 @@ impl From<Pair<'_, Rule>> for Operator {
"*" => Mul, "*" => Mul,
"/" => Div, "/" => Div,
"%" => Mod, "%" => Mod,
_ => unreachable!() _ => unreachable!(),
} }
} }
} }
@@ -91,7 +102,7 @@ impl<'a> Node<'a> {
"\\0" => string.push_str("\0"), "\\0" => string.push_str("\0"),
"\\\\" => string.push_str("\\"), "\\\\" => string.push_str("\\"),
"\\\"" => string.push_str("\""), "\\\"" => string.push_str("\""),
_ => string.push_str(string_inner) _ => string.push_str(string_inner),
} }
} }
Node::String(string) Node::String(string)
@@ -103,11 +114,13 @@ impl<'a> Node<'a> {
let mut inner = pair.into_inner(); let mut inner = pair.into_inner();
let sign = inner.next().unwrap().as_str(); let sign = inner.next().unwrap().as_str();
let mut num = i32::from_str(inner.next().unwrap().as_str()).unwrap(); let mut num = i32::from_str(inner.next().unwrap().as_str()).unwrap();
if sign == "-" { num *= -1 } if sign == "-" {
num *= -1
}
match outer { match outer {
Rule::relative_line_offset => Node::RelativeOffset(num), Rule::relative_line_offset => Node::RelativeOffset(num),
Rule::absolute_line_offset => Node::AbsoluteOffset(num), Rule::absolute_line_offset => Node::AbsoluteOffset(num),
_ => unreachable!() _ => unreachable!(),
} }
} }
} }
@@ -133,20 +146,24 @@ impl<'a> TryFrom<Pair<'a, Rule>> for Node<'a> {
} }
Ok(Node::Expr(Box::from(first), rest)) Ok(Node::Expr(Box::from(first), rest))
} }
Rule::fact | Rule::number => { Rule::fact | Rule::number => Ok(Node::try_from(pair.into_inner().next().unwrap())?),
Ok(Node::try_from(pair.into_inner().next().unwrap())?)
}
Rule::dec_number | Rule::dec_zero | Rule::neg_number => { Rule::dec_number | Rule::dec_zero | Rule::neg_number => {
Ok(Node::Number(i32::from_str(pair.as_str()).unwrap())) Ok(Node::Number(i32::from_str(pair.as_str()).unwrap()))
} }
Rule::hex_number => { Ok(Node::Number(i32::from_str_radix(pair.as_str().get(2..).unwrap(), 16).unwrap())) } Rule::hex_number => Ok(Node::Number(
Rule::bin_number => { Ok(Node::Number(i32::from_str_radix(pair.as_str().get(2..).unwrap(), 2).unwrap())) } i32::from_str_radix(pair.as_str().get(2..).unwrap(), 16).unwrap(),
Rule::oct_number => { Ok(Node::Number(i32::from_str_radix(pair.as_str().get(2..).unwrap(), 8).unwrap())) } )),
Rule::string => { Ok(Node::string(pair)) } Rule::bin_number => Ok(Node::Number(
i32::from_str_radix(pair.as_str().get(2..).unwrap(), 2).unwrap(),
)),
Rule::oct_number => Ok(Node::Number(
i32::from_str_radix(pair.as_str().get(2..).unwrap(), 8).unwrap(),
)),
Rule::string => Ok(Node::string(pair)),
Rule::label => Ok(Node::Label(pair.as_str())), Rule::label => Ok(Node::Label(pair.as_str())),
Rule::relative_label => Ok(Node::RelativeLabel(pair.as_str().get(1..).unwrap())), Rule::relative_label => Ok(Node::RelativeLabel(pair.as_str().get(1..).unwrap())),
Rule::absolute_line_offset | Rule::relative_line_offset => Ok(Node::line_offset(pair)), Rule::absolute_line_offset | Rule::relative_line_offset => Ok(Node::line_offset(pair)),
_ => todo!() _ => todo!(),
} }
} }
} }
+103 -46
View File
@@ -6,9 +6,8 @@ use pest::Parser;
use vcore::opcodes::Opcode; use vcore::opcodes::Opcode;
pub use crate::ast::*; use crate::ast::{Directive, Instruction, Node, Operator, VASMLine};
use crate::ast::{Node, VASMLine}; use crate::parse_error::ParseError;
pub use crate::parse_error::ParseError;
#[derive(Parser)] #[derive(Parser)]
#[grammar = "vasm.pest"] #[grammar = "vasm.pest"]
@@ -26,7 +25,7 @@ fn shake(node: Node) -> Node {
Node::Expr(Box::from(shaken_car), shaken_cdr) Node::Expr(Box::from(shaken_car), shaken_cdr)
} }
} }
_ => node _ => node,
} }
} }
@@ -45,7 +44,8 @@ pub fn parse_vasm_line(line: &str) -> Result<VASMLine, ParseError<'_>> {
vasm_line = vasm_line.with_label(label.as_str()) vasm_line = vasm_line.with_label(label.as_str())
} }
if let Some(instruction_group) = pairs.next_if(|pair| pair.as_rule() == Rule::instruction_group) { if let Some(instruction_group) = pairs.next_if(|pair| pair.as_rule() == Rule::instruction_group)
{
let mut pairs = instruction_group.into_inner(); let mut pairs = instruction_group.into_inner();
vasm_line = vasm_line.with_instruction(Instruction::try_from(pairs.next().unwrap())?); vasm_line = vasm_line.with_instruction(Instruction::try_from(pairs.next().unwrap())?);
@@ -61,8 +61,8 @@ pub fn parse_vasm_line(line: &str) -> Result<VASMLine, ParseError<'_>> {
mod test { mod test {
use vcore::opcodes::Opcode::*; use vcore::opcodes::Opcode::*;
use super::*;
use super::Directive::*; use super::Directive::*;
use super::*;
impl<'a> VASMLine<'a> { impl<'a> VASMLine<'a> {
pub fn op(opcode: Opcode) -> VASMLine<'a> { pub fn op(opcode: Opcode) -> VASMLine<'a> {
@@ -70,15 +70,21 @@ mod test {
} }
fn op_number(opcode: Opcode, argument: i32) -> VASMLine<'a> { fn op_number(opcode: Opcode, argument: i32) -> VASMLine<'a> {
Self::blank().with_opcode(opcode).with_argument(Node::Number(argument)) Self::blank()
.with_opcode(opcode)
.with_argument(Node::Number(argument))
} }
fn op_label(opcode: Opcode, argument: &'a str) -> VASMLine<'a> { fn op_label(opcode: Opcode, argument: &'a str) -> VASMLine<'a> {
Self::blank().with_opcode(opcode).with_argument(Node::Label(argument)) Self::blank()
.with_opcode(opcode)
.with_argument(Node::Label(argument))
} }
fn op_rel_label(opcode: Opcode, argument: &'a str) -> VASMLine<'a> { fn op_rel_label(opcode: Opcode, argument: &'a str) -> VASMLine<'a> {
Self::blank().with_opcode(opcode).with_argument(Node::RelativeLabel(argument)) Self::blank()
.with_opcode(opcode)
.with_argument(Node::RelativeLabel(argument))
} }
fn op_off(opcode: Opcode, argument: Node<'a>) -> VASMLine<'a> { fn op_off(opcode: Opcode, argument: Node<'a>) -> VASMLine<'a> {
@@ -86,7 +92,9 @@ mod test {
} }
pub fn dir_str(directive: Directive, string: &str) -> VASMLine<'a> { pub fn dir_str(directive: Directive, string: &str) -> VASMLine<'a> {
Self::blank().with_directive(directive).with_argument(Node::String(string.to_string())) Self::blank()
.with_directive(directive)
.with_argument(Node::String(string.to_string()))
} }
} }
@@ -94,7 +102,10 @@ mod test {
fn test_parse() { fn test_parse() {
assert_eq!(parse_vasm_line("add"), Ok(VASMLine::op(Add))); assert_eq!(parse_vasm_line("add"), Ok(VASMLine::op(Add)));
assert_eq!(parse_vasm_line("sub"), Ok(VASMLine::op(Sub))); assert_eq!(parse_vasm_line("sub"), Ok(VASMLine::op(Sub)));
assert_eq!(parse_vasm_line("blah"), Err(ParseError::InvalidInstruction("blah"))); assert_eq!(
parse_vasm_line("blah"),
Err(ParseError::InvalidInstruction("blah"))
);
assert_eq!(parse_vasm_line("47"), Err(ParseError::LineParseFailure)); assert_eq!(parse_vasm_line("47"), Err(ParseError::LineParseFailure));
} }
@@ -102,65 +113,111 @@ mod test {
fn test_numbers() { fn test_numbers() {
assert_eq!(parse_vasm_line("add 45"), Ok(VASMLine::op_number(Add, 45))); assert_eq!(parse_vasm_line("add 45"), Ok(VASMLine::op_number(Add, 45)));
assert_eq!(parse_vasm_line("add 0"), Ok(VASMLine::op_number(Add, 0))); assert_eq!(parse_vasm_line("add 0"), Ok(VASMLine::op_number(Add, 0)));
assert_eq!(parse_vasm_line("add 0x10"), Ok(VASMLine::op_number(Add, 16))); assert_eq!(
assert_eq!(parse_vasm_line("add 0b1111"), Ok(VASMLine::op_number(Add, 15))); parse_vasm_line("add 0x10"),
assert_eq!(parse_vasm_line("add 0o377"), Ok(VASMLine::op_number(Add, 255))); Ok(VASMLine::op_number(Add, 16))
assert_eq!(parse_vasm_line("add -17"), Ok(VASMLine::op_number(Add, -17))); );
assert_eq!(
parse_vasm_line("add 0b1111"),
Ok(VASMLine::op_number(Add, 15))
);
assert_eq!(
parse_vasm_line("add 0o377"),
Ok(VASMLine::op_number(Add, 255))
);
assert_eq!(
parse_vasm_line("add -17"),
Ok(VASMLine::op_number(Add, -17))
);
} }
#[test] #[test]
fn test_strings() { fn test_strings() {
assert_eq!(parse_vasm_line(".db \"blah\""), Ok(VASMLine::dir_str(Db, "blah"))); assert_eq!(
assert_eq!(parse_vasm_line(".db \"blah\\twith escapes\\0\""), Ok(VASMLine::dir_str(Db, "blah\twith escapes\0"))) parse_vasm_line(".db \"blah\""),
Ok(VASMLine::dir_str(Db, "blah"))
);
assert_eq!(
parse_vasm_line(".db \"blah\\twith escapes\\0\""),
Ok(VASMLine::dir_str(Db, "blah\twith escapes\0"))
)
} }
#[test] #[test]
fn test_exprs() { fn test_exprs() {
assert_eq!(parse_vasm_line("add 2 + 3 * (4 - 5) + 6"), Ok( assert_eq!(
VASMLine::op(Add) parse_vasm_line("add 2 + 3 * (4 - 5) + 6"),
.with_argument( Ok(VASMLine::op(Add).with_argument(Node::Expr(
Node::Expr( Box::from(Node::Number(2)),
Box::from(Node::Number(2)), vec![
vec![ (
( Operator::Add,
Operator::Add, Node::Expr(
Box::from(Node::Number(3)),
vec![(
Operator::Mul,
Node::Expr( Node::Expr(
Box::from(Node::Number(3)), Box::from(Node::Number(4)),
vec![ vec![(Operator::Sub, Node::Number(5))],
( )
Operator::Mul, )],
Node::Expr( )
Box::from(Node::Number(4)), ),
vec![(Operator::Sub, Node::Number(5))], (Operator::Add, Node::Number(6))
))], )), ],
( )))
Operator::Add, );
Node::Number(6)
)], ))));
} }
#[test] #[test]
fn test_expr_labels() { fn test_expr_labels() {
assert_eq!(parse_vasm_line("loadw foo"), Ok(VASMLine::op_label(Loadw, "foo"))); assert_eq!(
assert_eq!(parse_vasm_line("brz @blah"), Ok(VASMLine::op_rel_label(Brz, "blah"))) parse_vasm_line("loadw foo"),
Ok(VASMLine::op_label(Loadw, "foo"))
);
assert_eq!(
parse_vasm_line("brz @blah"),
Ok(VASMLine::op_rel_label(Brz, "blah"))
)
} }
#[test] #[test]
fn test_expr_offsets() { fn test_expr_offsets() {
assert_eq!(parse_vasm_line("jmp $-2"), Ok(VASMLine::op_off(Jmp, Node::AbsoluteOffset(-2)))); assert_eq!(
assert_eq!(parse_vasm_line("brz @+3"), Ok(VASMLine::op_off(Brz, Node::RelativeOffset(3)))) parse_vasm_line("jmp $-2"),
Ok(VASMLine::op_off(Jmp, Node::AbsoluteOffset(-2)))
);
assert_eq!(
parse_vasm_line("brz @+3"),
Ok(VASMLine::op_off(Brz, Node::RelativeOffset(3)))
)
} }
#[test] #[test]
fn test_parse_labels() { fn test_parse_labels() {
assert_eq!(parse_vasm_line("foo: add"), Ok(VASMLine::op(Add).with_label("foo"))); assert_eq!(
assert_eq!(parse_vasm_line("bar:"), Ok(VASMLine::blank().with_label("bar"))); parse_vasm_line("foo: add"),
assert_eq!(parse_vasm_line("foo: add 43"), Ok(VASMLine::op_number(Add, 43).with_label("foo"))); Ok(VASMLine::op(Add).with_label("foo"))
);
assert_eq!(
parse_vasm_line("bar:"),
Ok(VASMLine::blank().with_label("bar"))
);
assert_eq!(
parse_vasm_line("foo: add 43"),
Ok(VASMLine::op_number(Add, 43).with_label("foo"))
);
} }
#[test] #[test]
fn test_parse_directives() { fn test_parse_directives() {
assert_eq!(parse_vasm_line("foo: .equ"), Ok(VASMLine::blank().with_label("foo").with_directive(Equ))); assert_eq!(
assert_eq!(parse_vasm_line(".db"), Ok(VASMLine::blank().with_directive(Db))); parse_vasm_line("foo: .equ"),
Ok(VASMLine::blank().with_label("foo").with_directive(Equ))
);
assert_eq!(
parse_vasm_line(".db"),
Ok(VASMLine::blank().with_directive(Db))
);
} }
} }