Big refactoring, invalid assembly is now unrepresentable assembly
This commit is contained in:
+38
-107
@@ -1,12 +1,10 @@
|
||||
use std::convert::TryFrom;
|
||||
use std::str::FromStr;
|
||||
|
||||
use pest::iterators::Pair;
|
||||
|
||||
use vcore::opcodes::Opcode;
|
||||
|
||||
use crate::parse_error::ParseError;
|
||||
use crate::vasm_parser::{Rule, VASMParser};
|
||||
use crate::vasm_parser::Rule;
|
||||
|
||||
/// A non-opcode directive to the assembler
|
||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
@@ -28,26 +26,6 @@ impl From<Pair<'_, Rule>> for Directive {
|
||||
}
|
||||
}
|
||||
|
||||
/// Either an opcode or a directive; something that lives in the
|
||||
/// instruction column of a line
|
||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
pub enum Instruction {
|
||||
Directive(Directive),
|
||||
Opcode(Opcode),
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<Pair<'a, Rule>> for Instruction {
|
||||
type Error = ParseError<'a>;
|
||||
|
||||
fn try_from(pair: Pair<'a, Rule>) -> Result<Self, Self::Error> {
|
||||
match pair.as_rule() {
|
||||
Rule::opcode => Ok(Instruction::Opcode(Opcode::try_from(pair.as_str())?)),
|
||||
Rule::directive => Ok(Instruction::Directive(Directive::from(pair))),
|
||||
_ => Err(ParseError::InvalidInstruction(pair.as_str())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// One of the five arithmetical operators
|
||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
pub enum Operator {
|
||||
@@ -96,12 +74,12 @@ impl<'a> Node<'a> {
|
||||
for inner in pair.into_inner() {
|
||||
let string_inner = inner.as_str();
|
||||
match string_inner {
|
||||
"\\t" => string.push_str("\t"),
|
||||
"\\r" => string.push_str("\r"),
|
||||
"\\n" => string.push_str("\n"),
|
||||
"\\0" => string.push_str("\0"),
|
||||
"\\\\" => string.push_str("\\"),
|
||||
"\\\"" => string.push_str("\""),
|
||||
"\\t" => string.push('\t'),
|
||||
"\\r" => string.push('\r'),
|
||||
"\\n" => string.push('\n'),
|
||||
"\\0" => string.push('\0'),
|
||||
"\\\\" => string.push('\\'),
|
||||
"\\\"" => string.push('\"'),
|
||||
_ => string.push_str(string_inner),
|
||||
}
|
||||
}
|
||||
@@ -125,102 +103,55 @@ impl<'a> Node<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<Pair<'a, Rule>> for Node<'a> {
|
||||
type Error = ParseError<'a>;
|
||||
|
||||
/// Attempt to parse a given pair into the `Node` it represents. The result of this is a
|
||||
impl<'a> From<Pair<'a, Rule>> for Node<'a> {
|
||||
/// Parse a given pair into the `Node` it represents. The result of this is a
|
||||
/// `Node` that might contain a borrow of part of the original code, but which in no way
|
||||
/// depends on the original pair's object model.
|
||||
fn try_from(pair: Pair<'a, Rule>) -> Result<Self, Self::Error> {
|
||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||
match pair.as_rule() {
|
||||
Rule::expr | Rule::term => {
|
||||
let mut iter = pair.into_inner();
|
||||
let first = Node::try_from(iter.next().unwrap())?;
|
||||
let first = Node::from(iter.next().unwrap());
|
||||
let mut rest = Vec::<(Operator, Node)>::new();
|
||||
|
||||
while let Some(operator) = iter.next() {
|
||||
let rhs = iter.next().unwrap();
|
||||
let op = Operator::from(operator);
|
||||
let node = Node::try_from(rhs)?;
|
||||
let node = Node::from(rhs);
|
||||
rest.push((op, node));
|
||||
}
|
||||
Ok(Node::Expr(Box::from(first), rest))
|
||||
Node::Expr(Box::from(first), rest)
|
||||
}
|
||||
Rule::fact | Rule::number => Ok(Node::try_from(pair.into_inner().next().unwrap())?),
|
||||
Rule::fact | Rule::number => Node::from(pair.into_inner().next().unwrap()),
|
||||
Rule::dec_number | Rule::dec_zero | Rule::neg_number => {
|
||||
Ok(Node::Number(i32::from_str(pair.as_str()).unwrap()))
|
||||
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::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::relative_label => Ok(Node::RelativeLabel(pair.as_str().get(1..).unwrap())),
|
||||
Rule::absolute_line_offset | Rule::relative_line_offset => Ok(Node::line_offset(pair)),
|
||||
_ => todo!(),
|
||||
Rule::hex_number => {
|
||||
Node::Number(i32::from_str_radix(pair.as_str().get(2..).unwrap(), 16).unwrap())
|
||||
}
|
||||
Rule::bin_number => {
|
||||
Node::Number(i32::from_str_radix(pair.as_str().get(2..).unwrap(), 2).unwrap())
|
||||
}
|
||||
Rule::oct_number => {
|
||||
Node::Number(i32::from_str_radix(pair.as_str().get(2..).unwrap(), 8).unwrap())
|
||||
}
|
||||
Rule::string => Node::string(pair),
|
||||
Rule::label => Node::Label(pair.as_str()),
|
||||
Rule::relative_label => Node::RelativeLabel(pair.as_str().get(1..).unwrap()),
|
||||
Rule::absolute_line_offset | Rule::relative_line_offset => Node::line_offset(pair),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct VASMLine<'a> {
|
||||
label: Option<&'a str>,
|
||||
instruction: Option<Instruction>,
|
||||
argument: Option<Node<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> VASMLine<'a> {
|
||||
pub fn blank() -> VASMLine<'a> {
|
||||
VASMLine {
|
||||
label: None,
|
||||
instruction: None,
|
||||
argument: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_instruction(self, instruction: Instruction) -> VASMLine<'a> {
|
||||
VASMLine {
|
||||
label: self.label,
|
||||
instruction: Some(instruction),
|
||||
argument: self.argument,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_opcode(self, opcode: Opcode) -> VASMLine<'a> {
|
||||
VASMLine {
|
||||
label: self.label,
|
||||
instruction: Some(Instruction::Opcode(opcode)),
|
||||
argument: self.argument,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_directive(self, directive: Directive) -> VASMLine<'a> {
|
||||
VASMLine {
|
||||
label: self.label,
|
||||
instruction: Some(Instruction::Directive(directive)),
|
||||
argument: self.argument,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_label(self, label: &'a str) -> Self {
|
||||
VASMLine {
|
||||
label: Some(label),
|
||||
instruction: self.instruction,
|
||||
argument: self.argument,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_argument(self, argument: Node<'a>) -> Self {
|
||||
VASMLine {
|
||||
label: self.label,
|
||||
instruction: self.instruction,
|
||||
argument: Some(argument),
|
||||
}
|
||||
}
|
||||
pub struct Label<'a>(pub &'a str);
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum VASMLine<'a> {
|
||||
Instruction(Option<Label<'a>>, Opcode, Option<Node<'a>>),
|
||||
Db(Option<Label<'a>>, Node<'a>),
|
||||
Org(Option<Label<'a>>, Node<'a>),
|
||||
Equ(Label<'a>, Node<'a>),
|
||||
LabelDef(Label<'a>),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user