assembler: use common to match registers

This commit is contained in:
2025-06-25 19:29:56 +01:00
parent d9807b5b36
commit 68e459f32b
4 changed files with 46 additions and 28 deletions
+4 -2
View File
@@ -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]
+10 -1
View File
@@ -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)]
+30 -17
View File
@@ -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)> {
+2 -8
View File
@@ -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}");
} }