assembler: use common to match registers
This commit is contained in:
@@ -2,6 +2,8 @@
|
|||||||
//! easier to build from scratch and edit his code than it would be to try and wrangle it
|
//! easier to build from scratch and edit his code than it would be to try and wrangle it
|
||||||
//! into shape.
|
//! into shape.
|
||||||
|
|
||||||
|
use common::prelude::*;
|
||||||
|
|
||||||
use crate::source::{
|
use crate::source::{
|
||||||
source_info::SourceInfo,
|
source_info::SourceInfo,
|
||||||
token_info::{
|
token_info::{
|
||||||
@@ -71,8 +73,8 @@ impl Token {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn register(name: String, source_info: SourceInfo) -> Self {
|
pub const fn register(reg: Register, source_info: SourceInfo) -> Self {
|
||||||
Self::new(TokenType::Register(RegisterToken { name }), source_info)
|
Self::new(TokenType::Register(RegisterToken { reg }), source_info)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use common::prelude::Register;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct SymbolToken {
|
pub struct SymbolToken {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@@ -15,7 +17,14 @@ pub struct DirectiveToken {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct RegisterToken {
|
pub struct RegisterToken {
|
||||||
pub name: String,
|
pub reg: Register,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegisterToken {
|
||||||
|
/// Returns the name of a valid [`Register`]
|
||||||
|
pub fn name(&self) -> String {
|
||||||
|
self.reg.to_string()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ use std::{
|
|||||||
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
|
use common::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::AssemblerContext,
|
context::AssemblerContext,
|
||||||
error::{AssembleError, AssembleErrorKind, IoError, IoErrorKind},
|
error::{AssembleError, AssembleErrorKind, IoError, IoErrorKind},
|
||||||
@@ -36,10 +38,10 @@ pub struct Tokeniser {
|
|||||||
|
|
||||||
// Pre-compiled regex patterns
|
// Pre-compiled regex patterns
|
||||||
label_regex: Regex,
|
label_regex: Regex,
|
||||||
register_regex: Regex,
|
// register_regex: Regex,
|
||||||
immediate_regex: Regex,
|
immediate_regex: Regex,
|
||||||
directive_regex: Regex,
|
directive_regex: Regex,
|
||||||
instruction_regex: Regex,
|
// instruction_regex: Regex,
|
||||||
symbol_regex: Regex,
|
symbol_regex: Regex,
|
||||||
string_regex: Regex,
|
string_regex: Regex,
|
||||||
comment_regex: Regex,
|
comment_regex: Regex,
|
||||||
@@ -54,18 +56,18 @@ impl Tokeniser {
|
|||||||
|
|
||||||
label_regex: Regex::new(r"^([a-zA-Z_][a-zA-Z0-9_]*):")
|
label_regex: Regex::new(r"^([a-zA-Z_][a-zA-Z0-9_]*):")
|
||||||
.expect("Failed to compile label regex pattern"),
|
.expect("Failed to compile label regex pattern"),
|
||||||
register_regex: Regex::new(r"^(r[0-9]+|sp|fp|pc)")
|
// register_regex: Regex::new(r"^(r[0-9]+|sp|fp|pc)")
|
||||||
.expect("Failed to compile register regex pattern"),
|
// .expect("Failed to compile register regex pattern"),
|
||||||
immediate_regex: Regex::new(
|
immediate_regex: Regex::new(
|
||||||
r"^(0x[0-9a-fA-F_]+|0b[0-1_]+|0o[0-7_]+|[0-9_]+)",
|
r"^(0x[0-9a-fA-F_]+|0b[0-1_]+|0o[0-7_]+|[0-9_]+)",
|
||||||
)
|
)
|
||||||
.expect("Failed to compile immediate regex pattern"),
|
.expect("Failed to compile immediate regex pattern"),
|
||||||
directive_regex: Regex::new(r"^\.([a-zA-Z]+)")
|
directive_regex: Regex::new(r"^\.([a-zA-Z]+)")
|
||||||
.expect("Failed to compile directive regex pattern"),
|
.expect("Failed to compile directive regex pattern"),
|
||||||
instruction_regex: Regex::new(
|
// instruction_regex: Regex::new(
|
||||||
r"^(add|sub|mul|div|jmp|call|ret|lli|nop|halt)",
|
// r"^(add|sub|mul|div|jmp|call|ret|lli|nop|halt)",
|
||||||
)
|
// )
|
||||||
.expect("Failed to compile instruction regex pattern"),
|
// .expect("Failed to compile instruction regex pattern"),
|
||||||
symbol_regex: Regex::new(r"^([a-zA-Z_][a-zA-Z0-9_]*)")
|
symbol_regex: Regex::new(r"^([a-zA-Z_][a-zA-Z0-9_]*)")
|
||||||
.expect("Failed to compile symbol regex pattern"),
|
.expect("Failed to compile symbol regex pattern"),
|
||||||
string_regex: Regex::new(r#"^"([^"]*)"#)
|
string_regex: Regex::new(r#"^"([^"]*)"#)
|
||||||
@@ -186,11 +188,19 @@ impl Tokeniser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn try_match_register(&self, input: &str) -> Option<(TokenType, usize)> {
|
fn try_match_register(&self, input: &str) -> Option<(TokenType, usize)> {
|
||||||
let caps = self.register_regex.captures(input)?;
|
_ = self;
|
||||||
let name = caps.get(1)?.as_str().to_string();
|
|
||||||
let len = caps.get(0)?.len();
|
|
||||||
|
|
||||||
Some((TokenType::Register(RegisterToken { name }), len))
|
let reg = match Register::try_from(input) {
|
||||||
|
Ok(reg) => reg,
|
||||||
|
Err(_why) => {
|
||||||
|
// Probably ignore the error.
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let len = input.len();
|
||||||
|
|
||||||
|
Some((TokenType::Register(RegisterToken { reg }), len))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_match_immediate(&self, input: &str) -> Option<(TokenType, usize)> {
|
fn try_match_immediate(&self, input: &str) -> Option<(TokenType, usize)> {
|
||||||
@@ -224,12 +234,15 @@ impl Tokeniser {
|
|||||||
Some((TokenType::Directive(DirectiveToken { directive }), len))
|
Some((TokenType::Directive(DirectiveToken { directive }), len))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_match_instruction(&self, input: &str) -> Option<(TokenType, usize)> {
|
const fn try_match_instruction(&self, _input: &str) -> Option<(TokenType, usize)> {
|
||||||
let caps = self.instruction_regex.captures(input)?;
|
_ = self;
|
||||||
let mnemonic = caps.get(1)?.as_str().to_string();
|
|
||||||
let len = caps.get(0)?.len();
|
|
||||||
|
|
||||||
Some((TokenType::Instruction(InstructionToken { mnemonic }), len))
|
// let instruction =
|
||||||
|
// Some((TokenType::Instruction(InstructionToken { mnemonic }), len))
|
||||||
|
|
||||||
|
// TODO: fix me.
|
||||||
|
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_match_symbol(&self, input: &str) -> Option<(TokenType, usize)> {
|
fn try_match_symbol(&self, input: &str) -> Option<(TokenType, usize)> {
|
||||||
|
|||||||
@@ -90,19 +90,13 @@ fn test_all_instructions() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_registers() {
|
fn test_registers() {
|
||||||
let test_cases = [
|
let test_cases = [("rg0", "r0"), ("rgf", "rgf"), ("pcx", "pcx")];
|
||||||
("r0", "r0"),
|
|
||||||
("r15", "r15"),
|
|
||||||
("sp", "sp"),
|
|
||||||
("fp", "fp"),
|
|
||||||
("pc", "pc"),
|
|
||||||
];
|
|
||||||
|
|
||||||
for (input, expected) in &test_cases {
|
for (input, expected) in &test_cases {
|
||||||
let tokens = tokenize_source(input).expect("Failed to tokenize register");
|
let tokens = tokenize_source(input).expect("Failed to tokenize register");
|
||||||
|
|
||||||
if let TokenType::Register(reg) = &tokens[0].token_type {
|
if let TokenType::Register(reg) = &tokens[0].token_type {
|
||||||
assert_eq!(reg.name, *expected);
|
assert_eq!(reg.reg.to_string(), *expected);
|
||||||
} else {
|
} else {
|
||||||
panic!("Expected register token for {input}");
|
panic!("Expected register token for {input}");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user