69 lines
2.1 KiB
Rust
69 lines
2.1 KiB
Rust
|
use std::collections::VecDeque;
|
||
|
//use std::fmt::{Debug, Display, Error, Formatter};
|
||
|
use std::marker::PhantomData;
|
||
|
|
||
|
use crate::tokens::MpsToken;
|
||
|
use crate::lang::{MpsOp, BoxedMpsOpFactory};
|
||
|
use crate::lang::SyntaxError;
|
||
|
use crate::lang::MpsLanguageDictionary;
|
||
|
use crate::lang::utility::{assert_token_raw, assert_token_raw_back, assert_token};
|
||
|
|
||
|
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(),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl<Op: MpsOp + 'static, F: MpsFunctionFactory<Op> + 'static>
|
||
|
BoxedMpsOpFactory
|
||
|
for
|
||
|
MpsFunctionStatementFactory<Op, F>
|
||
|
{
|
||
|
fn is_op_boxed(&self, tokens: &VecDeque<MpsToken>) -> 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<MpsToken>,
|
||
|
dict: &MpsLanguageDictionary,
|
||
|
) -> Result<Box<dyn MpsOp>, 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)?;
|
||
|
Ok(Box::new(self.op_factory.build_function_params(name, tokens, dict)?))
|
||
|
}
|
||
|
}
|