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 }, 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}