muss/mps-interpreter/src/lang/function.rs

75 lines
2.3 KiB
Rust

use std::collections::VecDeque;
//use std::fmt::{Debug, Display, Error, Formatter};
use std::marker::PhantomData;
use crate::lang::utility::{assert_token, assert_token_raw};
use crate::lang::MpsLanguageDictionary;
use crate::lang::SyntaxError;
use crate::lang::{BoxedMpsOpFactory, MpsOp};
use crate::tokens::MpsToken;
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)?;
let end_tokens = tokens.split_off(tokens.len() - 1);
let func = self.op_factory.build_function_params(name, tokens, dict)?;
tokens.extend(end_tokens);
assert_token_raw(MpsToken::CloseBracket, tokens)?;
Ok(Box::new(func))
}
}