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

112 lines
3.1 KiB

use sexp::{Sexp, SourcePosition};
use crate::asm::data::{Mask, Rd, RdData, RdObj, Wr};
use crate::asm::error::CrsnError;
use crate::asm::parse::parse_data::{parse_rd, parse_wr};
use crate::asm::parse::ParserContext;
use crate::asm::parse::sexp_expect::expect_string_atom;
/// 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> 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 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,
}
}
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 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), Mask::FULL) => {
Ok(RdObj::new(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)
}
}