treeflection/
node_runner.rs1use crate::node_token::NodeToken;
2use std::slice::Iter;
3
4#[derive(Clone)]
5pub struct NodeRunner {
6 pub tokens: Vec<NodeToken>,
7}
8
9impl NodeRunner {
10 pub fn new(command: &str) -> Result<NodeRunner, String> {
11 let mut tokens: Vec<NodeToken> = vec!();
12
13 if command.len() == 0 {
14 return Err(String::from("Empty command"));
15 }
16
17 let chars: Vec<char> = {
18 let mut chars = vec!();
19 if !command.starts_with('.') && !command.starts_with('[') && !command.starts_with(':') {
20 chars.push('.');
21 }
22 chars.extend(command.chars());
23 chars
24 };
25
26 let mut i = 0;
34 loop {
35 if chars[i] == '.' {
36 let mut prop_string = String::new();
37 if i + 1 >= chars.len() {
38 return Err(String::from("Missing action"));
39 }
40
41 let mut next = chars[i+1];
42 while next != '.' && next != '[' && next != ':' {
43 i += 1;
44 prop_string.push(chars[i]);
45 if i + 1 >= chars.len() {
46 return Err(String::from("Missing action"));
47 }
48 next = chars[i+1];
49 }
50
51 if i + 1 >= chars.len() {
52 return Err(String::from("Missing action"));
53 }
54 i += 1;
55
56 if prop_string.len() == 0 {
57 return Err(String::from("Empty property"));
58 }
59 tokens.push(NodeToken::ChainProperty (prop_string));
60 }
61 else if i + 2 < chars.len() && chars[i] == '[' && chars[i+1] == '?' && chars[i+2] == ']' {
62 if i + 3 >= chars.len() {
63 return Err(String::from("Missing action"));
64 }
65 i += 3;
66 tokens.push(NodeToken::ChainContext);
67 }
68 else if i + 2 < chars.len() && chars[i] == '[' && chars[i+1] == '*' && chars[i+2] == ']' {
69 if i + 3 >= chars.len() {
70 return Err(String::from("Missing action"));
71 }
72 i += 3;
73 tokens.push(NodeToken::ChainAll);
74 }
75 else if i + 1 < chars.len() && chars[i] == '[' && chars[i+1] == '"' {
76 let mut key_string = String::new();
77 i += 1;
78 if i + 4 >= chars.len() {
79 return Err(String::from("Missing action"));
80 }
81 let mut next1 = chars[i+1];
82 let mut next2 = chars[i+2];
83 while next1 != '"' || next2 != ']' {
84 i += 1;
85 key_string.push(chars[i]);
86 if i + 2 >= chars.len() {
87 return Err(String::from("Missing \"]"));
88 }
89 next1 = chars[i+1];
90 next2 = chars[i+2];
91 }
92
93 if i + 3 >= chars.len() {
94 return Err(String::from("Missing action"));
95 }
96 i += 3;
97
98 tokens.push(NodeToken::ChainKey(key_string));
99 }
100 else if chars[i] == '[' {
101 let mut index_string = String::new();
102 if i + 1 >= chars.len() {
103 return Err(String::from("Missing action"));
104 }
105
106 let mut next = chars[i+1];
107 while next != ']' {
108 i += 1;
109 index_string.push(chars[i]);
110 if i + 1 >= chars.len() {
111 return Err(String::from("Missing ]"));
112 }
113 next = chars[i+1];
114 }
115
116 if i + 2 >= chars.len() {
117 return Err(String::from("Missing action"));
118 }
119 i += 2;
120
121 if index_string.len() == 0 {
122 return Err(String::from("Missing index"));
123 }
124
125 match index_string.parse() {
126 Ok (index) => tokens.push(NodeToken::ChainIndex (index)),
127 Err (_) => return Err (format!("Invalid index: {}", index_string)),
128 }
129 }
130 else if chars[i] == ':' {
131 let tokenized = NodeRunner::tokenize_action(&chars[i+1..])?;
132 tokens.push(NodeRunner::get_action(tokenized.iter())?);
133
134 tokens.reverse();
135
136 return Ok(NodeRunner {
137 tokens: tokens
138 });
139 }
140 else {
141 return Err(String::from("Missing ."));
144 }
145 }
146 }
147
148 fn tokenize_action(string: &[char]) -> Result<Vec<String>, String> {
151 let mut tokens: Vec<String> = vec!();
152 let mut current = String::new();
153 let mut quoted = false;
154 let mut escaped = false;
155 for c in string {
156 if escaped {
157 match *c {
158 '"' => { current.push('"') }
159 't' => { current.push('\t') }
160 'n' => { current.push('\n') }
161 ' ' => { current.push(' ') }
162 '\\' => { current.push('\\') }
163 _ => { }
164 }
165 escaped = false;
166 }
167 else if *c == '\\' {
168 escaped = true;
169 }
170 else if !quoted && c.is_whitespace() {
171 if current.len() > 0 {
172 tokens.push(current);
173 current = String::new();
174 }
175 }
176 else if *c == '"' {
177 if quoted {
178 tokens.push(current);
179 current = String::new();
180 }
181 quoted = !quoted;
182 }
183 else {
184 current.push(*c);
185 }
186 }
187
188 if current.len() > 0 {
189 tokens.push(current);
190 }
191
192 if quoted {
193 Err(String::from("Unterminated string"))
194 } else {
195 Ok(tokens)
196 }
197 }
198
199 fn get_action(mut action: Iter<String>) -> Result<NodeToken, String> {
200 match action.next().map(|x| x.as_ref()) {
201 Some("help") => Ok(NodeToken::Help),
202 Some("reset") => Ok(NodeToken::SetDefault),
203 Some("edit") => Ok(NodeToken::Edit),
204 Some("copy") => Ok(NodeToken::CopyFrom),
205 Some("paste") => Ok(NodeToken::PasteTo),
206 Some("getkeys") => Ok(NodeToken::GetKeys),
207 Some("get") => Ok(NodeToken::Get),
208 Some("set") => {
209 let mut set_value: Vec<&str> = vec!();
210 for token in action {
211 set_value.push(token);
212 }
213 Ok(NodeToken::Set(set_value.join(" ")))
214 }
215 Some("insert") => {
216 match action.next() {
217 Some(arg0) => {
218 match action.next() {
219 Some(arg1) => {
220 match arg0.parse() {
221 Ok(index) => {
222 Ok(NodeToken::InsertIndexKey (index, arg1.to_string()))
223 }
224 Err(_) => Err(String::from("When two arguments are used, first must be a valid index."))
225 }
226 }
227 None => {
228 match arg0.parse() {
229 Ok(index) => Ok(NodeToken::InsertIndex (index)),
230 Err(_) => Ok(NodeToken::InsertKey (arg0.to_string())),
231 }
232 }
233 }
234 }
235 None => {
236 Ok(NodeToken::Insert)
237 }
238 }
239 }
240 Some("remove") => {
241 match action.next() {
242 Some(arg) => {
243 match arg.parse() {
244 Ok(index) => Ok(NodeToken::RemoveIndex (index)),
245 Err(_) => Ok(NodeToken::RemoveKey (arg.to_string())),
246 }
247 }
248 None => {
249 Ok(NodeToken::Remove)
250 }
251 }
252 }
253 Some("variant") => {
254 Ok(NodeToken::SetVariant (
255 match action.next() {
256 Some(value) => value.to_string(),
257 None => String::new()
258 }
259 ))
260 }
261 Some(action_name) => {
262 let args: Vec<String> = action.cloned().collect();
263 Ok(NodeToken::Custom(action_name.to_string(), args))
264 }
265 None => Err (String::from("Missing action"))
266 }
267 }
268
269 pub fn step(&mut self) -> NodeToken {
270 self.tokens.pop().unwrap()
271 }
272}