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_data.rs

73 lines
2.2 KiB

use std::convert::TryFrom;
use sexp::{Atom, Sexp};
use crate::asm::data::{DataDisp, Rd, RdData, reg, Wr, WrData};
use crate::asm::data::literal::Label;
use crate::asm::error::Error;
use crate::asm::parse::sexp_expect::expect_string_atom;
/// Parse a label
pub fn parse_label(name: Option<Sexp>) -> Result<Label, Error> {
let name = expect_string_atom(name)?;
Ok(Label::Named(name.trim_start_matches(':').into()))
}
/// Parse data disposition (address/value, without the read/write restriction)
pub fn parse_data_disp(tok: Option<Sexp>) -> Result<DataDisp, Error> {
let tok = if let Some(tok) = tok {
tok
} else {
return Err(Error::Parse("Expected data disposition token".into()));
};
// TODO implement masks
match &tok {
Sexp::Atom(Atom::I(val)) => {
Ok(DataDisp::Immediate(unsafe { std::mem::transmute(*val) }))
}
Sexp::Atom(Atom::S(s)) => {
if s == "_" {
return Ok(DataDisp::Discard);
}
if let Some(reference) = s.strip_prefix('@') {
Ok(DataDisp::ObjectPtr(reg::parse_reg(reference)?))
} else if s.starts_with(|c: char| c.is_ascii_digit()) {
Ok(DataDisp::Immediate(unsafe { std::mem::transmute(parse_i64(s)?) }))
} else {
Ok(DataDisp::Register(reg::parse_reg(s)?))
}
}
_ => {
Err(Error::Parse(format!("bad data disp: {:?}", tok).into()))
}
}
}
pub fn parse_u64(literal: &str) -> anyhow::Result<u64> {
if let Some(hex) = literal.strip_prefix("0x") {
Ok(u64::from_str_radix(hex, 16)?)
} else if let Some(hex) = literal.strip_prefix("0b") {
Ok(u64::from_str_radix(hex, 2)?)
} else {
Ok(u64::from_str_radix(literal, 10)?)
}
}
pub fn parse_i64(literal: &str) -> anyhow::Result<i64> {
if let Some(_value) = literal.strip_prefix("-") {
Ok(-1 * i64::try_from(parse_u64(literal)?)?)
} else {
Ok(i64::try_from(parse_u64(literal)?)?)
}
}
pub fn parse_rd(tok: Option<Sexp>) -> anyhow::Result<Rd> {
Ok(Rd::new(RdData::try_from(parse_data_disp(tok)?)?))
}
pub fn parse_wr(tok: Option<Sexp>) -> anyhow::Result<Wr> {
Ok(Wr::new(WrData::try_from(parse_data_disp(tok)?)?))
}