feat: add parsing for push

This commit is contained in:
Nat 2024-12-09 10:29:45 -08:00
parent 45ed7b2ba4
commit 9c2170299c
1 changed files with 48 additions and 20 deletions

View File

@ -6,11 +6,24 @@ use std::collections::{HashMap, BTreeMap, VecDeque};
use ponderosa::state::{Land, Rule};
macro_rules! assert_argument_count {
($tokens:expr, $count:expr) => {
if $tokens.len() < $count {
return Err("Too few arguments".to_owned());
}
if $tokens.len() > $count {
return Err("Too many arguments".to_owned());
}
};
}
fn parse_number(string: &str) -> u16 {
string.parse::<u16>().unwrap()
}
fn stack_bit(c: char) -> Result<u16, String> {
fn stack_bit(token: &String) -> Result<u16, String> {
let c = token.as_bytes()[0] as char;
match c {
'r' => Ok(0),
't' => Ok(1),
@ -18,27 +31,42 @@ fn stack_bit(c: char) -> Result<u16, String> {
}
}
fn parse_binary_math_format<'a>(tokens: &Vec<String>, opcode: u16, signed: bool) -> Result<u16, String> {
if tokens.len() < 4 { Err("Too few arguments".to_owned()) }
else if tokens.len() > 4 { Err("Too many arguments".to_owned()) }
else {
let left_parse = stack_bit(tokens[1].as_bytes()[0] as char);
let right_parse = stack_bit(tokens[2].as_bytes()[0] as char);
let dest_parse = stack_bit(tokens[3].as_bytes()[0] as char);
fn parse_unary_math_format<'a>(tokens: &Vec<String>, opcode: u16, signed: bool) -> Result<u16, String> {
assert_argument_count!(tokens, 4);
match (left_parse, right_parse, dest_parse) {
(Ok(left), Ok(right), Ok(dest)) => Ok(
opcode << 11 &
left << 10 &
right << 9 &
dest << 8 &
(signed as u16) << 7
),
(Err(e), _, _) => Err(e),
(_, Err(e), _) => Err(e),
(_, _, Err(e)) => Err(e),
}
let src = stack_bit(&tokens[1])?;
let dest = stack_bit(&tokens[2])?;
Ok(opcode<<11 & src<<9 & dest<<8 & (signed as u16)<<7)
}
fn parse_binary_math_format<'a>(tokens: &Vec<String>, opcode: u16, signed: bool) -> Result<u16, String> {
assert_argument_count!(tokens, 4);
let left = stack_bit(&tokens[1])?;
let right = stack_bit(&tokens[2])?;
let dest = stack_bit(&tokens[3])?;
Ok(opcode<<11 & left<<10 & right<<9 & dest<<8 & (signed as u16)<<7)
}
fn parse_push(tokens: &Vec<String>, opcode: u16, signed: bool) -> Result<u16, String> {
assert_argument_count!(tokens, 3);
let dest = stack_bit(&tokens[1])?;
let signed_immediate = tokens[2].parse::<i16>()
.map_err(|_| format!("Cannot parse number: {t}", t=tokens[2]))?;
let unsigned_immediate = tokens[2].parse::<u16>()
.map_err(|_| format!("Cannot parse number: {t}", t=tokens[2]))?;
let immediate = if signed { signed_immediate as u16 } else { unsigned_immediate };
if immediate > 511 {
return Err("Cannot push number larger than 511 due to bit width limitations".to_owned());
}
Ok(opcode<<11 & dest<<10 & (signed as u16) << 9 & immediate)
}
fn main() -> io::Result<()> {