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

73 lines
2.4 KiB

use sexp::Sexp;
use crate::asm::error::CrsnError;
use crate::asm::instr::{Flatten, InstrWithBranches};
use crate::asm::parse::arg_parser::TokenParser;
use crate::asm::parse::parse_cond::parse_cond_branch;
use crate::asm::parse::parse_routine::parse_routine;
use crate::asm::parse::ParserContext;
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
use crate::asm::patches::SexpIsA;
use crate::module::ParseRes;
use super::parse_op::parse_op;
pub fn parse_instructions(items: impl Iterator<Item=Sexp>, pcx: &ParserContext) -> Result<Box<dyn Flatten>, CrsnError> {
let mut parsed = vec![];
for expr in items {
let tokens = expect_list(Some(expr), false)?;
let mut toki = tokens.into_iter();
let name = expect_string_atom(toki.next())?;
if name == "proc" {
parsed.push(parse_routine(toki, pcx)?);
continue;
}
let mut token_parser = TokenParser::new(toki.collect(), pcx);
for p in pcx.parsers {
token_parser = match p.parse_syntax(&name, token_parser) {
Ok(ParseRes::Parsed(op)) => return Ok(op),
Ok(ParseRes::ParsedNone) => return Ok(Box::new(())),
Ok(ParseRes::Unknown(to_reuse)) => {
if to_reuse.parsing_started() {
panic!("Module \"{}\" started parsing syntax, but returned Unknown!", p.name());
}
to_reuse
}
Err(err) => {
return Err(err);
}
}
}
// Get back the original iterator
let toki = token_parser.into_iter();
let arg_tokens = TokenParser::new(toki.clone().take_while(|e| e.is_atom()).collect(), pcx);
let branch_tokens = toki
.skip_while(|e| e.is_atom())
.take_while(|e| e.is_list());
let branches = {
let mut branches = vec![];
for t in branch_tokens {
branches.push(parse_cond_branch(t, pcx)?);
}
if branches.is_empty() {
None
} else {
Some(branches)
}
};
if let Some(op) = parse_op(name.as_str(), arg_tokens)? {
parsed.push(Box::new(InstrWithBranches {
op,
branches,
}));
}
}
Ok(Box::new(parsed))
}