1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use std::cell::RefCell;
use std::io::Write;
use std::rc::Rc;

use crate::context::Context;
use crate::error::{EngineError, MyError, MyResult};
use crate::interface::{Directive, Interface, Operation};
use crate::value::Value;

pub enum Action<W: Write> {
    Operation(Rc<Operation<W>>),
    Directive(Rc<Directive<W>>, Vec<String>),
    Definition(Vec<Action<W>>),
    Value(Value),
}

impl<W: Write> Clone for Action<W> {
    fn clone(&self) -> Self {
        match self {
            Action::Operation(operation) => Action::Operation(operation.clone()),
            Action::Directive(directive, tokens) => Action::Directive(directive.clone(), tokens.clone()),
            Action::Definition(actions) => Action::Definition(actions.clone()),
            Action::Value(value) => Action::Value(value.clone()),
        }
    }
}

pub struct Actions<'a, W: Write, I: Iterator<Item = &'a str>> {
    interface: Rc<RefCell<Interface<W>>>,
    context: Rc<RefCell<Context>>,
    tokens: I,
}

impl<'a, W: Write, I: Iterator<Item = &'a str>> Actions<'a, W, I> {
    pub fn new(
        interface: &Rc<RefCell<Interface<W>>>,
        context: &Rc<RefCell<Context>>,
        tokens: I,
    ) -> Actions<'a, W, I> {
        let interface = Rc::clone(interface);
        let context = Rc::clone(context);
        return Actions { interface, context, tokens };
    }
}

// noinspection RsLift
impl<'a, W: Write, I: Iterator<Item = &'a str>> Iterator for Actions<'a, W, I> {
    type Item = MyResult<(Action<W>, &'a str)>;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(token) = self.tokens.next() {
            let interface = self.interface.borrow();
            if let Some(operation) = interface.get_operation(token) {
                let action = Action::Operation(operation);
                return Some(Ok((action, token)));
            } else if let Some(directive) = interface.get_directive(token) {
                let mut tokens = Vec::new();
                while let Some(token) = self.tokens.next() {
                    tokens.push(String::from(token));
                }
                let action = Action::Directive(directive, tokens);
                return Some(Ok((action, token)));
            } else if let Some(actions) = interface.get_definition(token) {
                let action = Action::Definition(actions);
                return Some(Ok((action, token)));
            } else {
                match Value::from_string(&self.context.borrow(), token) {
                    Ok(value) => {
                        let action = Action::Value(value);
                        return Some(Ok((action, token)));
                    }
                    Err(_) => {
                        let error = EngineError::ParseError(String::from(token));
                        return Some(Err(MyError::from(error)));
                    }
                }
            }
        }
        return None;
    }
}