1use crate::ast::*;
2use crate::lexer::Lexer;
3use crate::token::{Token, TokenType};
4
5pub struct Parser<'a> {
6 lexer: Lexer<'a>,
7 pub i: usize,
8 pub tokens: Vec<Token<'a>>,
9}
10
11impl<'a> Parser<'a> {
12 pub fn new(mut lexer: Lexer<'a>) -> Self {
13 let mut t = lexer.next();
14 let mut tokens = vec![t];
15 while t.typ != TokenType::Eof {
16 t = lexer.next();
17 tokens.push(t);
18 }
19 Self {
20 lexer,
21 i: 0,
22 tokens,
23 }
24 }
25 pub fn parse(&mut self) -> Ast {
26 let mut a = Ast::default();
27 while self.i < self.tokens.len() {
28 let curr = self.tokens[self.i];
29 match curr.typ {
30 TokenType::Eof => break,
31 TokenType::Word => match curr.word {
32 "i18n_type" => {
33 a.i18n_type = Some(true);
34 self.i += 2;
35 }
36 "class" => {
37 let c = self.consume_class();
38 a.classes.push(c);
39 }
40 "Function" => {
41 let f = self.consume_func();
42 a.functions.push(f);
43 }
44 "comment" => {
45 let c = self.consume_comment();
46 a.comments.push(c);
47 }
48 "decl" => {
49 let d = self.consume_decl();
50 a.decls.push(d);
51 }
52 "widget_class" => {
53 let w = self.consume_widget();
54 a.widget_classes.push(w);
55 }
56 _ => (),
57 },
58 _ => (),
59 }
60 self.i += 1;
61 }
62 a
63 }
64 fn consume_func(&mut self) -> Function {
65 let mut f = Function::default();
66 self.i += 1;
67 f.name = self.consume_braced_string();
68 self.i += 1; while self.tokens[self.i].typ != TokenType::Eof {
70 self.i += 1;
71 if self.tokens[self.i].typ == TokenType::CloseBrace {
72 break;
73 }
74 match self.tokens[self.i].word {
75 "open" => f.props.open = Some(true),
76 "C" => f.props.c = Some(true),
77 "protected" => f.props.visibility = Some(Visibility::PROTECTED),
78 "private" => f.props.visibility = Some(Visibility::PRIVATE),
79 "comment" => {
80 self.i += 1;
81 if self.tokens[self.i].typ == TokenType::OpenBrace {
82 f.props.comment = Some(self.consume_braced_string());
83 } else {
84 f.props.comment = Some(self.tokens[self.i].word.to_string());
85 }
86 }
87 "return_type" => {
88 self.i += 1;
89 if self.tokens[self.i].typ == TokenType::OpenBrace {
90 f.props.return_type = Some(self.consume_braced_string());
91 } else {
92 f.props.return_type = Some(self.tokens[self.i].word.to_string());
93 }
94 }
95 _ => (),
96 }
97 }
98 self.i += 1; if self.tokens[self.i].typ == TokenType::OpenBrace {
100 while self.tokens[self.i].typ != TokenType::CloseBrace {
101 self.i += 1;
102 if self.tokens[self.i].word == "code" {
103 self.i += 1;
104 f.code = Some(self.consume_code());
105 self.i += 1;
106 }
107 if self.tokens[self.i].word.starts_with("Fl_")
108 || self.tokens[self.i].word == "MenuItem"
109 || self.tokens[self.i].word == "Submenu"
110 {
111 let w = self.consume_widget();
112 f.widgets.push(w);
113 self.i += 1;
114 }
115 }
116 }
117 f
118 }
119 fn consume_widget(&mut self) -> Widget {
120 let mut w = Widget {
121 typ: self.tokens[self.i].word.to_string(),
122 ..Default::default()
123 };
124 self.i += 1;
125 if self.tokens[self.i].typ == TokenType::OpenBrace {
126 self.i += 1;
127 }
128 if !self.tokens[self.i].word.is_empty() {
129 w.name = self.tokens[self.i].word.to_string();
130 } else {
131 w.name = String::new();
132 }
133 while self.tokens[self.i].typ != TokenType::Eof {
134 self.i += 1;
135 if self.tokens[self.i].typ == TokenType::CloseBrace {
136 break;
137 }
138 match self.tokens[self.i].word {
139 "open" => w.props.open = Some(true),
140 "hide" => w.props.hide = Some(true),
141 "deactivate" => w.props.deactivate = Some(true),
142 "divider" => w.props.divider = Some(true),
143 "resizable" => w.props.resizable = Some(true),
144 "visible" => w.props.visible = Some(true),
145 "hotspot" => w.props.hotspot = Some(true),
146 "modal" => w.props.modal = Some(true),
147 "non_modal" => w.props.non_modal = Some(true),
148 "noborder" => w.props.noborder = Some(true),
149 "xywh" => {
150 self.i += 1;
151 w.props.xywh = self.consume_braced_string();
152 }
153 "size_range" => {
154 self.i += 1;
155 w.props.size_range = Some(self.consume_braced_string());
156 }
157 "color" => {
158 self.i += 1;
159 w.props.color = Some(self.tokens[self.i].word.to_string().parse().unwrap_or_else(|_| panic!("Failed to parse numeric value for `align` property at token:\"{:?}\"!",
160 self.tokens[self.i])));
161 }
162 "selection_color" => {
163 self.i += 1;
164 w.props.selection_color = Some(
165 self.tokens[self.i]
166 .word
167 .to_string()
168 .parse()
169 .unwrap_or_else(|_| panic!("Failed to parse numeric value for `selection_color` property at token:\"{:?}\"!",
170 self.tokens[self.i])),
171 );
172 }
173 "labelcolor" => {
174 self.i += 1;
175 w.props.labelcolor = Some(self.tokens[self.i].word.to_string().parse().unwrap_or_else(|_| panic!("Failed to parse numeric value for `labelcolor` property at token:\"{:?}\"!",
176 self.tokens[self.i])));
177 }
178 "textcolor" => {
179 self.i += 1;
180 w.props.textcolor = Some(self.tokens[self.i].word.to_string().parse().unwrap_or_else(|_| panic!("Failed to parse numeric value for `textcolor` property at token:\"{:?}\"!",
181 self.tokens[self.i])));
182 }
183 "type" => {
184 self.i += 1;
185 if self.tokens[self.i].typ == TokenType::OpenBrace {
186 w.props.typ = Some(self.consume_braced_string());
187 } else {
188 w.props.typ = Some(self.tokens[self.i].word.to_string());
189 }
190 }
191 "labeltype" => {
192 self.i += 1;
193 w.props.labeltype = Some(self.tokens[self.i].word.to_string());
194 }
195 "labelfont" => {
196 self.i += 1;
197 w.props.labelfont = Some(self.tokens[self.i].word.to_string().parse().unwrap_or_else(|_| panic!("Failed to parse numeric value for `labeltype` property at token:\"{:?}\"!",
198 self.tokens[self.i])));
199 }
200 "textfont" => {
201 self.i += 1;
202 w.props.textfont = Some(self.tokens[self.i].word.to_string().parse().unwrap_or_else(|_| panic!("Failed to parse numeric value for `textfont` property at token:\"{:?}\"!",
203 self.tokens[self.i])));
204 }
205 "labelsize" => {
206 self.i += 1;
207 w.props.labelsize = Some(self.tokens[self.i].word.to_string().parse().unwrap_or_else(|_| panic!("Failed to parse numeric value for `labelsize` property at token:\"{:?}\"!",
208 self.tokens[self.i])));
209 }
210 "textsize" => {
211 self.i += 1;
212 w.props.textsize = Some(self.tokens[self.i].word.to_string().parse().unwrap_or_else(|_| panic!("Failed to parse numeric value for `textsize` property at token:\"{:?}\"!",
213 self.tokens[self.i])));
214 }
215 "box" => {
216 self.i += 1;
217 w.props.r#box = Some(self.tokens[self.i].word.to_string());
218 }
219 "down_box" => {
220 self.i += 1;
221 w.props.down_box = Some(self.tokens[self.i].word.to_string());
222 }
223 "align" => {
224 self.i += 1;
225 w.props.align = Some(self.tokens[self.i].word.to_string().parse().unwrap_or_else(|_| panic!("Failed to parse numeric value for `align` property at token:\"{:?}\"!",
226 self.tokens[self.i])));
227 }
228 "when" => {
229 self.i += 1;
230 w.props.when = Some(self.tokens[self.i].word.to_string().parse().unwrap_or_else(|_| panic!("Failed to parse numeric value for `when` property at token:\"{:?}\"!",
231 self.tokens[self.i])));
232 }
233 "shortcut" => {
234 self.i += 1;
235 w.props.shortcut = Some(self.tokens[self.i].word.to_string());
236 }
237 "gap" => {
238 self.i += 1;
239 if self.tokens[self.i].typ == TokenType::OpenBrace {
240 w.props.gap = Some(self.consume_braced_string());
241 } else {
242 w.props.gap = Some(self.tokens[self.i].word.to_string());
243 }
244 }
245 "minimum" => {
246 self.i += 1;
247 w.props.minimum = Some(self.tokens[self.i].word.to_string().parse().unwrap_or_else(|_| panic!("Failed to parse numeric value for `minimum` property at token:\"{:?}\"!",
248 self.tokens[self.i])));
249 }
250 "maximum" => {
251 self.i += 1;
252 w.props.maximum = Some(self.tokens[self.i].word.to_string().parse().unwrap_or_else(|_| panic!("Failed to parse numeric value for `maximum` property at token:\"{:?}\"!",
253 self.tokens[self.i])));
254 }
255 "step" => {
256 self.i += 1;
257 w.props.step = Some(self.tokens[self.i].word.to_string().parse().unwrap_or_else(|_| panic!("Failed to parse numeric value for `step` property at token:\"{:?}\"!",
258 self.tokens[self.i])));
259 }
260 "slider_size" => {
261 self.i += 1;
262 w.props.slider_size = Some(
263 self.tokens[self.i]
264 .word
265 .to_string()
266 .parse()
267 .unwrap_or_else(|_| panic!("Failed to parse numeric value for `slider_size` property at token:\"{:?}\"!",
268 self.tokens[self.i])),
269 );
270 }
271 "size" => {
272 self.i += 1;
273 w.props.size = Some(self.tokens[self.i].word.to_string().parse().unwrap_or_else(|_| panic!("Failed to parse numeric value for `size` property at token:\"{:?}\"!",
274 self.tokens[self.i])));
275 }
276 "label" => {
277 self.i += 1;
278 if self.tokens[self.i].typ == TokenType::OpenBrace {
279 w.props.label = Some(self.consume_braced_string());
280 } else {
281 w.props.label = Some(self.tokens[self.i].word.to_string());
282 }
283 }
284 "xclass" => {
285 self.i += 1;
286 if self.tokens[self.i].typ == TokenType::OpenBrace {
287 w.props.xclass = Some(self.consume_braced_string());
288 } else {
289 w.props.xclass = Some(self.tokens[self.i].word.to_string());
290 }
291 }
292 "class" => {
293 self.i += 1;
294 if self.tokens[self.i].typ == TokenType::OpenBrace {
295 w.props.class = Some(self.consume_braced_string());
296 } else {
297 w.props.class = Some(self.tokens[self.i].word.to_string());
298 }
299 }
300 "tooltip" => {
301 self.i += 1;
302 if self.tokens[self.i].typ == TokenType::OpenBrace {
303 w.props.tooltip = Some(self.consume_braced_string());
304 } else {
305 w.props.tooltip = Some(self.tokens[self.i].word.to_string());
306 }
307 }
308 "image" => {
309 self.i += 1;
310 if self.tokens[self.i].typ == TokenType::OpenBrace {
311 w.props.image = Some(self.consume_braced_string());
312 } else {
313 w.props.image = Some(self.tokens[self.i].word.to_string());
314 }
315 }
316 "deimage" => {
317 self.i += 1;
318 if self.tokens[self.i].typ == TokenType::OpenBrace {
319 w.props.deimage = Some(self.consume_braced_string());
320 } else {
321 w.props.deimage = Some(self.tokens[self.i].word.to_string());
322 }
323 }
324 "value" => {
325 self.i += 1;
326 if self.tokens[self.i].typ == TokenType::OpenBrace {
327 w.props.value = Some(self.consume_braced_string());
328 } else {
329 w.props.value = Some(self.tokens[self.i].word.to_string());
330 }
331 }
332 "set_size_tuples" => {
333 self.i += 1;
334 w.props.size_tuple = Some(self.consume_braced_string());
335 }
336 "margins" => {
337 self.i += 1;
338 w.props.margins = Some(self.consume_braced_string());
339 }
340 "dimensions" => {
341 self.i += 1;
342 w.props.dimensions = Some(self.consume_braced_string());
343 }
344 "margin" => {
345 self.i += 1;
346 w.props.margin = Some(self.consume_braced_string());
347 }
348 "fixed_size_tuples" => {
349 self.i += 1;
350 w.props.size_tuple = Some(self.consume_braced_string());
351 }
352 "code0" => {
353 self.i += 1;
354 w.props.code0 = Some(self.consume_braced_string());
355 }
356 "code1" => {
357 self.i += 1;
358 w.props.code1 = Some(self.consume_braced_string());
359 }
360 "code2" => {
361 self.i += 1;
362 w.props.code2 = Some(self.consume_braced_string());
363 }
364 "code3" => {
365 self.i += 1;
366 w.props.code3 = Some(self.consume_braced_string());
367 }
368 "extra_code" => {
369 self.i += 1;
370 w.props.extra_code = Some(self.consume_braced_string());
371 }
372 "callback" => {
373 self.i += 1;
374 if self.tokens[self.i].typ == TokenType::OpenBrace {
375 w.props.callback = Some(self.consume_braced_string());
376 } else {
377 w.props.callback = Some(self.tokens[self.i].word.to_string());
378 }
379 }
380 "user_data" => {
381 self.i += 1;
382 if self.tokens[self.i].typ == TokenType::OpenBrace {
383 w.props.user_data = Some(self.consume_braced_string());
384 } else {
385 w.props.user_data = Some(self.tokens[self.i].word.to_string());
386 }
387 }
388 "user_data_type" => {
389 self.i += 1;
390 if self.tokens[self.i].typ == TokenType::OpenBrace {
391 w.props.user_data_type = Some(self.consume_braced_string());
392 } else {
393 w.props.user_data_type = Some(self.tokens[self.i].word.to_string());
394 }
395 }
396 "comment" => {
397 self.i += 1;
398 if self.tokens[self.i].typ == TokenType::OpenBrace {
399 w.props.comment = Some(self.consume_braced_string());
400 } else {
401 w.props.comment = Some(self.tokens[self.i].word.to_string());
402 }
403 }
404 "parent_properties" => {
405 while self.tokens[self.i].typ != TokenType::CloseBrace {
406 self.i += 1;
407 w.props.parent_properties = Some(self.consume_parent_props());
408 }
409 }
410 _ => (),
411 }
412 }
413 if self.tokens[self.i + 1].typ == TokenType::OpenBrace {
414 self.i += 1;
415 while self.tokens[self.i].typ != TokenType::CloseBrace {
416 self.i += 1;
417 while self.tokens[self.i].word.starts_with("Fl_")
418 || self.tokens[self.i].word == "MenuItem"
419 || self.tokens[self.i].word == "Submenu"
420 {
421 let c = self.consume_widget();
422 w.children.push(c);
423 self.i += 1;
424 }
425 }
426 }
427 w
428 }
429 fn consume_class(&mut self) -> Class {
430 let mut c = Class::default();
431 self.i += 1;
432 if self.tokens[self.i].typ == TokenType::OpenBrace {
433 self.i += 2;
434 }
435 c.name = self.tokens[self.i].word.to_string();
436 self.i += 1;
437 while self.tokens[self.i].typ != TokenType::CloseBrace {
439 self.i += 1;
440 match self.tokens[self.i].word {
441 "open" => c.props.open = Some(true),
442 "protected" => c.props.visibility = Some(Visibility::PROTECTED),
443 "private" => c.props.visibility = Some(Visibility::PRIVATE),
444 "comment" => {
445 self.i += 1;
446 if self.tokens[self.i].typ == TokenType::OpenBrace {
447 c.props.comment = Some(self.consume_braced_string());
448 } else {
449 c.props.comment = Some(self.tokens[self.i].word.to_string());
450 }
451 }
452 _ => (),
453 }
454 }
455 self.i += 1;
456 if self.tokens[self.i].typ == TokenType::OpenBrace {
457 while self.tokens[self.i].typ != TokenType::CloseBrace {
458 self.i += 1;
459 while self.tokens[self.i].word == "Function" {
460 let f = self.consume_func();
461 c.functions.push(f);
462 }
463 if self.tokens[self.i].word == "comment" {
464 self.i += 1;
465 if self.tokens[self.i].typ == TokenType::OpenBrace {
466 c.props.comment = Some(self.consume_braced_string());
467 } else {
468 c.props.comment = Some(self.tokens[self.i].word.to_string());
469 }
470 }
471 }
472 }
473 c
474 }
475 fn consume_comment(&mut self) -> Comment {
476 let mut c = Comment::default();
477 self.i += 1;
478 c.comment = self.consume_braced_string();
479 while self.tokens[self.i].typ != TokenType::Eof {
480 self.i += 1;
481 if self.tokens[self.i].typ == TokenType::CloseBrace {
482 break;
483 }
484 match self.tokens[self.i].word {
485 "in_source" => c.props.in_source = Some(true),
486 "in_header" => c.props.in_header = Some(true),
487 _ => (),
488 }
489 }
490 c
491 }
492 fn consume_decl(&mut self) -> Decl {
493 let mut d = Decl::default();
494 self.i += 1;
495 d.decl = self.consume_braced_string();
496 while self.tokens[self.i].typ != TokenType::Eof {
497 self.i += 1;
498 if self.tokens[self.i].typ == TokenType::CloseBrace {
499 break;
500 }
501 match self.tokens[self.i].word {
502 "private" => d.props.visibility = Visibility::PRIVATE,
503 "public" => d.props.visibility = Visibility::PUBLIC,
504 "global" => d.props.global = Some(true),
505 "local" => d.props.local = Some(true),
506 _ => (),
507 }
508 }
509 d
510 }
511 fn consume_code(&mut self) -> String {
512 let s = self.consume_braced_string();
513 self.i += 1;
515 self.i += 1;
516 s
517 }
518
519 fn consume_braced_string(&mut self) -> String {
520 self.i += 1;
521 let mut t = self.tokens[self.i];
522 let start = t.start;
523 let mut openbrace = 1;
524 while t.typ != TokenType::Eof {
525 self.i += 1;
526 t = self.tokens[self.i];
527 if t.typ == TokenType::OpenBrace {
528 openbrace += 1;
529 }
530 if t.typ == TokenType::CloseBrace {
531 openbrace -= 1;
532 }
533 if openbrace == 0 {
534 break;
535 }
536 }
537 let end = self.tokens[self.i].end - 1;
538 self.lexer.s[start..end].to_string()
539 }
540 fn consume_parent_props(&mut self) -> ParentProps {
541 let mut p = ParentProps::default();
542 while self.tokens[self.i].typ != TokenType::Eof {
543 self.i += 1;
544 if self.tokens[self.i].typ == TokenType::CloseBrace {
545 break;
546 }
547 match self.tokens[self.i].word {
548 "location" => {
549 self.i += 1;
550 p.location = Some(self.consume_braced_string());
551 },
552 _ => (),
553 }
554 }
555 p
556 }
557}