use std::collections::VecDeque; //use std::fmt::{Debug, Display, Error, Formatter}; use std::marker::PhantomData; use crate::lang::utility::{assert_token, assert_token_raw, assert_token_raw_back}; #[cfg(debug_assertions)] use crate::lang::utility::assert_empty; use crate::lang::MpsLanguageDictionary; use crate::lang::SyntaxError; use crate::lang::{BoxedMpsOpFactory, MpsOp}; use crate::tokens::MpsToken; pub trait MpsFunctionFactory { fn is_function(&self, name: &str) -> bool; fn build_function_params( &self, name: String, tokens: &mut VecDeque, dict: &MpsLanguageDictionary, ) -> Result; } pub struct MpsFunctionStatementFactory + 'static> { op_factory: F, idc: PhantomData, } impl + 'static> MpsFunctionStatementFactory { pub fn new(factory: F) -> Self { Self { op_factory: factory, idc: PhantomData::default(), } } } impl + 'static> BoxedMpsOpFactory for MpsFunctionStatementFactory { fn is_op_boxed(&self, tokens: &VecDeque) -> bool { let tokens_len = tokens.len(); if tokens_len < 3 { false } else { match &tokens[0] { MpsToken::Name(n) => { self.op_factory.is_function(n) && tokens[1].is_open_bracket() && tokens[tokens_len - 1].is_close_bracket() } _ => false, } } } fn build_op_boxed( &self, tokens: &mut VecDeque, dict: &MpsLanguageDictionary, ) -> Result, SyntaxError> { let name = assert_token( |t| match t { MpsToken::Name(n) => Some(n), _ => None, }, MpsToken::Name("function_name".into()), tokens, )?; assert_token_raw(MpsToken::OpenBracket, tokens)?; assert_token_raw_back(MpsToken::CloseBracket, tokens)?; let func = self.op_factory.build_function_params(name, tokens, dict)?; #[cfg(debug_assertions)] assert_empty(tokens)?; Ok(Box::new(func)) } }