1#![allow(dead_code)]
2
3#[derive(Debug, PartialEq)]
4enum LexState {
5 Seperator,
6 Token,
7 Done,
8}
9
10pub fn lex_line(line: &str) -> Vec<&str> {
12 let mut v = Vec::new();
13 let mut start_index = 0;
15 let mut stop_index = 0;
17 let mut state = LexState::Seperator;
19
20 for character in line.chars() {
21 match character {
22 ';' | '\n' | '\r' => {
23 if state == LexState::Token { v.push(&line[start_index..stop_index]); }
25 state == LexState::Done;
26 break;
27 }
28 ' ' | '\t' => {
29 if state == LexState::Token { v.push(&line[start_index..stop_index]); }
32 state = LexState::Seperator;
33 }
34 _ => {
35 if state == LexState::Seperator { start_index = stop_index; }
38 state = LexState::Token;
39 }
40 }
41 stop_index += 1;
43 }
44 if state == LexState::Token {
47 let new_token = &line[start_index..stop_index];
48 if v.len() == 0 { v.push(new_token); }
50 else {
52 let last_token = v.pop().unwrap();
53 if new_token != last_token { v.push(last_token); }
55 v.push(new_token);
58 }
59 }
60 return v;
61}
62
63pub fn lex(source: &str) -> Vec<Vec<&str>> {
64 let mut v = Vec::new();
65 for line in source.lines() {
66 v.push(lex_line(line));
67 };
68 return v;
69}
70
71#[cfg(test)]
72mod test_lex {
73 use super::*;
74 #[test]
75 fn test_lex_line_with_comment() {
76 let result = lex_line("ident1 ident2:ident2more\tident3; comment");
77 assert_eq!(&result[..], ["ident1", "ident2:ident2more", "ident3"]);
78 }
79
80 #[test]
81 fn test_lex_line_lexes_only_one_line() {
82 let result = lex_line("ident1 ident2 \n ident3");
83 assert_eq!(&result[..], ["ident1", "ident2"]);
84 }
85
86 #[test]
87 fn test_lex_multiple_lines() {
88 let result = lex("l1i1 l1i2 ; line 1 comment\nl2i1 l2i2 l2i3 ; line 2 comment");
89 assert_eq!(&result[..], &[vec!["l1i1", "l1i2"], vec!["l2i1", "l2i2", "l2i3"]]);
90 }
91}