Wrote AssemblerInstruction and Program parser
This commit is contained in:
parent
1af8f089c3
commit
4bfde58cc5
5 changed files with 98 additions and 7 deletions
|
@ -1,13 +1,15 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
pub mod instruction_parser;
|
||||||
pub mod opcode_parser;
|
pub mod opcode_parser;
|
||||||
pub mod operand_parser;
|
pub mod operand_parser;
|
||||||
|
pub mod program_parser;
|
||||||
pub mod register_parser;
|
pub mod register_parser;
|
||||||
|
|
||||||
use crate::instruction::Opcode;
|
use crate::instruction::Opcode;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum Token {
|
pub enum Token {
|
||||||
Op { code: Opcode },
|
Opcode { code: Opcode },
|
||||||
Register { reg_num: u8 },
|
Register { reg_num: u8 },
|
||||||
IntegerOperand { value: i32 },
|
Number { value: i32 },
|
||||||
}
|
}
|
||||||
|
|
55
src/assembler/instruction_parser.rs
Normal file
55
src/assembler/instruction_parser.rs
Normal file
|
@ -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<Token>,
|
||||||
|
op2: Option<Token>,
|
||||||
|
op3: Option<Token>,
|
||||||
|
}
|
||||||
|
|
||||||
|
named!(pub instruction_one<CompleteStr, AssemblerInstruction>,
|
||||||
|
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
|
||||||
|
}
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,8 +5,8 @@ use nom::{digit, types::CompleteStr};
|
||||||
use crate::assembler::Token;
|
use crate::assembler::Token;
|
||||||
use crate::instruction::Opcode;
|
use crate::instruction::Opcode;
|
||||||
|
|
||||||
named!(opcode_load<CompleteStr, Token>,
|
named!(pub opcode_load<CompleteStr, Token>,
|
||||||
do_parse!(tag!("load") >> (Token::Op{code: Opcode::LOAD}))
|
do_parse!(tag!("load") >> (Token::Opcode{code: Opcode::LOAD}))
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -18,7 +18,7 @@ mod opcode_parser_test {
|
||||||
// Test that opcode is dected and parsed correctly
|
// Test that opcode is dected and parsed correctly
|
||||||
let result = opcode_load(CompleteStr("load"));
|
let result = opcode_load(CompleteStr("load"));
|
||||||
let (rest, token) = result.unwrap();
|
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(""));
|
assert_eq!(rest, CompleteStr(""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ named!(pub integer_operand<CompleteStr, Token>,
|
||||||
tag!("#") >>
|
tag!("#") >>
|
||||||
reg_num: digit >>
|
reg_num: digit >>
|
||||||
(
|
(
|
||||||
Token::IntegerOperand{value: reg_num.parse::<i32>().unwrap()}
|
Token::Number{value: reg_num.parse::<i32>().unwrap()}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -25,6 +25,6 @@ mod reg_parser_test {
|
||||||
let result = integer_operand(CompleteStr("#10"));
|
let result = integer_operand(CompleteStr("#10"));
|
||||||
let (rest, value) = result.unwrap();
|
let (rest, value) = result.unwrap();
|
||||||
assert_eq!(rest, CompleteStr(""));
|
assert_eq!(rest, CompleteStr(""));
|
||||||
assert_eq!(value, Token::IntegerOperand { value: 10 });
|
assert_eq!(value, Token::Number { value: 10 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
34
src/assembler/program_parser.rs
Normal file
34
src/assembler/program_parser.rs
Normal file
|
@ -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<AssemblerInstruction>,
|
||||||
|
}
|
||||||
|
|
||||||
|
named!(pub program<CompleteStr, 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());
|
||||||
|
}
|
||||||
|
}
|
Reference in a new issue