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.
84 lines
2.7 KiB
84 lines
2.7 KiB
use sexp::Sexp;
|
|
|
|
use crate::asm::data::literal::RoutineName;
|
|
use crate::asm::error::CrsnError;
|
|
use crate::asm::instr::{Flatten, Instr, Routine};
|
|
use crate::asm::parse::arg_parser::TokenParser;
|
|
use crate::asm::parse::parse_cond::parse_cond_branch;
|
|
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
|
|
use crate::asm::patches::SexpIsA;
|
|
use crate::module::{CrsnExtension, ParseRes};
|
|
|
|
use super::parse_op::parse_op;
|
|
|
|
pub fn parse_instructions(items: impl Iterator<Item=Sexp>, parsers: &[Box<dyn CrsnExtension>]) -> 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, parsers)?);
|
|
continue;
|
|
}
|
|
|
|
let mut token_parser = TokenParser::new(toki.collect());
|
|
for p in parsers {
|
|
token_parser = match p.parse_syntax(&name, token_parser, parsers) {
|
|
Ok(ParseRes::Parsed(op)) => return Ok(op),
|
|
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());
|
|
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, parsers)?);
|
|
}
|
|
if branches.is_empty() {
|
|
None
|
|
} else {
|
|
Some(branches)
|
|
}
|
|
};
|
|
|
|
parsed.push(Box::new(Instr {
|
|
op: parse_op(name.as_str(), arg_tokens, parsers)?,
|
|
branches,
|
|
}));
|
|
}
|
|
Ok(Box::new(parsed))
|
|
}
|
|
|
|
fn parse_routine(mut toki: impl Iterator<Item=Sexp> + Clone, parsers: &[Box<dyn CrsnExtension>]) -> Result<Box<dyn Flatten>, CrsnError> {
|
|
let name = expect_string_atom(toki.next())?;
|
|
|
|
let _arg_tokens = TokenParser::new(toki.clone().take_while(|e| e.is_atom()).collect());
|
|
|
|
// TODO parse arg tokens
|
|
|
|
let body = parse_instructions(toki, parsers)?;
|
|
|
|
return Ok(Box::new(Routine {
|
|
name: RoutineName(name),
|
|
body,
|
|
}));
|
|
}
|
|
|