light_cli/
lexer.rs

1use nb;
2use heapless::{ArrayLength, String};
3
4use tokenizer;
5use tokenizer::{Token, Tokenizer};
6
7#[derive(Clone)]
8#[derive(PartialEq)]
9enum MachineState {
10    NewCommand,
11    NewCommandCR,
12    Key,
13    Value,
14}
15
16pub enum CallbackCommand<'a> {
17    Attribute(&'a str, &'a str, &'a str),
18    Command(&'a str),
19}
20
21pub struct Lexer<SLEN> where SLEN: ArrayLength<u8> {
22    current_cmd: String<SLEN>,
23    current_key: String<SLEN>,
24    state: MachineState,
25}
26
27impl<SLEN> Lexer<SLEN> where SLEN: ArrayLength<u8> {
28    pub fn new() -> Self {
29        Self {
30            current_cmd: String::new(),
31            current_key: String::new(),
32            state: MachineState::NewCommand,
33        }
34    }
35
36    pub fn parse_data<CB>(&mut self, tokenizer: &mut Tokenizer<SLEN>, mut callback: CB) -> nb::Result<(), tokenizer::Error> 
37        where CB: FnMut(CallbackCommand) -> () {
38        tokenizer.get_tokens(|token| {
39            let new_state = match token {
40                Token::NewLine => {
41                    if self.state != MachineState::NewCommandCR {
42                        callback(CallbackCommand::Command(self.current_cmd.as_str()));
43                        self.current_cmd.clear();
44                        self.current_key.clear();
45                    }
46                    MachineState::NewCommand
47                },
48                Token::CarriageReturn => {
49                    callback(CallbackCommand::Command(self.current_cmd.as_str()));
50                    self.current_cmd.clear();
51                    self.current_key.clear();
52                    MachineState::NewCommandCR
53                }, // ignore carriage returns
54                Token::Value(s) => {
55                    match self.state {
56                        MachineState::NewCommandCR => {
57                            self.current_cmd = String::from(s);
58                            MachineState::Key
59                        },
60                        MachineState::NewCommand => {
61                            self.current_cmd = String::from(s);
62                            MachineState::Key
63                        },
64                        MachineState::Key => {
65                            self.current_key = String::from(s);
66                            MachineState::Value
67                        },
68                        MachineState::Value => {
69                            callback(CallbackCommand::Attribute(self.current_cmd.as_str(), self.current_key.as_str(), s));
70                            MachineState::Key
71                        },
72                    }
73                },
74                Token::Space => {
75                    match self.state {
76                        MachineState::Value => {
77                            callback(CallbackCommand::Attribute(self.current_cmd.as_str(), self.current_key.as_str(), ""));
78                            MachineState::Key
79                        },
80                        MachineState::NewCommand => self.state.clone(),
81                        MachineState::NewCommandCR => self.state.clone(),
82                        MachineState::Key => self.state.clone()
83                    }
84                },
85                Token::Equals => {
86                    self.state.clone()
87                }
88            };
89
90            self.state = new_state;
91        })
92    }
93}