1
2#[derive(Debug)]
4pub enum Event {
5 StartSelector(Vec<String>),
7 EndSelector(Vec<String>),
9 Rule(String, String),
11 Comment(String),
13}
14
15pub struct Lexer {
17 content: Vec<char>,
18 data: Vec<Event>,
19 selector_stack: Vec<Vec<String>>,
20}
21
22impl Lexer {
23 pub fn new(contents: &str) -> Self {
27 Self {
28 content: contents.chars().collect::<Vec<char>>(),
29 data: Vec::new(),
30 selector_stack: Vec::new(),
31 }
32 }
33
34 pub fn parse(&mut self) -> &[Event] {
36 while !self.content.is_empty() {
37 self.trim_whitespaces();
38
39 if !self.content.is_empty()
42 && (self.content[0] == '*'
43 || self.content[0] == '.'
44 || self.content[0] == '#'
45 || self.content[0].is_alphabetic())
46 {
47 self.parse_start_selector();
48 }
49
50 self.trim_whitespaces();
51
52 if !self.content.is_empty() && self.content[0] == '{' {
55 self.parse_rules()
56 }
57
58 self.trim_whitespaces();
59
60 if !self.content.is_empty() && self.content[0] == '}' {
63 self.parse_end_selector();
64 }
65
66 self.trim_whitespaces();
67
68 if self.content.len() > 1 && self.content[0] == '/' && self.content[1] == '*' {
71 self.parse_comment();
72 }
73 }
74
75 &self.data
76 }
77
78 fn parse_start_selector(&mut self) {
84 let mut selectors = Vec::new();
85
86 while !self.content.is_empty() && self.content[0] != '{' {
88 let selector = self.take_while(|x| x != ' ' && x != ',' && x != '{');
89
90 self.trim_whitespaces();
91
92 if !self.content.is_empty() && self.content[0] == ',' {
93 self.take_slice(0, 1); self.trim_whitespaces();
95 }
96
97 selectors.push(selector);
98 }
99
100 self.data.push(Event::StartSelector(selectors.clone()));
104 self.selector_stack.push(selectors);
105 }
106
107 fn parse_rules(&mut self) {
113 self.take_slice(0, 1); self.trim_whitespaces();
116
117 while self.content[0] != '}' {
118 let rule_name = self.take_while(|x| x.is_alphabetic() || x == '-');
119 self.trim_whitespaces();
120
121 if self.content[0] != ':' {
122 eprintln!("ERROR: expecting `:`");
123 break;
124 }
125 self.take_slice(0, 1); self.trim_whitespaces();
127
128 let rule_value = self.take_while(|x| x != ';');
129 self.take_slice(0, 1); self.data.push(Event::Rule(rule_name, rule_value));
132
133 self.trim_whitespaces();
134 }
135 }
136
137 fn parse_end_selector(&mut self) {
140 self.take_slice(0, 1); if let Some(selector) = self.selector_stack.pop() {
143 self.data.push(Event::EndSelector(selector));
144 } else {
145 eprintln!("ERROR: invalid clsoing selector. Need a staring selector.");
146 }
147 }
148
149 fn parse_comment(&mut self) {
155 self.take_slice(0, 2); let mut astric_count = 0;
158
159 let comment = self.take_while(|x| {
160 if x == '*' {
161 astric_count += 1;
162 }
163 else if x == '/' && astric_count == 1 {
165 return false;
166 }
167
168 true
169 });
170
171 self.take_slice(0, 2); let comment = comment[..comment.len() - 1].to_string();
176
177 self.data.push(Event::Comment(comment));
178 }
179
180 fn trim_whitespaces(&mut self) -> () {
181 self.take_while(|x| x.is_whitespace());
182 }
183
184 fn take_while<F>(&mut self, predict: F) -> String
185 where
186 F: FnMut(char) -> bool,
187 {
188 self.take_while_from(0, predict)
189 }
190
191 fn take_while_from<F>(&mut self, start: usize, mut predict: F) -> String
192 where
193 F: FnMut(char) -> bool,
194 {
195 let mut i = start;
196
197 while self.content.len() > i && predict(self.content[i]) {
198 i += 1;
199 }
200
201 self.take_slice(start, i)
202 }
203
204 fn take_slice(&mut self, from: usize, to: usize) -> String {
205 let slice = self.content[from..to].iter().collect::<String>();
206 self.content = self.content[to..].to_vec();
207
208 slice
209 }
210}