Croissant Runtime
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
crsn/crsn/src/asm/parse/parse_op.rs

109 lines
3.5 KiB

use crate::asm::data::literal::{Label, RoutineName};
use crate::asm::error::Error;
use crate::asm::instr::{Op, OpWrapper};
use crate::asm::instr::cond::parse_cond;
use crate::asm::instr::op::{AsmModule, ParseOpResult};
use crate::asm::parse::arg_parser::ArgParser;
use crate::asm::parse::parse_data::{parse_label, parse_rd};
use crate::asm::parse::sexp_expect::expect_string_atom;
pub fn parse_op(keyword: &str, far: bool, mut arg_tokens: ArgParser, parsers: &[Box<dyn AsmModule>]) -> Result<OpWrapper, Error> {
Ok(match keyword {
"j" => {
let dest = parse_label(arg_tokens.next())?;
if far {
OpWrapper::Op(Op::FarJump(dest))
} else {
OpWrapper::Jump(dest)
}
}
"call" => {
let dest = RoutineName(arg_tokens.next_string()?);
let mut args = vec![];
for t in arg_tokens {
args.push(parse_rd(Some(t))?);
}
OpWrapper::Op(Op::Call(dest, args))
}
"ret" => {
let mut args = vec![];
for t in arg_tokens {
args.push(parse_rd(Some(t))?);
}
OpWrapper::Op(Op::Ret(args))
}
"routine" => {
let dest = RoutineName(arg_tokens.next_string()?);
OpWrapper::Op(Op::Routine(dest))
}
"s" => {
OpWrapper::Op(Op::Skip(arg_tokens.next_rd()?))
}
"sif" => {
let cond = parse_cond(&arg_tokens.next_string()?)?;
let offs = arg_tokens.next_rd()?;
OpWrapper::Op(Op::SkipIf(cond, offs))
}
"jif" => {
let cond = parse_cond(&arg_tokens.next_string()?)?;
let dest = parse_label(arg_tokens.next())?;
OpWrapper::JumpIf(cond, dest)
}
"barrier" => {
OpWrapper::Op(Op::Barrier(match arg_tokens.next() {
None => None,
Some(s) => Some(expect_string_atom(Some(s))?.into()),
}))
}
"fault" => {
OpWrapper::Op(Op::Fault(match arg_tokens.next() {
None => None,
Some(s) => Some(expect_string_atom(Some(s))?.into()),
}))
}
"ld" => {
OpWrapper::Op(Op::Move {
dst: arg_tokens.next_wr()?,
src: arg_tokens.next_rd()?,
})
}
other => {
if let Some(label) = other.strip_prefix(':') {
let label = Label::Named(label.to_string());
if far {
OpWrapper::Op(Op::FarLabel(label))
} else {
OpWrapper::Label(label)
}
} else {
for p in parsers {
arg_tokens = match p.parse_op(keyword, arg_tokens) {
Ok(ParseOpResult::Parsed(op)) => return Ok(OpWrapper::Op(Op::Extension(op))),
Ok(ParseOpResult::Unknown(to_reuse)) => {
if to_reuse.parsing_started() {
panic!("Module \"{}\" started parsing {}, but returned Unknown!", p.name(), keyword);
}
to_reuse
}
Err(err) => {
return Err(err);
}
}
}
return Err(Error::Parse(format!("Unknown instruction: {}", other).into()));
}
}
})
}