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