From ca23d53cc9220bb1841e555df33cca347be47211 Mon Sep 17 00:00:00 2001 From: Ryan Jones-Ward Date: Tue, 16 Jul 2024 12:04:15 +0100 Subject: [PATCH] Add some error checking and move some of the returned items into a holding struct instead, to keep things cleaner. --- redox-core/src/parsing/asm_parser.rs | 61 ++++++++++++---------- redox-core/src/parsing/data_declaration.rs | 39 ++++++++++++++ redox-core/src/parsing/mod.rs | 1 + redox-terminal/src/main.rs | 3 +- 4 files changed, 74 insertions(+), 30 deletions(-) create mode 100644 redox-core/src/parsing/data_declaration.rs diff --git a/redox-core/src/parsing/asm_parser.rs b/redox-core/src/parsing/asm_parser.rs index b0c5b2d..019324e 100644 --- a/redox-core/src/parsing/asm_parser.rs +++ b/redox-core/src/parsing/asm_parser.rs @@ -3,18 +3,18 @@ use std::{num::ParseIntError, str::FromStr}; use crate::{ ins::{ - expression::{ - Expression, - {ExpressionArgs::*, ExpressionOperator::*}, - }, + expression::{Expression, ExpressionArgs::*, ExpressionOperator::*}, instruction::Instruction, op_codes::OpCode, }, - parsing::type_hints::{ArgTypeHint, InstructionLookup}, + parsing::{ + data_declaration::DataDeclarationType, + type_hints::{ArgTypeHint, InstructionLookup}, + }, reg::registers::RegisterId, }; -use super::type_hints::InstructionHints; +use super::{data_declaration::DataDeclaration, type_hints::InstructionHints}; const F32_REGISTERS: [RegisterId; 2] = [RegisterId::FR1, RegisterId::FR2]; @@ -56,26 +56,6 @@ enum Argument { Expression(Expression), } -/// The supported data declaration command types. -#[derive(Debug, Clone)] -enum DataDeclarationType { - /// Declare a byte storage block. - DB, -} - -impl TryFrom<&str> for DataDeclarationType { - type Error = (); - - fn try_from(string: &str) -> Result { - match string.to_lowercase().as_str() { - "db" => Ok(DataDeclarationType::DB), - _ => { - panic!("invalid syntax - an unrecognized data declaration {string}"); - } - } - } -} - /// The sections that can be found in an valid file. enum FileSection { /// The text (code) section of an assembly file. @@ -138,6 +118,9 @@ pub struct AsmParser<'a> { /// A vector of the parsed instructions. pub parsed_instructions: Vec, + + /// A vector of the parsed data declarations. + pub parsed_data_declarations: Vec, } impl<'a> AsmParser<'a> { @@ -145,6 +128,7 @@ impl<'a> AsmParser<'a> { Self { hints: InstructionHints::new(), parsed_instructions: vec![], + parsed_data_declarations: vec![], } } @@ -155,6 +139,8 @@ impl<'a> AsmParser<'a> { /// * `string` - The string to be parsed. pub fn parse(&mut self, string: &str) { let mut instructions = Vec::with_capacity(100); + let mut data_declarations = Vec::::with_capacity(100); + let mut read_only_data_declarations = Vec::::with_capacity(100); // Convert newlines into a single type and automatically // allow lines ending with a \ to be treated as a singular line. @@ -177,12 +163,27 @@ impl<'a> AsmParser<'a> { FileSection::Text => { instructions.push(self.parse_code_line(line)); } - FileSection::Data => self.parse_data_line(line), - FileSection::ReadOnlyData => todo!(), + FileSection::Data => { + let (label, decl_type, bytes) = self.parse_data_line(line); + + if data_declarations.iter().any(|d| d.label == label) + || read_only_data_declarations.iter().any(|d| d.label == label) + { + panic!("invalid syntax - a duplicate label with the name of {label}."); + } + + data_declarations.push(DataDeclaration::new(decl_type, label, bytes)); + } + FileSection::ReadOnlyData => { + todo!(); + } } } self.parsed_instructions = instructions; + self.parsed_data_declarations = data_declarations; + + println!("{:#?}", self.parsed_data_declarations); } /// Parse a code line of an assembly file. @@ -394,7 +395,7 @@ impl<'a> AsmParser<'a> { /// # Arguments /// /// * `line` - A code line to be parsed. - fn parse_data_line(&mut self, line: &str) { + fn parse_data_line(&mut self, line: &str) -> (String, DataDeclarationType, Vec) { use unicode_segmentation::UnicodeSegmentation; let graphemes: Vec<&str> = line.graphemes(true).collect(); @@ -467,6 +468,8 @@ impl<'a> AsmParser<'a> { println!("label = {label}, declaration_type = {declaration_type:?}, storage = {storage:?}"); //println!("{:?}", String::from_utf8(storage)); + + (label.clone(), declaration_type, storage) } /// Parse a section line of an ASM file. diff --git a/redox-core/src/parsing/data_declaration.rs b/redox-core/src/parsing/data_declaration.rs new file mode 100644 index 0000000..2d2207d --- /dev/null +++ b/redox-core/src/parsing/data_declaration.rs @@ -0,0 +1,39 @@ +#[derive(Debug, Clone)] +pub struct DataDeclaration { + /// The [`DataDeclarationType`]. + pub declaration_type: DataDeclarationType, + /// The label associated with the statement. + pub label: String, + /// The stored bytes. + pub bytes: Vec, +} + +impl DataDeclaration { + pub fn new(declaration_type: DataDeclarationType, label: String, bytes: Vec) -> Self { + Self { + declaration_type, + label, + bytes, + } + } +} + +/// The supported data declaration statement types. +#[derive(Debug, Clone)] +pub enum DataDeclarationType { + /// Declare a byte storage block. + DB, +} + +impl TryFrom<&str> for DataDeclarationType { + type Error = (); + + fn try_from(string: &str) -> Result { + match string.to_lowercase().as_str() { + "db" => Ok(DataDeclarationType::DB), + _ => { + panic!("invalid syntax - an unrecognized data declaration {string}"); + } + } + } +} diff --git a/redox-core/src/parsing/mod.rs b/redox-core/src/parsing/mod.rs index 292da0b..4112322 100644 --- a/redox-core/src/parsing/mod.rs +++ b/redox-core/src/parsing/mod.rs @@ -1,2 +1,3 @@ pub mod asm_parser; +mod data_declaration; mod type_hints; diff --git a/redox-terminal/src/main.rs b/redox-terminal/src/main.rs index 067a620..3091442 100644 --- a/redox-terminal/src/main.rs +++ b/redox-terminal/src/main.rs @@ -67,7 +67,8 @@ fn main() { } let code = "section .data - banana db \"apples\",0xff + banana db \"apples\" + waffles db \"waffles\" section .text push 0 call :LABEL_1