Add OrParse trait to simplify chained parsers
parent
827aef74f8
commit
fc76248853
|
@ -34,6 +34,22 @@ trait OpcodeParser {
|
||||||
fn parse_opcode(data: &View) -> ParseResult;
|
fn parse_opcode(data: &View) -> ParseResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait OrParse<T> {
|
||||||
|
/// If the current parse failed to parse the given opcode (i.e. this is Err(UnknownOpcode)), attempt to
|
||||||
|
/// parse again with the given parse function. Otherwise, this result itself is returned.
|
||||||
|
fn or_parse<F: Fn(u8) -> Result<T, Error>>(self, parse_func: F) -> Result<T, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> OrParse<T> for Result<T, Error> {
|
||||||
|
fn or_parse<F: Fn(u8) -> Result<T, Error>>(self, parse_func: F) -> Result<T, Error> {
|
||||||
|
if let Err(Error::UnknownOpcode(opcode)) = self {
|
||||||
|
parse_func(opcode)
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// `next_instruction` will parse the next instruction from the given data stream. Returns either an error,
|
/// `next_instruction` will parse the next instruction from the given data stream. Returns either an error,
|
||||||
/// or the parsed instruction, and the number of bytes read.
|
/// or the parsed instruction, and the number of bytes read.
|
||||||
pub fn next_instruction(data: &View) -> ParseResult {
|
pub fn next_instruction(data: &View) -> ParseResult {
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::{
|
||||||
register,
|
register,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{OpcodeParser, ParseOutput};
|
use super::{OpcodeParser, OrParse, ParseOutput};
|
||||||
|
|
||||||
// similar to `arith8::Operand`, but only for the parts that can be uniquely determined from the opcode
|
// similar to `arith8::Operand`, but only for the parts that can be uniquely determined from the opcode
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
@ -25,7 +25,7 @@ pub struct Parser;
|
||||||
impl OpcodeParser for Parser {
|
impl OpcodeParser for Parser {
|
||||||
fn parse_opcode(data: &View) -> super::ParseResult {
|
fn parse_opcode(data: &View) -> super::ParseResult {
|
||||||
parse_eight_bit_arithmetic_instruction(data)
|
parse_eight_bit_arithmetic_instruction(data)
|
||||||
.or_else(|_err| parse_stack_pointer_adjust_instruction(data))
|
.or_parse(|_opcode| parse_stack_pointer_adjust_instruction(data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ fn parse_stack_pointer_adjust_instruction(data: &View) -> super::ParseResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn operation_for_opcode(opcode: u8) -> Result<Operation, super::Error> {
|
fn operation_for_opcode(opcode: u8) -> Result<Operation, super::Error> {
|
||||||
operation_for_binary_opcode(opcode).or_else(|_err| operation_for_unary_opcode(opcode))
|
operation_for_binary_opcode(opcode).or_parse(operation_for_unary_opcode)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn operand_for_opcode(opcode: u8) -> Result<OpcodeOperand, super::Error> {
|
fn operand_for_opcode(opcode: u8) -> Result<OpcodeOperand, super::Error> {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::cpu::instructions::load8::EightBitLoadInstruction;
|
use crate::cpu::instructions::load8::EightBitLoadInstruction;
|
||||||
use crate::cpu::instructions::Instruction;
|
use crate::cpu::instructions::Instruction;
|
||||||
use crate::cpu::parse::{self, Error, OpcodeParser, ParseOutput, ParseResult};
|
use crate::cpu::parse::{self, Error, OpcodeParser, OrParse, ParseOutput, ParseResult};
|
||||||
use crate::memory::{GetViewTuple, View};
|
use crate::memory::{GetViewTuple, View};
|
||||||
use crate::register;
|
use crate::register;
|
||||||
|
|
||||||
|
@ -8,25 +8,11 @@ use crate::register;
|
||||||
pub struct Parser;
|
pub struct Parser;
|
||||||
|
|
||||||
impl OpcodeParser for Parser {
|
impl OpcodeParser for Parser {
|
||||||
// Parses a single 8 bit instruction to load an 8 bit value to/from memory
|
|
||||||
fn parse_opcode(data: &View) -> ParseResult {
|
fn parse_opcode(data: &View) -> ParseResult {
|
||||||
let parse_funcs = &[
|
parse_load_from_register_to_address(data)
|
||||||
parse_load_from_register_to_address,
|
.or_parse(|_opcode| parse_load_from_address_to_register(data))
|
||||||
parse_load_from_address_to_register,
|
.or_parse(|_opcode| parse_load_immediate_instructions(data))
|
||||||
parse_load_immediate_instructions,
|
.or_parse(|_opcode| parse_load_from_register_to_address_and_do_arithmetic(data))
|
||||||
parse_load_from_register_to_address_and_do_arithmetic,
|
|
||||||
];
|
|
||||||
|
|
||||||
for parse_func in parse_funcs {
|
|
||||||
match parse_func(data) {
|
|
||||||
Ok(parsed_data) => return Ok(parsed_data),
|
|
||||||
Err(Error::UnknownOpcode(_)) => continue,
|
|
||||||
Err(err) => return Err(err),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let opcode = parse::get_opcode_from_data(data);
|
|
||||||
Err(Error::UnknownOpcode(opcode))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue