From 4bfde58cc599b074488d46bc4396c979344746b3 Mon Sep 17 00:00:00 2001 From: Anthony Foxclaw <35226681+tonytins@users.noreply.github.com> Date: Fri, 7 Feb 2020 21:49:56 -0500 Subject: [PATCH] Wrote AssemblerInstruction and Program parser --- src/assembler.rs | 6 ++-- src/assembler/instruction_parser.rs | 55 +++++++++++++++++++++++++++++ src/assembler/opcode_parser.rs | 6 ++-- src/assembler/operand_parser.rs | 4 +-- src/assembler/program_parser.rs | 34 ++++++++++++++++++ 5 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 src/assembler/instruction_parser.rs create mode 100644 src/assembler/program_parser.rs diff --git a/src/assembler.rs b/src/assembler.rs index 9934471..087dc0d 100644 --- a/src/assembler.rs +++ b/src/assembler.rs @@ -1,13 +1,15 @@ #![allow(dead_code)] +pub mod instruction_parser; pub mod opcode_parser; pub mod operand_parser; +pub mod program_parser; pub mod register_parser; use crate::instruction::Opcode; #[derive(Debug, PartialEq)] pub enum Token { - Op { code: Opcode }, + Opcode { code: Opcode }, Register { reg_num: u8 }, - IntegerOperand { value: i32 }, + Number { value: i32 }, } diff --git a/src/assembler/instruction_parser.rs b/src/assembler/instruction_parser.rs new file mode 100644 index 0000000..9fc9138 --- /dev/null +++ b/src/assembler/instruction_parser.rs @@ -0,0 +1,55 @@ +use nom::*; +use crate::assembler::Token; +use crate::assembler::opcode_parser::opcode_load; +use crate::assembler::operand_parser::integer_operand; +use crate::assembler::register_parser::register; + +use nom::types::CompleteStr; +use nom::*; + +#[derive(Debug, PartialEq)] +pub struct AssemblerInstruction { + opcode: Token, + op1: Option, + op2: Option, + op3: Option, +} + +named!(pub instruction_one, + do_parse!( + o: opcode_load >> + r: register >> + i: integer_operand >> + ( + AssemblerInstruction{ + opcode: o, + op1: Some(r), + op2: Some(i), + op3: None + } + ) + ) +); + +#[cfg(test)] +mod instruction_parser_test { + use super::*; + use crate::instruction::Opcode; + + #[test] + fn test_parse_instruction() { + let result = instruction_one(CompleteStr("load $0 #100\n")); + assert_eq!( + result, + Ok(( + CompleteStr(""), + AssemblerInstruction { + opcode: Token::Opcode { code: Opcode::LOAD }, + op1: Some(Token::Register { reg_num: 0 }), + op2: Some(Token::Number { value: 100 }), + op3: None + } + )) + ); + } +} diff --git a/src/assembler/opcode_parser.rs b/src/assembler/opcode_parser.rs index b2a85fb..900515b 100644 --- a/src/assembler/opcode_parser.rs +++ b/src/assembler/opcode_parser.rs @@ -5,8 +5,8 @@ use nom::{digit, types::CompleteStr}; use crate::assembler::Token; use crate::instruction::Opcode; -named!(opcode_load, - do_parse!(tag!("load") >> (Token::Op{code: Opcode::LOAD})) +named!(pub opcode_load, + do_parse!(tag!("load") >> (Token::Opcode{code: Opcode::LOAD})) ); #[cfg(test)] @@ -18,7 +18,7 @@ mod opcode_parser_test { // Test that opcode is dected and parsed correctly let result = opcode_load(CompleteStr("load")); let (rest, token) = result.unwrap(); - assert_eq!(token, Token::Op { code: Opcode::LOAD }); + assert_eq!(token, Token::Opcode { code: Opcode::LOAD }); assert_eq!(rest, CompleteStr("")); } } diff --git a/src/assembler/operand_parser.rs b/src/assembler/operand_parser.rs index 0e5fc4a..110d9fe 100644 --- a/src/assembler/operand_parser.rs +++ b/src/assembler/operand_parser.rs @@ -10,7 +10,7 @@ named!(pub integer_operand, tag!("#") >> reg_num: digit >> ( - Token::IntegerOperand{value: reg_num.parse::().unwrap()} + Token::Number{value: reg_num.parse::().unwrap()} ) ) ) @@ -25,6 +25,6 @@ mod reg_parser_test { let result = integer_operand(CompleteStr("#10")); let (rest, value) = result.unwrap(); assert_eq!(rest, CompleteStr("")); - assert_eq!(value, Token::IntegerOperand { value: 10 }); + assert_eq!(value, Token::Number { value: 10 }); } } diff --git a/src/assembler/program_parser.rs b/src/assembler/program_parser.rs new file mode 100644 index 0000000..bfdf5eb --- /dev/null +++ b/src/assembler/program_parser.rs @@ -0,0 +1,34 @@ +use nom::types::CompleteStr; +use nom::*; + +use crate::assembler::instruction_parser::{instruction_one, AssemblerInstruction}; + +#[derive(Debug, PartialEq)] +pub struct Program { + instructions: Vec, +} + +named!(pub program, + do_parse!( + instructions: many1!(instruction_one) >> + ( + Program { + instructions + } + ) + ) +); + +#[cfg(test)] +mod instruction_parser_test { + use super::*; + use crate::instruction::Opcode; + + #[test] + fn test_parse_instruction() { + let result = program(CompleteStr("load $0 #100\n")); + let (leftover, p) = result.unwrap(); + assert_eq!(leftover, CompleteStr("")); + assert_eq!(1, p.instructions.len()); + } +}