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, parsers: &[Box]) -> Result, 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 + Clone, parsers: &[Box]) -> Result, 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, })); }