Add OrParse trait to simplify chained parsers
parent
827aef74f8
commit
fc76248853
|
@ -34,6 +34,22 @@ trait OpcodeParser {
|
|||
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,
|
||||
/// or the parsed instruction, and the number of bytes read.
|
||||
pub fn next_instruction(data: &View) -> ParseResult {
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::{
|
|||
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
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
@ -25,7 +25,7 @@ pub struct Parser;
|
|||
impl OpcodeParser for Parser {
|
||||
fn parse_opcode(data: &View) -> super::ParseResult {
|
||||
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> {
|
||||
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> {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::cpu::instructions::load8::EightBitLoadInstruction;
|
||||
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::register;
|
||||
|
||||
|
@ -8,25 +8,11 @@ use crate::register;
|
|||
pub struct 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 {
|
||||
let parse_funcs = &[
|
||||
parse_load_from_register_to_address,
|
||||
parse_load_from_address_to_register,
|
||||
parse_load_immediate_instructions,
|
||||
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))
|
||||
parse_load_from_register_to_address(data)
|
||||
.or_parse(|_opcode| parse_load_from_address_to_register(data))
|
||||
.or_parse(|_opcode| parse_load_immediate_instructions(data))
|
||||
.or_parse(|_opcode| parse_load_from_register_to_address_and_do_arithmetic(data))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue