138 lines
4.3 KiB
Rust
138 lines
4.3 KiB
Rust
use std::fmt::{Display, Formatter};
|
|
|
|
use vcore::opcodes::InvalidMnemonic;
|
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
|
pub struct Location {
|
|
pub line_num: usize,
|
|
pub file: String,
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
|
pub enum ParseError {
|
|
LineParseFailure,
|
|
InvalidInstruction(String),
|
|
}
|
|
|
|
impl Display for Location {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{}:{}", self.file, self.line_num)
|
|
}
|
|
}
|
|
|
|
impl Default for Location {
|
|
fn default() -> Self {
|
|
Location {
|
|
line_num: 0,
|
|
file: "<none>".to_string(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<usize> for Location {
|
|
fn from(line: usize) -> Self {
|
|
Self {
|
|
line_num: line,
|
|
file: "<none>".to_string(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> From<InvalidMnemonic<'a>> for ParseError {
|
|
fn from(err: InvalidMnemonic<'a>) -> Self {
|
|
Self::InvalidInstruction(err.0.into())
|
|
}
|
|
}
|
|
|
|
impl Display for ParseError {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
use ParseError::*;
|
|
match self {
|
|
LineParseFailure => write!(f, "Failed to parse line"),
|
|
InvalidInstruction(p) => write!(f, "Cannot parse {} as instruction", p),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub enum AssembleError {
|
|
ParseError(Location, ParseError),
|
|
EquResolveError(Location, String, EvalError),
|
|
EquDuplicateError(Location, String),
|
|
OrgResolveError(Location, EvalError),
|
|
ArgError(Location, EvalError),
|
|
NoCode,
|
|
IncludeError(Location, String),
|
|
FileError(String),
|
|
MacroError(Location),
|
|
}
|
|
|
|
impl AssembleError {
|
|
pub fn message(&self) -> String {
|
|
match self {
|
|
AssembleError::ParseError(_, err) => format!("Parse error: {}", err),
|
|
AssembleError::EquResolveError(_, name, _) => format!("Cannot resolve .equ {}", name),
|
|
AssembleError::EquDuplicateError(_, name) => format!("Duplicate .equ {}", name),
|
|
AssembleError::OrgResolveError(_, _) => "Cannot resolve .org".to_string(),
|
|
AssembleError::ArgError(_, _) => "Cannot calculate argument".to_string(),
|
|
AssembleError::NoCode => "No output would be generated by this code".to_string(),
|
|
AssembleError::IncludeError(_, file) => format!("Cannot read \"{}\"", file),
|
|
AssembleError::FileError(_) => "File read error".to_string(),
|
|
AssembleError::MacroError(_) => "Malformed macro control structure".to_string()
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Display for AssembleError {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
AssembleError::EquResolveError(line, name, err) => {
|
|
write!(f, "{} {} at {}: {}", self.message(), name, line, err)
|
|
}
|
|
AssembleError::EquDuplicateError(line, name) => {
|
|
write!(f, "{} {} at {}", self.message(), name, line)
|
|
}
|
|
AssembleError::OrgResolveError(line, err) |
|
|
AssembleError::ArgError(line, err) => {
|
|
write!(f, "{} at {}: {}", self.message(), line, err)
|
|
}
|
|
AssembleError::ParseError(line, err) => {
|
|
write!(f, "{} at {}: {}", self.message(), line, err)
|
|
}
|
|
AssembleError::NoCode => {
|
|
write!(f, "{}", self.message())
|
|
}
|
|
AssembleError::IncludeError(line, _) |
|
|
AssembleError::MacroError(line) => {
|
|
write!(f, "{} at {}", self.message(), line)
|
|
}
|
|
AssembleError::FileError(file) => {
|
|
write!(f, "{} in {}", self.message(), file)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub enum EvalError {
|
|
MissingLabel(String),
|
|
UnknownAddress(usize),
|
|
OffsetError(usize, i32),
|
|
}
|
|
|
|
impl Display for EvalError {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
EvalError::MissingLabel(label) => write!(f, "Unable to resolve label {}", label),
|
|
EvalError::UnknownAddress(line_num) => write!(
|
|
f,
|
|
"Unable to calculate starting address of line {}",
|
|
line_num
|
|
),
|
|
EvalError::OffsetError(line_num, offset) => {
|
|
write!(f, "Invalid line offset {} on line {}", offset, line_num)
|
|
}
|
|
}
|
|
}
|
|
}
|