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, 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; 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, 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 { self.args.pop() } /// Get the next entry, or raise an error pub fn next_or_err(&mut self) -> Result { 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 { 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 { 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 { parse_wr(self.next_or_err()?, self.pcx) } /// Get the next entry as write location pub fn next_rdwr(&mut self) -> Result { 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, CrsnError> { if let Some(s) = keyword.strip_prefix(prefix) { let width = if s.is_empty() { (std::mem::size_of::() 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, CrsnError> { if let Some(s) = keyword.strip_prefix(prefix) { let width = if s.is_empty() { (std::mem::size_of::() 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, CrsnError> { if let Some(s) = keyword.strip_prefix(prefix) { let width = if s.is_empty() { (std::mem::size_of::() 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())) } } }