use sexp::{Sexp, Atom}; use crate::data::{DataDisp, Rd, Wr, DstDisp, SrcDisp, reg}; use crate::error::Error; use crate::data::literal::{Value, Addr, Label}; use std::convert::TryFrom; use crate::parse::sexp_expect::expect_string_atom; /// Parse a label pub fn parse_label(name : Option) -> Result { 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) -> Result { 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 let Some(reference) = s.strip_prefix('@') { if reference.starts_with(|c : char| c.is_ascii_digit()) { let val : u64 = parse_u64(reference)?; Ok(DataDisp::ImmediatePtr(Addr(val))) } else { Ok(DataDisp::RegisterPtr(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 { 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 { 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) -> anyhow::Result { Ok(Rd::new(SrcDisp::try_from(parse_data_disp(tok)?)?)) } pub fn parse_wr(tok: Option) -> anyhow::Result { Ok(Wr::new(DstDisp::try_from(parse_data_disp(tok)?)?)) }