DRY arithmetic parsing

This commit is contained in:
2020-10-17 22:52:07 +02:00
parent 3999c51eb7
commit e560fc5657
2 changed files with 82 additions and 441 deletions
+53 -435
View File
@@ -11,27 +11,25 @@ use crate::defs::ArithOp;
pub(crate) fn parse<'a>(op_pos: &SourcePosition, keyword: &str, mut args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> {
Ok(ParseRes::ext(match keyword {
"cmp" => {
ArithOp::Compare {
a: args.next_rd()?,
b: args.next_rd()?,
}
let parsed = ArithOp::Compare { a: args.next_rd()?, b: args.next_rd()? };
args.ensure_empty("two input arguments")?;
parsed
}
"rcmp" => {
ArithOp::RangeTest {
val: args.next_rd()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
let parsed = ArithOp::RangeTest { val: args.next_rd()?, a: args.next_rd()?, b: args.next_rd()? };
args.ensure_empty("3 arguments (value, min, max)")?;
parsed
}
"tst" => {
let arg = args.next_rd()?;
args.ensure_empty("1 input argument")?;
ArithOp::Test { a: arg }
}
"rng" => {
match args.len() {
let parsed = match args.len() {
1 => {
ArithOp::Rng {
dst: args.next_wr()?,
@@ -56,94 +54,34 @@ pub(crate) fn parse<'a>(op_pos: &SourcePosition, keyword: &str, mut args: TokenP
_ => {
return Err(CrsnError::Parse("Rng requires 1, 2 or 3 arguments".into(), op_pos.clone()));
}
}
};
args.ensure_empty("1 (dst) or 3 (dst, min, max) arguments")?;
parsed
}
"inc" => {
let dst = args.next_rdwr()?;
ArithOp::Add {
dst: dst.wr(),
a: dst.rd(),
b: Rd::immediate(1),
}
let (dst, a) = args.parse_wr_rd()?;
ArithOp::Add { dst, a, b: Rd::immediate(1) }
}
"dec" => {
let dst = args.next_rdwr()?;
ArithOp::Sub {
dst: dst.wr(),
a: dst.rd(),
b: Rd::immediate(1),
}
let (dst, a) = args.parse_wr_rd()?;
ArithOp::Sub { dst, a, b: Rd::immediate(1) }
}
"add" => {
match args.len() {
3 => {
ArithOp::Add {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::Add {
dst: dst.wr(),
a: dst.rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("Add requires 2 or 3 arguments".into(), op_pos.clone()));
}
}
let (dst, a, b) = args.parse_wr_rd_rd()?;
ArithOp::Add { dst, a, b }
}
"sub" => {
match args.len() {
3 => {
ArithOp::Sub {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::Sub {
dst: dst.wr(),
a: dst.rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("Sub requires 2 or 3 arguments".into(), op_pos.clone()));
}
}
let (dst, a, b) = args.parse_wr_rd_rd()?;
ArithOp::Sub { dst, a, b }
}
"mul" => {
match args.len() {
3 => {
ArithOp::Mul {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::Mul {
dst: dst.wr(),
a: dst.rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("Mul requires 2 or 3 arguments".into(), op_pos.clone()));
}
}
let (dst, a, b) = args.parse_wr_rd_rd()?;
ArithOp::Mul { dst, a, b }
}
"divr" => {
@@ -174,403 +112,83 @@ pub(crate) fn parse<'a>(op_pos: &SourcePosition, keyword: &str, mut args: TokenP
}
"div" => {
match args.len() {
3 => {
ArithOp::Div {
dst: args.next_wr()?,
rem: Wr::discard(),
a: args.next_rd()?,
div: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
let div = args.next_rd()?;
ArithOp::Div {
dst: dst.wr(),
rem: Wr::discard(),
a: dst.rd(),
div,
}
}
_ => {
return Err(CrsnError::Parse("Div requires 2 or 3 arguments".into(), op_pos.clone()));
}
}
let (dst, a, div) = args.parse_wr_rd_rd()?;
ArithOp::Div { dst, rem: Wr::discard(), a, div }
}
"mod" => {
match args.len() {
3 => {
ArithOp::Mod {
dst: args.next_wr()?,
a: args.next_rd()?,
div: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
let div = args.next_rd()?;
ArithOp::Mod {
dst: dst.wr(),
a: dst.rd(),
div,
}
}
_ => {
return Err(CrsnError::Parse("Mod requires 2 or 3 arguments".into(), op_pos.clone()));
}
}
let (dst, a, div) = args.parse_wr_rd_rd()?;
ArithOp::Mod { dst, a, div }
}
"and" => {
match args.len() {
3 => {
ArithOp::And {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::And {
dst: dst.wr(),
a: dst.rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("And requires 2 or 3 arguments".into(), op_pos.clone()));
}
}
let (dst, a, b) = args.parse_wr_rd_rd()?;
ArithOp::And { dst, a, b }
}
"or" => {
match args.len() {
3 => {
ArithOp::Or {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::Or {
dst: dst.wr(),
a: dst.rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("Or requires 2 or 3 arguments".into(), op_pos.clone()));
}
}
let (dst, a, b) = args.parse_wr_rd_rd()?;
ArithOp::Or { dst, a, b }
}
"xor" => {
match args.len() {
3 => {
ArithOp::Xor {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::Xor {
dst: dst.wr(),
a: dst.rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("Xor requires 2 or 3 arguments".into(), op_pos.clone()));
}
}
let (dst, a, b) = args.parse_wr_rd_rd()?;
ArithOp::Xor { dst, a, b }
}
"cpl" => {
match args.len() {
2 => {
ArithOp::Cpl {
dst: args.next_wr()?,
a: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Cpl {
dst: dst.wr(),
a: dst.rd(),
}
}
_ => {
return Err(CrsnError::Parse("Cpl requires 1 or 2 arguments".into(), op_pos.clone()));
}
}
let (dst, a) = args.parse_wr_rd()?;
ArithOp::Cpl { dst, a }
}
"rol" => {
match args.len() {
3 => {
ArithOp::Rol {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::Rol {
dst: dst.wr(),
a: dst.rd(),
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Rol {
dst: dst.wr(),
a: dst.rd(),
n: Rd::immediate(1),
}
}
_ => {
return Err(CrsnError::Parse("Rol requires 1, 2 or 3 arguments".into(), op_pos.clone()));
}
}
let (dst, a, n) = args.parse_wr_rd_rd_or_n(1)?;
ArithOp::Rol { dst, a, n }
}
"ror" => {
match args.len() {
3 => {
ArithOp::Ror {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::Ror {
dst: dst.wr(),
a: dst.rd(),
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Ror {
dst: dst.wr(),
a: dst.rd(),
n: Rd::immediate(1),
}
}
_ => {
return Err(CrsnError::Parse("Ror requires 1, 2 or 3 arguments".into(), op_pos.clone()));
}
}
let (dst, a, n) = args.parse_wr_rd_rd_or_n(1)?;
ArithOp::Ror { dst, a, n }
}
"lsl" | "asl" => {
match args.len() {
3 => {
ArithOp::Lsl {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::Lsl {
dst: dst.wr(),
a: dst.rd(),
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Lsl {
dst: dst.wr(),
a: dst.rd(),
n: Rd::immediate(1),
}
}
_ => {
return Err(CrsnError::Parse("Lsl requires 1, 2 or 3 arguments".into(), op_pos.clone()));
}
}
let (dst, a, n) = args.parse_wr_rd_rd_or_n(1)?;
ArithOp::Lsl { dst, a, n }
}
"lsr" => {
match args.len() {
3 => {
ArithOp::Lsr {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::Lsr {
dst: dst.wr(),
a: dst.rd(),
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Lsr {
dst: dst.wr(),
a: dst.rd(),
n: Rd::immediate(1),
}
}
_ => {
return Err(CrsnError::Parse("Lsr requires 1, 2 or 3 arguments".into(), op_pos.clone()));
}
}
let (dst, a, n) = args.parse_wr_rd_rd_or_n(1)?;
ArithOp::Lsr { dst, a, n }
}
"asr" => {
match args.len() {
3 => {
ArithOp::Asr {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::Asr {
dst: dst.wr(),
a: dst.rd(),
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Asr {
dst: dst.wr(),
a: dst.rd(),
n: Rd::immediate(1),
}
}
_ => {
return Err(CrsnError::Parse("Asr requires 1, 2 or 3 arguments".into(), op_pos.clone()));
}
}
let (dst, a, n) = args.parse_wr_rd_rd_or_n(1)?;
ArithOp::Asr { dst, a, n }
}
"sw32" => {
match args.len() {
2 => {
ArithOp::Sw32 {
dst: args.next_wr()?,
src: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Sw32 {
dst: dst.wr(),
src: dst.rd(),
}
}
_ => {
return Err(CrsnError::Parse("SW32 requires 1 or 2 arguments".into(), op_pos.clone()));
}
}
let (dst, src) = args.parse_wr_rd()?;
ArithOp::Sw32 { dst, src }
}
"sw16" => {
match args.len() {
2 => {
ArithOp::Sw16 {
dst: args.next_wr()?,
src: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Sw16 {
dst: dst.wr(),
src: dst.rd(),
}
}
_ => {
return Err(CrsnError::Parse("SW16 requires 1 or 2 arguments".into(), op_pos.clone()));
}
}
let (dst, src) = args.parse_wr_rd()?;
ArithOp::Sw16 { dst, src }
}
"sw8" => {
match args.len() {
2 => {
ArithOp::Sw8 {
dst: args.next_wr()?,
src: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Sw8 {
dst: dst.wr(),
src: dst.rd(),
}
}
_ => {
return Err(CrsnError::Parse("SW8 requires 1 or 2 arguments".into(), op_pos.clone()));
}
}
let (dst, src) = args.parse_wr_rd()?;
ArithOp::Sw8 { dst, src }
}
"rev" => {
match args.len() {
2 => {
ArithOp::Rev {
dst: args.next_wr()?,
src: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Rev {
dst: dst.wr(),
src: dst.rd(),
}
}
_ => {
return Err(CrsnError::Parse("REV requires 1 or 2 arguments".into(), op_pos.clone()));
}
}
let (dst, src) = args.parse_wr_rd()?;
ArithOp::Rev { dst, src }
}
"rbit" => {
match args.len() {
2 => {
ArithOp::Rbit {
dst: args.next_wr()?,
src: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Rbit {
dst: dst.wr(),
src: dst.rd(),
}
}
_ => {
return Err(CrsnError::Parse("RBIT requires 1 or 2 arguments".into(), op_pos.clone()));
}
}
let (dst, src) = args.parse_wr_rd()?;
ArithOp::Rbit { dst, src }
}
other => {