1use std::fmt;
6
7#[derive(Debug)]
9#[derive(PartialEq)]
10pub enum Infix {
11 None,
12 Unify,
14 Equal,
16 GreaterThan,
18 LessThan,
20 GreaterThanOrEqual,
22 LessThanOrEqual,
24 Plus,
26 Minus,
28 Multiply,
30 Divide,
32}
33
34pub fn check_infix(chrs: &Vec<char>) -> (Infix, usize) {
63
64 let length = chrs.len();
65 let mut prev = '#'; let mut i = 0;
68 while i < length {
69
70 let c1 = chrs[i];
71 let mut c2 = '#';
72 if i + 1 < length { c2 = chrs[i + 1]; }
73 let mut c3 = '#';
74 if i + 2 < length { c3 = chrs[i + 2]; }
75
76 if c1 == '"' {
78 let mut j = i + 1;
79 while j < length {
80 let cx = chrs[j];
81 if cx == '"' {
82 i = j;
83 break;
84 }
85 j += 1;
86 }
87 }
88 else if c1 == '(' {
89 let mut j = i + 1;
91 while j < length {
92 let cx = chrs[j];
93 if cx == ')' {
94 i = j;
95 break;
96 }
97 j += 1;
98 }
99 }
100 else {
101 if prev != ' ' {
103 prev = c1;
104 i += 1;
105 continue;
106 }
107 if i >= (length - 2) { return (Infix::None, 0); }
110 if c1 == '<' {
111 if c2 == '=' {
112 if c3 == ' ' {
113 return (Infix::LessThanOrEqual, i);
114 }
115 }
116 else if c2 == ' ' {
117 return (Infix::LessThan, i);
118 }
119 }
120 else if c1 == '>' {
121 if c2 == '=' {
122 if c3 == ' ' {
123 return (Infix::GreaterThanOrEqual, i);
124 }
125 }
126 else if c2 == ' ' {
127 return (Infix::GreaterThan, i);
128 }
129 }
130 else if c1 == '=' {
131 if c2 == '=' {
132 if c3 == ' ' {
133 return (Infix::Equal, i);
134 }
135 }
136 else if c2 == ' ' {
137 return (Infix::Unify, i);
138 }
139 }
140
141 } prev = c1;
144 i += 1;
145
146 } return (Infix::None, 0); } pub fn check_arithmetic_infix(chrs: &Vec<char>) -> (Infix, usize) {
177
178 let length = chrs.len();
179 let mut prev = '#'; let mut i = 0;
182 while i < length {
183
184 let c1 = chrs[i];
185 let mut c2 = '#';
186 if i + 1 < length { c2 = chrs[i + 1]; }
187
188 if c1 == '"' {
190 let mut j = i + 1;
191 while j < length {
192 let cx = chrs[j];
193 if cx == '"' {
194 i = j; break;
195 }
196 j += 1;
197 }
198 }
199 else if c1 == '(' {
200 let mut j = i + 1;
202 while j < length {
203 let cx = chrs[j];
204 if cx == ')' {
205 i = j; break;
206 }
207 j += 1;
208 }
209 }
210 else {
211
212 if prev != ' ' {
214 prev = c1;
215 i += 1;
216 continue;
217 }
218
219 if c1 == '+' { if c2 == ' ' { return (Infix::Plus, i); } }
222 else
223 if c1 == '-' { if c2 == ' ' { return (Infix::Minus, i); } }
224 else
225 if c1 == '*' { if c2 == ' ' { return (Infix::Multiply, i); } }
226 else
227 if c1 == '/' { if c2 == ' ' { return (Infix::Divide, i); } }
228 } prev = c1;
231 i += 1;
232
233 } return (Infix::None, 0); } impl fmt::Display for Infix {
240 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
241 return match &self {
242 Infix::None => write!(f, "None"),
243 Infix::Unify => write!(f, "="),
244 Infix::Equal => write!(f, "=="),
245 Infix::GreaterThan => write!(f, ">"),
246 Infix::LessThan => write!(f, "<"),
247 Infix::GreaterThanOrEqual => write!(f, ">="),
248 Infix::LessThanOrEqual => write!(f, "<="),
249 Infix::Plus => write!(f, "+"),
250 Infix::Minus => write!(f, "-"),
251 Infix::Multiply => write!(f, "*"),
252 Infix::Divide => write!(f, "/"),
253 };
254 } } #[cfg(test)]
258mod test {
259
260 use crate::str_to_chars;
261 use super::*;
262
263 #[test]
264 fn test_check_infix() {
265
266 let chrs = str_to_chars!("$X = $Y");
267 let (inf, ind) = check_infix(&chrs);
268 assert_eq!(inf, Infix::Unify);
269 assert_eq!(ind, 3, "Unify");
270
271 let chrs = str_to_chars!("$X =$Y");
272 let (inf, ind) = check_infix(&chrs);
273 assert_eq!(inf, Infix::None);
274 assert_eq!(ind, 0);
275
276 let chrs = str_to_chars!("$X > $Y");
277 let (inf, ind) = check_infix(&chrs);
278 assert_eq!(inf, Infix::GreaterThan);
279 assert_eq!(ind, 3, "GreaterThan");
280
281 let chrs = str_to_chars!("$Age >= 50");
282 let (inf, ind) = check_infix(&chrs);
283 assert_eq!(inf, Infix::GreaterThanOrEqual);
284 assert_eq!(ind, 5, "GreaterThanOrEqual");
285
286 let chrs = str_to_chars!("$Height < 152");
287 let (inf, ind) = check_infix(&chrs);
288 assert_eq!(inf, Infix::LessThan);
289 assert_eq!(ind, 8, "LessThan");
290
291 let chrs = str_to_chars!("$Grade <= 60");
292 let (inf, ind) = check_infix(&chrs);
293 assert_eq!(inf, Infix::LessThanOrEqual);
294 assert_eq!(ind, 7, "LessThanOrEqual");
295
296 let chrs = str_to_chars!("100 == $Score");
297 let (inf, ind) = check_infix(&chrs);
298 assert_eq!(inf, Infix::Equal);
299 assert_eq!(ind, 4, "Equal");
300
301 let chrs = str_to_chars!("\" <= \"");
302 let (inf, ind) = check_infix(&chrs);
303 assert_eq!(inf, Infix::None);
304 assert_eq!(ind, 0, "Infix between double quotes should be ignored.");
305
306 let chrs = str_to_chars!("$X =1");
310 let (inf, ind) = check_infix(&chrs);
311 assert_eq!(inf, Infix::None);
312 assert_eq!(ind, 0);
313
314 let chrs = str_to_chars!("$X <=1");
315 let (inf, ind) = check_infix(&chrs);
316 assert_eq!(inf, Infix::None);
317 assert_eq!(ind, 0);
318
319 let chrs = str_to_chars!("$X >=1");
320 let (inf, ind) = check_infix(&chrs);
321 assert_eq!(inf, Infix::None);
322 assert_eq!(ind, 0);
323
324 let chrs = str_to_chars!("$X ==1");
325 let (inf, ind) = check_infix(&chrs);
326 assert_eq!(inf, Infix::None);
327 assert_eq!(ind, 0);
328
329 let chrs = str_to_chars!("$X <1");
330 let (inf, ind) = check_infix(&chrs);
331 assert_eq!(inf, Infix::None);
332 assert_eq!(ind, 0);
333
334 let chrs = str_to_chars!("$X >1");
335 let (inf, ind) = check_infix(&chrs);
336 assert_eq!(inf, Infix::None);
337 assert_eq!(ind, 0);
338 } #[test]
341 fn test_check_arithmetic_infix() {
342
343 let chrs = str_to_chars!("$X * 7");
344 let (inf, ind) = check_arithmetic_infix(&chrs);
345 assert_eq!(inf, Infix::Multiply);
346 assert_eq!(ind, 3, "Multiply operator");
347
348 let chrs = str_to_chars!("$X / 7");
349 let (inf, ind) = check_arithmetic_infix(&chrs);
350 assert_eq!(inf, Infix::Divide);
351 assert_eq!(ind, 3, "Divide operator");
352
353 let chrs = str_to_chars!("$X + 7");
354 let (inf, ind) = check_arithmetic_infix(&chrs);
355 assert_eq!(inf, Infix::Plus);
356 assert_eq!(ind, 3, "Plus operator");
357
358 let chrs = str_to_chars!("$X - 7");
359 let (inf, ind) = check_arithmetic_infix(&chrs);
360 assert_eq!(inf, Infix::Minus);
361 assert_eq!(ind, 3, "Minus operator");
362
363 let chrs = str_to_chars!("$X < 7");
365 let (inf, ind) = check_arithmetic_infix(&chrs);
366 assert_eq!(inf, Infix::None);
367 assert_eq!(ind, 0, "Not an arithmetic operator");
368
369 let chrs = str_to_chars!("$X *7");
371 let (inf, ind) = check_arithmetic_infix(&chrs);
372 assert_eq!(inf, Infix::None);
373 assert_eq!(ind, 0, "Missing space.");
374
375 let chrs = str_to_chars!("$X/ 7");
377 let (inf, ind) = check_arithmetic_infix(&chrs);
378 assert_eq!(inf, Infix::None);
379 assert_eq!(ind, 0, "Missing space.");
380
381 let chrs = str_to_chars!("\"$X / 7\"");
383 let (inf, ind) = check_arithmetic_infix(&chrs);
384 assert_eq!(inf, Infix::None);
385 assert_eq!(ind, 0, "Between quotes.");
386
387 let chrs = str_to_chars!("($X + 7)");
389 let (inf, ind) = check_arithmetic_infix(&chrs);
390 assert_eq!(inf, Infix::None);
391 assert_eq!(ind, 0, "Between parentheses.");
392
393 } }