rpn_cli/
action.rs

1use crate::error::{EngineError, MyError, MyResult};
2use crate::interface::{Directive, Interface, Operation};
3use crate::value::Value;
4use std::cell::RefCell;
5use std::io::Write;
6use std::rc::Rc;
7
8pub enum Action<W: Write> {
9    Operation(Rc<Operation<W>>),
10    Directive(Rc<Directive<W>>, Vec<String>),
11    Definition(Vec<Action<W>>),
12    Value(Value),
13}
14
15impl<W: Write> Clone for Action<W> {
16    fn clone(&self) -> Self {
17        match self {
18            Self::Operation(operation) => Self::Operation(operation.clone()),
19            Self::Directive(directive, tokens) => Self::Directive(directive.clone(), tokens.clone()),
20            Self::Definition(actions) => Self::Definition(actions.clone()),
21            Self::Value(value) => Self::Value(value.clone()),
22        }
23    }
24}
25
26pub struct Actions<'a, W: Write, I: Iterator<Item = &'a str>> {
27    interface: Rc<RefCell<Interface<W>>>,
28    tokens: I,
29}
30
31impl<'a, W: Write, I: Iterator<Item = &'a str>> Actions<'a, W, I> {
32    pub fn new(
33        interface: &Rc<RefCell<Interface<W>>>,
34        tokens: I,
35    ) -> Self {
36        let interface = Rc::clone(interface);
37        Self { interface, tokens }
38    }
39}
40
41// noinspection RsLift
42impl<'a, W: Write, I: Iterator<Item = &'a str>> Iterator for Actions<'a, W, I> {
43    type Item = MyResult<(Action<W>, &'a str)>;
44
45    fn next(&mut self) -> Option<Self::Item> {
46        if let Some(token) = self.tokens.next() {
47            let interface = self.interface.borrow();
48            if let Some(operation) = interface.get_operation(token) {
49                let action = Action::Operation(operation);
50                return Some(Ok((action, token)));
51            } else if let Some(directive) = interface.get_directive(token) {
52                let mut tokens = Vec::new();
53                while let Some(token) = self.tokens.next() {
54                    tokens.push(String::from(token));
55                }
56                let action = Action::Directive(directive, tokens);
57                return Some(Ok((action, token)));
58            } else if let Some(actions) = interface.get_definition(token) {
59                let action = Action::Definition(actions);
60                return Some(Ok((action, token)));
61            } else {
62                match Value::from_string(token) {
63                    Ok(value) => {
64                        let action = Action::Value(value);
65                        return Some(Ok((action, token)));
66                    }
67                    Err(_) => {
68                        let error = EngineError::ParseError(String::from(token));
69                        return Some(Err(MyError::from(error)));
70                    }
71                }
72            }
73        }
74        None
75    }
76}