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/arg_parser.rs

357 lines
12 KiB

use sexp::{Sexp, SourcePosition};
use crate::asm::data::{Rd, RdData, RdObj, Wr, RdWr};
use crate::asm::error::CrsnError;
use crate::asm::parse::parse_data::{parse_rd, parse_wr, parse_value, parse_rdwr_offset, parse_rdwr, parse_rd_offset, parse_wr_offset};
use crate::asm::parse::ParserContext;
use crate::asm::parse::sexp_expect::expect_string_atom;
use crate::asm::data::literal::Value;
use crate::builtin::defs::BitMask;
use crate::asm::patches::ErrWithPos;
use std::fmt::{Debug, Formatter};
use std::fmt;
/// Utility for argument parsing
pub struct TokenParser<'a> {
orig_len: usize,
args: Vec<Sexp>,
start_pos: &'a SourcePosition,
pub pcx: &'a ParserContext<'a>,
}
impl<'a> Debug for TokenParser<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("TokenParser")
.field("orig_len", &self.orig_len)
.field("args", &self.args)
.field("start_pos", &self.start_pos)
.finish()
}
}
impl<'a> IntoIterator for TokenParser<'a> {
type Item = Sexp;
type IntoIter = std::vec::IntoIter<Sexp>;
fn into_iter(mut self) -> Self::IntoIter {
// The vec is reversed so we can call "pop", but here we will iterate it as a slice, so it
// must be reversed to its original direction.
self.args.reverse();
self.args.into_iter()
}
}
impl<'a> TokenParser<'a> {
/// Create a new argument parser
pub fn new(mut args: Vec<Sexp>, start_pos: &'a SourcePosition, pcx: &'a ParserContext) -> Self {
args.reverse();
Self {
orig_len: args.len(),
start_pos,
args,
pcx,
}
}
/// Prepend a token
pub fn prepend(&mut self, what: Sexp) {
// the list is reversed - actually, append it
self.args.push(what);
self.orig_len += 1;
}
/// Get error if not empty.
/// The argument is substituted into the phrase "Instruction needs ...!" - i.e. "one Wr argument and a list or string"
pub fn ensure_empty(&self, what_arguments : &str) -> Result<(), CrsnError> {
self.ensure_empty_custom(&format!("Instruction needs {}!", what_arguments))
}
pub fn ensure_empty_custom(&self, msg : &str) -> Result<(), CrsnError> {
if self.have_more() {
Err(CrsnError::Parse(msg.to_string().into(), self.start_pos.clone()))
} else {
Ok(())
}
}
pub fn have_more(&self) -> bool {
self.len() > 0
}
/// Get remaining items count
pub fn len(&self) -> usize {
self.args.len()
}
/// Get len before parsing started
pub fn orig_len(&self) -> usize {
self.orig_len
}
/// Check if parsing started
pub fn parsing_started(&self) -> bool {
self.args.len() != self.orig_len
}
/// Get the next entry
pub fn next(&mut self) -> Option<Sexp> {
self.args.pop()
}
/// Get the next entry, or raise an error
pub fn next_or_err(&mut self) -> Result<Sexp, CrsnError> {
match self.next() {
None => {
Err(CrsnError::Parse("Unexpected end of token list".into(), self.start_pos.clone()))
}
Some(removed) => Ok(removed)
}
}
/// Look at the next entry
pub fn peek(&mut self) -> Option<&Sexp> {
self.args.last()
}
/// Get the next string entry
pub fn next_string(&mut self) -> Result<(String, SourcePosition), CrsnError> {
let next = self.next_or_err()?;
let esa = expect_string_atom(next)?;
Ok(esa)
}
/// Get the next value entry
pub fn next_value(&mut self) -> Result<(Value, SourcePosition), CrsnError> {
let next = self.next_or_err()?;
parse_value(next, self.pcx)
}
/// Get the next entry as read location
pub fn next_rd(&mut self) -> Result<Rd, CrsnError> {
let next = self.next_or_err()?;
parse_rd(next, self.pcx)
}
/// Get the next entry as an object location
pub fn next_rdobj(&mut self) -> Result<RdObj, CrsnError> {
match parse_rd(self.next_or_err()?, self.pcx)? {
Rd(RdData::RegObject(reg)) => {
Ok(RdObj::from_reg(reg))
}
other => {
Err(CrsnError::Parse(
format!("Not a valid object handle syntax: {:?}", other).into(),
self.start_pos.clone(),
))
}
}
}
/// Get the next entry as write location
pub fn next_wr(&mut self) -> Result<Wr, CrsnError> {
parse_wr(self.next_or_err()?, self.pcx)
}
/// Get the next entry as write location
pub fn next_rdwr(&mut self) -> Result<RdWr, CrsnError> {
let next = self.next_or_err()?;
parse_rdwr(next, self.pcx)
}
/// Get the next entry as write location with optional :offset
pub fn next_rdwr_offset(&mut self) -> Result<(RdWr, u32), CrsnError> {
let next = self.next_or_err()?;
parse_rdwr_offset(next, self.pcx)
}
pub fn next_rd_offset(&mut self) -> Result<(Rd, u32), CrsnError> {
let next = self.next_or_err()?;
parse_rd_offset(next, self.pcx)
}
pub fn next_wr_offset(&mut self) -> Result<(Wr, u32), CrsnError> {
let next = self.next_or_err()?;
parse_wr_offset(next, self.pcx)
}
/// Parse combining binary instruction operands (i.e. add) with bit masks
/// Accepts (Wr, Rd, Rd) and (RdWr, Rd)
pub fn parse_masked_wr_rd_rd(&mut self, keyword: &str, prefix: &str) -> Result<Option<(Wr, Rd, Rd, BitMask)>, CrsnError> {
if let Some(s) = keyword.strip_prefix(prefix) {
let width = if s.is_empty() {
(std::mem::size_of::<Value>() as u32) * 8
} else {
s.parse().err_pos(self.start_pos)?
};
if self.len() == 2 {
let (rw, dst_pos) = self.next_rdwr_offset()?;
let (rd, src_pos) = self.next_rd_offset()?;
let mask = BitMask {
width,
dst_pos,
src_pos: dst_pos,
src2_pos: src_pos,
};
mask.validate(self.start_pos)?;
Ok(Some((rw.wr(), rw.rd(), rd, mask)))
} else if self.len() == 3 {
let (wr, dst_pos) = self.next_wr_offset()?;
let (rd1, src_pos) = self.next_rd_offset()?;
let (rd2, src2_pos) = self.next_rd_offset()?;
let mask = BitMask {
width,
dst_pos,
src_pos,
src2_pos,
};
mask.validate(self.start_pos)?;
Ok(Some((wr, rd1, rd2, mask)))
} else {
Err(CrsnError::Parse("Instruction needs 2 (RW,Rd) or 3 (Wr,Rd,Rd) arguments!".into(), self.start_pos.clone()))
}
} else {
Ok(None)
}
}
/// Parse unary instruction operands (i.e. complement) with bit masks.
/// Accepts (Wr, Rd) and (RdWr)
pub fn parse_masked_wr_rd(&mut self, keyword: &str, prefix: &'static str) -> Result<Option<(Wr, Rd, BitMask)>, CrsnError> {
if let Some(s) = keyword.strip_prefix(prefix) {
let width = if s.is_empty() {
(std::mem::size_of::<Value>() as u32) * 8
} else {
s.parse().err_pos(self.start_pos)?
};
if self.len() == 1 {
let (rw, dst_pos) = self.next_rdwr_offset()?;
let mask = BitMask {
width,
dst_pos,
src_pos: dst_pos,
src2_pos: 0,
};
mask.validate(self.start_pos)?;
Ok(Some((rw.wr(), rw.rd(), mask)))
} else if self.len() == 2 {
let (wr, dst_pos) = self.next_wr_offset()?;
let (rd, src_pos) = self.next_rd_offset()?;
let mask = BitMask {
width,
dst_pos,
src_pos,
src2_pos: 0,
};
mask.validate(self.start_pos)?;
Ok(Some((wr, rd, mask)))
} else {
Err(CrsnError::Parse("Instruction needs 1 (RW) or 2 (Wr,Rd) arguments!".into(), self.start_pos.clone()))
}
} else {
Ok(None)
}
}
/// Parse a swap-type binary instruction operands (i.e. exchange) with bit masks
/// Accepts (RdWr, RdWr)
pub fn parse_masked_rdwr_rdwr(&mut self, keyword: &str, prefix: &str) -> Result<Option<(RdWr, RdWr, BitMask)>, CrsnError> {
if let Some(s) = keyword.strip_prefix(prefix) {
let width = if s.is_empty() {
(std::mem::size_of::<Value>() as u32) * 8
} else {
s.parse().err_pos(self.start_pos)?
};
if self.len() == 2 {
let (wr1, dst_pos) = self.next_rdwr_offset()?;
let (wr2, src_pos) = self.next_rdwr_offset()?;
let mask = BitMask {
width,
dst_pos,
src_pos,
src2_pos: 0,
};
mask.validate(self.start_pos)?;
Ok(Some((wr1, wr2, mask)))
} else {
Err(CrsnError::Parse("Instruction needs 2 (RW,RW) arguments!".into(), self.start_pos.clone()))
}
} else {
Ok(None)
}
}
/// Parse combining binary instruction operands (i.e. add) without masks
/// Accepts (Wr, Rd, Rd) and (RdWr, Rd)
pub fn parse_wr_rd_rd(&mut self) -> Result<(Wr, Rd, Rd), CrsnError> {
if self.len() == 2 {
let rw = self.next_rdwr()?;
let rd = self.next_rd()?;
Ok((rw.wr(), rw.rd(), rd))
} else if self.len() == 3 {
let wr = self.next_wr()?;
let rd1 = self.next_rd()?;
let rd2 = self.next_rd()?;
Ok((wr, rd1, rd2))
} else {
Err(CrsnError::Parse("Instruction needs 2 (RW,Rd) or 3 (Wr,Rd,Rd) arguments!".into(), self.start_pos.clone()))
}
}
/// Parse combining binary instruction operands (i.e. add) without masks
/// Accepts (Wr, Rd, Rd) and (RdWr, Rd)
pub fn parse_wr_rd_rd_or_n(&mut self, n : Value) -> Result<(Wr, Rd, Rd), CrsnError> {
if self.len() == 1 {
let rw = self.next_rdwr()?;
Ok((rw.wr(), rw.rd(), Rd::new_imm(n)))
} else if self.len() == 2 {
let rw = self.next_rdwr()?;
let rd = self.next_rd()?;
Ok((rw.wr(), rw.rd(), rd))
} else if self.len() == 3 {
let wr = self.next_wr()?;
let rd1 = self.next_rd()?;
let rd2 = self.next_rd()?;
Ok((wr, rd1, rd2))
} else {
Err(CrsnError::Parse("Instruction needs 1 (RW,1), 2 (RW,Rd) or 3 (Wr,Rd,Rd) arguments!".into(), self.start_pos.clone()))
}
}
/// Parse unary instruction operands (i.e. complement) without masks
/// Accepts (Wr, Rd) and (RdWr)
pub fn parse_wr_rd(&mut self) -> Result<(Wr, Rd), CrsnError> {
if self.len() == 1 {
let rw = self.next_rdwr()?;
Ok((rw.wr(), rw.rd()))
} else if self.len() == 2 {
let wr = self.next_wr()?;
let rd = self.next_rd()?;
Ok((wr, rd))
} else {
Err(CrsnError::Parse("Instruction needs 1 (RW) or 2 (Wr,Rd) arguments!".into(), self.start_pos.clone()))
}
}
/// Parse a swap-type binary instruction operands (i.e. exchange) without masks
/// Accepts (RdWr, RdWr)
pub fn parse_rdwr_rdwr(&mut self, _keyword: &str, _prefix: &str, _pos: &SourcePosition) -> Result<(RdWr, RdWr), CrsnError> {
if self.len() == 2 {
let rw1 = self.next_rdwr()?;
let rw2 = self.next_rdwr()?;
Ok((rw1, rw2))
} else {
Err(CrsnError::Parse("Instruction needs 2 (RW,RW) arguments!".into(), self.start_pos.clone()))
}
}
}