1use regex::RegexBuilder;
19use std::collections::HashMap;
20use std::fmt::Debug;
21use std::net::IpAddr;
22use std::sync::Arc;
23use tree_sitter::{self, Node};
24
25use crate::common::TextLocation;
26use crate::mel::ast::Expr::BinaryExpr;
27use crate::mel::ast::Expr::MemberAccess;
28use crate::mel::ast::Expr::TernaryExpr;
29use crate::mel::ast::Literal::{Boolean, Number};
30use crate::mel::ast::LogicOperator::{And, Or};
31use crate::mel::ast::MathOperator::{Divide, Minus, Modulo, Multiply, Plus};
32use crate::mel::ast::{Argument, BinaryInfixOperator, StringConcatOperator};
33use crate::mel::compiler::error::CompilerError;
34use crate::mel::compiler::error::CompilerLocatableError;
35use crate::mel::{
36 ast::{self, ArgumentList, Expr, Identifier},
37 grammar::GrammarNode,
38};
39use crate::utils;
40
41pub type SyntaxVisitorResult<T> = Result<T, CompilerLocatableError>;
42
43pub trait SyntaxVisitor<T>: Sized {
44 fn visit_function_call(
45 &self,
46 syntax: Node,
47 context: T,
48 driver: &SyntaxVisitorDriver,
49 ) -> SyntaxVisitorResult<T>;
50 fn visit_error(
51 &self,
52 syntax: Node,
53 context: T,
54 driver: &SyntaxVisitorDriver,
55 ) -> CompilerLocatableError;
56 fn visit_expr(
57 &self,
58 syntax: Node,
59 context: T,
60 driver: &SyntaxVisitorDriver,
61 ) -> SyntaxVisitorResult<T> {
62 let node = syntax.named_child(0).ok_or(CompilerLocatableError {
63 error: CompilerError::BadGrammarElement,
64 location: syntax.into(),
65 })?;
66 driver.visit(node, self, context)
67 }
68 fn visit_identifier(
69 &self,
70 syntax: Node,
71 context: T,
72 driver: &SyntaxVisitorDriver,
73 ) -> SyntaxVisitorResult<T>;
74 fn visit_argument_list(
75 &self,
76 syntax: Node,
77 context: T,
78 driver: &SyntaxVisitorDriver,
79 ) -> SyntaxVisitorResult<T>;
80 fn visit_argument(
81 &self,
82 syntax: Node,
83 context: T,
84 driver: &SyntaxVisitorDriver,
85 ) -> SyntaxVisitorResult<T>;
86 fn visit_string_concat_operator(
87 &self,
88 syntax: Node,
89 context: T,
90 driver: &SyntaxVisitorDriver,
91 ) -> SyntaxVisitorResult<T>;
92 fn visit_comparison_operator(
93 &self,
94 syntax: Node,
95 context: T,
96 driver: &SyntaxVisitorDriver,
97 ) -> SyntaxVisitorResult<T>;
98 fn visit_logic_operator(
99 &self,
100 syntax: Node,
101 context: T,
102 driver: &SyntaxVisitorDriver,
103 ) -> SyntaxVisitorResult<T>;
104 fn visit_math_operator(
105 &self,
106 syntax: Node,
107 context: T,
108 driver: &SyntaxVisitorDriver,
109 ) -> SyntaxVisitorResult<T>;
110 fn visit_member_access_expr(
111 &self,
112 syntax: Node,
113 context: T,
114 driver: &SyntaxVisitorDriver,
115 ) -> SyntaxVisitorResult<T>;
116 fn visit_member_access_oper(
117 &self,
118 syntax: Node,
119 context: T,
120 driver: &SyntaxVisitorDriver,
121 ) -> SyntaxVisitorResult<T>;
122 fn visit_binary_expr(
123 &self,
124 syntax: Node,
125 context: T,
126 driver: &SyntaxVisitorDriver,
127 ) -> SyntaxVisitorResult<T>;
128 fn visit_ternary_operator(
129 &self,
130 syntax: Node,
131 context: T,
132 driver: &SyntaxVisitorDriver,
133 ) -> SyntaxVisitorResult<T>;
134 fn visit_ternary_expr(
135 &self,
136 syntax: Node,
137 context: T,
138 driver: &SyntaxVisitorDriver,
139 ) -> SyntaxVisitorResult<T>;
140 fn visit_literal(
141 &self,
142 syntax: Node,
143 context: T,
144 driver: &SyntaxVisitorDriver,
145 ) -> SyntaxVisitorResult<T>;
146 fn visit_boolean_literal(
147 &self,
148 syntax: Node,
149 context: T,
150 driver: &SyntaxVisitorDriver,
151 ) -> SyntaxVisitorResult<T>;
152 fn visit_number_literal(
153 &self,
154 syntax: Node,
155 context: T,
156 driver: &SyntaxVisitorDriver,
157 ) -> SyntaxVisitorResult<T>;
158 fn visit_string_literal(
159 &self,
160 syntax: Node,
161 context: T,
162 driver: &SyntaxVisitorDriver,
163 ) -> SyntaxVisitorResult<T>;
164 fn visit_regex_literal(
165 &self,
166 syntax: Node,
167 context: T,
168 driver: &SyntaxVisitorDriver,
169 ) -> SyntaxVisitorResult<T>;
170 fn visit_ipaddress_literal(
171 &self,
172 syntax: Node,
173 context: T,
174 driver: &SyntaxVisitorDriver,
175 ) -> SyntaxVisitorResult<T>;
176 fn visit_mel(
177 &self,
178 syntax: Node,
179 context: T,
180 driver: &SyntaxVisitorDriver,
181 ) -> SyntaxVisitorResult<T>;
182}
183
184#[derive(Default, Debug, Clone)]
186pub enum MELCompilerContext {
187 Expr(ast::Expr<()>),
188 BinaryOperator(ast::BinaryInfixOperator),
189 TernaryOperator(ast::TernaryOperator),
190 #[default]
191 Empty,
192}
193
194#[macro_export]
196macro_rules! expect_expr {
197 ( $t:ident, $x:expr ) => {{
198 match $x {
199 $t::Expr(e) => Some(e),
200 _ => None,
201 }
202 }};
203}
204
205pub struct MELCompiler {
206 source: String,
207}
208
209impl MELCompiler {
210 pub fn new(source: &str) -> Self {
211 MELCompiler {
212 source: source.to_string(),
213 }
214 }
215
216 pub fn extract_error(&self, en: &Node) -> CompilerLocatableError {
217 let error_tok = en
218 .utf8_text(self.source.as_bytes())
219 .or::<String>(Ok(""))
220 .expect("Could not get error token");
221
222 let repr = en
223 .to_string()
224 .trim_start_matches("(")
225 .trim_end_matches(")")
226 .to_string();
227
228 let msg = if repr.starts_with("UNEXPECTED") {
229 format!("Unexpected token {error_tok}")
230 } else if repr.starts_with("MISSING") {
231 let msg = repr.trim_start_matches("MISSING ");
232 format!("Missing: {msg}")
233 } else {
234 format!("Bad token: {error_tok}")
235 };
236
237 CompilerLocatableError {
238 error: CompilerError::SyntaxError(msg),
239 location: (*en).into(),
240 }
241 }
242}
243
244impl SyntaxVisitor<MELCompilerContext> for MELCompiler {
245 fn visit_function_call(
246 &self,
247 syntax: Node,
248 _context: MELCompilerContext,
249 _driver: &SyntaxVisitorDriver,
250 ) -> SyntaxVisitorResult<MELCompilerContext> {
251 let mut walker = syntax.walk();
252 walker.goto_first_child();
253
254 let callee = match _driver.visit(walker.node(), self, _context.clone())? {
255 MELCompilerContext::Expr(callee) => {
256 Result::<Expr<()>, CompilerLocatableError>::Ok(callee)
257 }
258 _ => Result::<Expr<()>, CompilerLocatableError>::Err(CompilerLocatableError {
259 error: CompilerError::EmptyContext,
260 location: syntax.into(),
261 }),
262 }?;
263
264 walker.goto_next_sibling();
265
266 let argument_list = match _driver.visit(walker.node(), self, _context.clone())? {
267 MELCompilerContext::Expr(ast::Expr::ArgumentList(args)) => {
268 Result::<Arc<ArgumentList<()>>, CompilerLocatableError>::Ok(args)
269 }
270 _ => Result::<Arc<ArgumentList<()>>, CompilerLocatableError>::Err(
271 CompilerLocatableError {
272 error: CompilerError::EmptyContext,
273 location: syntax.into(),
274 },
275 ),
276 }?;
277
278 Ok(MELCompilerContext::Expr(Expr::FunctionCall(Arc::new(
279 ast::FunctionCall::<()> {
280 callee: callee.clone(),
281 arguments: (*argument_list).clone(),
282 location: syntax.into(),
283 aug: (),
284 },
285 ))))
286 }
287
288 fn visit_mel(
289 &self,
290 syntax: Node,
291 context: MELCompilerContext,
292 driver: &SyntaxVisitorDriver,
293 ) -> SyntaxVisitorResult<MELCompilerContext> {
294 let mut context = context;
296 for child in syntax.children(&mut syntax.walk()) {
297 context = driver.visit(child, self, context)?;
298 }
299
300 Ok(context)
301 }
302
303 fn visit_identifier(
304 &self,
305 syntax: Node,
306 _context: MELCompilerContext,
307 _driver: &SyntaxVisitorDriver,
308 ) -> SyntaxVisitorResult<MELCompilerContext> {
309 let identifier =
310 syntax
311 .utf8_text(self.source.as_bytes())
312 .map_err(|_| CompilerLocatableError {
313 error: CompilerError::InvalidRange,
314 location: syntax.into(),
315 })?;
316 let id = Identifier {
317 identifier: identifier.to_string(),
318 location: syntax.into(),
319 aug: (),
320 };
321 Ok(MELCompilerContext::Expr(Expr::Identifier(Arc::new(id))))
322 }
323
324 fn visit_argument(
325 &self,
326 syntax: Node,
327 _context: MELCompilerContext,
328 _driver: &SyntaxVisitorDriver,
329 ) -> SyntaxVisitorResult<MELCompilerContext> {
330 let mut walker = syntax.walk();
332 walker.goto_first_child();
333
334 match _driver.visit(walker.node(), self, _context.clone())? {
335 MELCompilerContext::Expr(expr) => Ok(MELCompilerContext::Expr(Expr::Argument(
336 Arc::new(ast::Argument {
337 expr,
338 location: syntax.into(),
339 aug: (),
340 }),
341 ))),
342 _ => Err(CompilerLocatableError {
343 error: CompilerError::EmptyContext,
344 location: syntax.into(),
345 }),
346 }
347 }
348
349 fn visit_argument_list(
350 &self,
351 syntax: Node,
352 context: MELCompilerContext,
353 driver: &SyntaxVisitorDriver,
354 ) -> SyntaxVisitorResult<MELCompilerContext> {
355 let mut walker = syntax.walk();
356 let mut args: Vec<Argument<()>> = vec![];
357 for arg in syntax.named_children(&mut walker) {
358 let argument = match driver.visit(arg, self, context.clone())? {
359 MELCompilerContext::Expr(Expr::Argument(arg)) => {
360 Result::<Arc<Argument<()>>, CompilerLocatableError>::Ok(arg)
361 }
362 _ => Result::<Arc<Argument<()>>, CompilerLocatableError>::Err(
363 CompilerLocatableError {
364 error: CompilerError::EmptyContext,
365 location: syntax.into(),
366 },
367 ),
368 }?;
369 args.push((*argument).clone());
370 }
371
372 Ok(MELCompilerContext::Expr(Expr::ArgumentList(Arc::new(
373 ArgumentList {
374 arguments: args,
375 location: syntax.into(),
376 aug: (),
377 },
378 ))))
379 }
380
381 fn visit_string_concat_operator(
382 &self,
383 syntax: Node,
384 _context: MELCompilerContext,
385 _driver: &SyntaxVisitorDriver,
386 ) -> SyntaxVisitorResult<MELCompilerContext> {
387 let mut walker = syntax.walk();
388 walker.goto_first_child();
389
390 if walker.node().grammar_name() == "string_concat" {
391 return Ok(MELCompilerContext::BinaryOperator(
392 BinaryInfixOperator::Concat(StringConcatOperator {}),
393 ));
394 }
395 Err(CompilerLocatableError {
396 error: CompilerError::BadGrammarElement,
397 location: syntax.into(),
398 })
399 }
400
401 fn visit_logic_operator(
402 &self,
403 syntax: Node,
404 _context: MELCompilerContext,
405 _driver: &SyntaxVisitorDriver,
406 ) -> SyntaxVisitorResult<MELCompilerContext> {
407 let mut walker = syntax.walk();
408 walker.goto_first_child();
409
410 if walker.node().grammar_name() == "and" {
411 return Ok(MELCompilerContext::BinaryOperator(
412 BinaryInfixOperator::Logic(And),
413 ));
414 } else if walker.node().grammar_name() == "or" {
415 return Ok(MELCompilerContext::BinaryOperator(
416 BinaryInfixOperator::Logic(Or),
417 ));
418 }
419 Err(CompilerLocatableError {
420 error: CompilerError::BadGrammarElement,
421 location: syntax.into(),
422 })
423 }
424
425 fn visit_math_operator(
426 &self,
427 syntax: Node,
428 _context: MELCompilerContext,
429 _driver: &SyntaxVisitorDriver,
430 ) -> SyntaxVisitorResult<MELCompilerContext> {
431 let mut walker = syntax.walk();
432 walker.goto_first_child();
433
434 if walker.node().grammar_name() == "plus" {
435 return Ok(MELCompilerContext::BinaryOperator(
436 BinaryInfixOperator::Math(Plus),
437 ));
438 } else if walker.node().grammar_name() == "minus" {
439 return Ok(MELCompilerContext::BinaryOperator(
440 BinaryInfixOperator::Math(Minus),
441 ));
442 } else if walker.node().grammar_name() == "mul" {
443 return Ok(MELCompilerContext::BinaryOperator(
444 BinaryInfixOperator::Math(Multiply),
445 ));
446 } else if walker.node().grammar_name() == "div" {
447 return Ok(MELCompilerContext::BinaryOperator(
448 BinaryInfixOperator::Math(Divide),
449 ));
450 } else if walker.node().grammar_name() == "modulo" {
451 return Ok(MELCompilerContext::BinaryOperator(
452 BinaryInfixOperator::Math(Modulo),
453 ));
454 }
455 Err(CompilerLocatableError {
456 error: CompilerError::BadGrammarElement,
457 location: syntax.into(),
458 })
459 }
460
461 fn visit_binary_expr(
462 &self,
463 syntax: Node,
464 context: MELCompilerContext,
465 driver: &SyntaxVisitorDriver,
466 ) -> SyntaxVisitorResult<MELCompilerContext> {
467 let mut walker = syntax.walk();
468
469 walker.goto_first_child();
470
471 let left = match driver.visit(walker.node(), self, context.clone())? {
472 MELCompilerContext::Expr(left) => Result::<Expr<()>, CompilerLocatableError>::Ok(left),
473 _ => Result::<Expr<()>, CompilerLocatableError>::Err(CompilerLocatableError {
474 error: CompilerError::EmptyContext,
475 location: syntax.into(),
476 }),
477 }?;
478
479 walker.goto_next_sibling();
480
481 let operator = match driver.visit(walker.node(), self, context.clone())? {
482 MELCompilerContext::BinaryOperator(oper) => {
483 Result::<BinaryInfixOperator, CompilerLocatableError>::Ok(oper)
484 }
485 _ => {
486 Result::<BinaryInfixOperator, CompilerLocatableError>::Err(CompilerLocatableError {
487 error: CompilerError::EmptyContext,
488 location: syntax.into(),
489 })
490 }
491 }?;
492
493 walker.goto_next_sibling();
494
495 let right = match driver.visit(walker.node(), self, context.clone())? {
496 MELCompilerContext::Expr(right) => {
497 Result::<Expr<()>, CompilerLocatableError>::Ok(right)
498 }
499 _ => Result::<Expr<()>, CompilerLocatableError>::Err(CompilerLocatableError {
500 error: CompilerError::EmptyContext,
501 location: syntax.into(),
502 }),
503 }?;
504
505 Ok(MELCompilerContext::Expr(BinaryExpr(Arc::new(
506 ast::BinaryExpr {
507 left,
508 op: operator,
509 right,
510 location: syntax.into(),
511 aug: (),
512 },
513 ))))
514 }
515
516 fn visit_ternary_operator(
517 &self,
518 syntax: Node,
519 _context: MELCompilerContext,
520 _driver: &SyntaxVisitorDriver,
521 ) -> SyntaxVisitorResult<MELCompilerContext> {
522 let mut walker = syntax.walk();
523 walker.goto_first_child();
524 if walker.node().grammar_name() == "ternary_question" {
525 return Ok(MELCompilerContext::TernaryOperator(
526 ast::TernaryOperator::Question,
527 ));
528 } else if walker.node().grammar_name() == "ternary_colon" {
529 return Ok(MELCompilerContext::TernaryOperator(
530 ast::TernaryOperator::Colon,
531 ));
532 }
533 Err(CompilerLocatableError {
534 error: CompilerError::BadGrammarElement,
535 location: syntax.into(),
536 })
537 }
538
539 fn visit_ternary_expr(
540 &self,
541 syntax: Node,
542 context: MELCompilerContext,
543 driver: &SyntaxVisitorDriver,
544 ) -> SyntaxVisitorResult<MELCompilerContext> {
545 let mut walker = syntax.walk();
546
547 walker.goto_first_child();
548
549 let condition = match driver.visit(walker.node(), self, context.clone())? {
550 MELCompilerContext::Expr(condition) => {
551 Result::<Expr<()>, CompilerLocatableError>::Ok(condition)
552 }
553 _ => Result::<Expr<()>, CompilerLocatableError>::Err(CompilerLocatableError {
554 error: CompilerError::EmptyContext,
555 location: syntax.into(),
556 }),
557 }?;
558
559 walker.goto_next_sibling();
560
561 match driver.visit(walker.node(), self, context.clone())? {
562 MELCompilerContext::TernaryOperator(ast::TernaryOperator::Question) => {
563 Result::<(), CompilerLocatableError>::Ok(())
564 }
565 _ => Result::<(), CompilerLocatableError>::Err(CompilerLocatableError {
566 error: CompilerError::BadGrammarElement,
567 location: syntax.into(),
568 }),
569 }?;
570
571 walker.goto_next_sibling();
572
573 let yes = match driver.visit(walker.node(), self, context.clone())? {
574 MELCompilerContext::Expr(yes) => Result::<Expr<()>, CompilerLocatableError>::Ok(yes),
575 _ => Result::<Expr<()>, CompilerLocatableError>::Err(CompilerLocatableError {
576 error: CompilerError::BadGrammarElement,
577 location: syntax.into(),
578 }),
579 }?;
580
581 walker.goto_next_sibling();
582
583 match driver.visit(walker.node(), self, context.clone())? {
584 MELCompilerContext::TernaryOperator(ast::TernaryOperator::Colon) => {
585 Result::<(), CompilerLocatableError>::Ok(())
586 }
587 _ => Result::<(), CompilerLocatableError>::Err(CompilerLocatableError {
588 error: CompilerError::BadGrammarElement,
589 location: syntax.into(),
590 }),
591 }?;
592
593 walker.goto_next_sibling();
594
595 let no = match driver.visit(walker.node(), self, context.clone())? {
596 MELCompilerContext::Expr(no) => Result::<Expr<()>, CompilerLocatableError>::Ok(no),
597 _ => Result::<Expr<()>, CompilerLocatableError>::Err(CompilerLocatableError {
598 error: CompilerError::BadGrammarElement,
599 location: syntax.into(),
600 }),
601 }?;
602
603 Ok(MELCompilerContext::Expr(TernaryExpr(Arc::new(
604 ast::TernaryExpr {
605 condition,
606 yes,
607 no,
608 location: syntax.into(),
609 aug: (),
610 },
611 ))))
612 }
613
614 fn visit_literal(
615 &self,
616 syntax: Node,
617 context: MELCompilerContext,
618 driver: &SyntaxVisitorDriver,
619 ) -> SyntaxVisitorResult<MELCompilerContext> {
620 let mut walker = syntax.walk();
621 walker.goto_first_child();
622 driver.visit(walker.node(), self, context)
623 }
624
625 fn visit_boolean_literal(
626 &self,
627 syntax: Node,
628 _context: MELCompilerContext,
629 _driver: &SyntaxVisitorDriver,
630 ) -> SyntaxVisitorResult<MELCompilerContext> {
631 let literal =
632 syntax
633 .utf8_text(self.source.as_bytes())
634 .map_err(|_| CompilerLocatableError {
635 error: CompilerError::InvalidRange,
636 location: syntax.into(),
637 })?;
638 if literal == "true" {
639 return Ok(MELCompilerContext::Expr(Expr::Literal(
640 Boolean(ast::BooleanLiteral::True),
641 syntax.into(),
642 (),
643 )));
644 } else if literal == "false" {
645 return Ok(MELCompilerContext::Expr(Expr::Literal(
646 Boolean(ast::BooleanLiteral::False),
647 syntax.into(),
648 (),
649 )));
650 }
651 Err(CompilerLocatableError {
652 error: CompilerError::BadGrammarElement,
653 location: syntax.into(),
654 })
655 }
656 fn visit_number_literal(
657 &self,
658 syntax: Node,
659 _context: MELCompilerContext,
660 _driver: &SyntaxVisitorDriver,
661 ) -> SyntaxVisitorResult<MELCompilerContext> {
662 let literal =
663 syntax
664 .utf8_text(self.source.as_bytes())
665 .map_err(|_| CompilerLocatableError {
666 error: CompilerError::InvalidRange,
667 location: syntax.into(),
668 })?;
669 let number: usize = literal
670 .parse::<usize>()
671 .map_err(|e| CompilerLocatableError {
672 error: CompilerError::BadLiteral(e.to_string()),
673 location: syntax.into(),
674 })?;
675
676 Ok(MELCompilerContext::Expr(Expr::Literal(
677 Number(ast::NumberLiteral { literal: number }),
678 syntax.into(),
679 (),
680 )))
681 }
682
683 fn visit_string_literal(
684 &self,
685 syntax: Node,
686 _context: MELCompilerContext,
687 _driver: &SyntaxVisitorDriver,
688 ) -> SyntaxVisitorResult<MELCompilerContext> {
689 let literal =
690 syntax
691 .utf8_text(self.source.as_bytes())
692 .map_err(|_| CompilerLocatableError {
693 error: CompilerError::InvalidRange,
694 location: syntax.into(),
695 })?;
696 Ok(MELCompilerContext::Expr(Expr::Literal(
697 ast::Literal::String(ast::StringLiteral {
698 literal: utils::strip_quotes(literal),
699 }),
700 syntax.into(),
701 (),
702 )))
703 }
704
705 fn visit_comparison_operator(
706 &self,
707 syntax: Node,
708 _context: MELCompilerContext,
709 _driver: &SyntaxVisitorDriver,
710 ) -> SyntaxVisitorResult<MELCompilerContext> {
711 let mut walker = syntax.walk();
712 walker.goto_first_child();
713
714 if walker.node().grammar_name() == "eq" {
715 return Ok(MELCompilerContext::BinaryOperator(
716 BinaryInfixOperator::Comparison(ast::ComparisonOperator::Eq),
717 ));
718 } else if walker.node().grammar_name() == "lt" {
719 return Ok(MELCompilerContext::BinaryOperator(
720 BinaryInfixOperator::Comparison(ast::ComparisonOperator::Lt),
721 ));
722 } else if walker.node().grammar_name() == "lte" {
723 return Ok(MELCompilerContext::BinaryOperator(
724 BinaryInfixOperator::Comparison(ast::ComparisonOperator::Lte),
725 ));
726 } else if walker.node().grammar_name() == "gt" {
727 return Ok(MELCompilerContext::BinaryOperator(
728 BinaryInfixOperator::Comparison(ast::ComparisonOperator::Gt),
729 ));
730 } else if walker.node().grammar_name() == "gte" {
731 return Ok(MELCompilerContext::BinaryOperator(
732 BinaryInfixOperator::Comparison(ast::ComparisonOperator::Gte),
733 ));
734 } else if walker.node().grammar_name() == "ne" {
735 return Ok(MELCompilerContext::BinaryOperator(
736 BinaryInfixOperator::Comparison(ast::ComparisonOperator::Ne),
737 ));
738 } else if walker.node().grammar_name() == "regex_eq" {
739 return Ok(MELCompilerContext::BinaryOperator(
740 BinaryInfixOperator::Comparison(ast::ComparisonOperator::Re),
741 ));
742 } else if walker.node().grammar_name() == "ipmatch" {
743 return Ok(MELCompilerContext::BinaryOperator(
744 BinaryInfixOperator::Comparison(ast::ComparisonOperator::IP),
745 ));
746 }
747
748 Err(CompilerLocatableError {
749 error: CompilerError::BadGrammarElement,
750 location: syntax.into(),
751 })
752 }
753
754 fn visit_member_access_expr(
755 &self,
756 syntax: Node,
757 context: MELCompilerContext,
758 driver: &SyntaxVisitorDriver,
759 ) -> SyntaxVisitorResult<MELCompilerContext> {
760 let mut walker = syntax.walk();
761
762 walker.goto_first_child();
763
764 let base = match driver.visit(walker.node(), self, context.clone())? {
765 MELCompilerContext::Expr(base) => Result::<Expr<()>, CompilerLocatableError>::Ok(base),
766 _ => Result::<Expr<()>, CompilerLocatableError>::Err(CompilerLocatableError {
767 error: CompilerError::EmptyContext,
768 location: syntax.into(),
769 }),
770 }?;
771
772 walker.goto_next_sibling();
773
774 match driver.visit(walker.node(), self, context.clone())? {
775 MELCompilerContext::BinaryOperator(BinaryInfixOperator::MemberAccess(_)) => {
776 Result::<(), CompilerLocatableError>::Ok(())
777 }
778 _ => Result::<(), CompilerLocatableError>::Err(CompilerLocatableError {
779 error: CompilerError::BadGrammarElement,
780 location: syntax.into(),
781 }),
782 }?;
783
784 walker.goto_next_sibling();
785
786 let member = match driver.visit(walker.node(), self, context.clone())? {
787 MELCompilerContext::Expr(ast::Expr::Identifier(id)) => {
788 Result::<Arc<Identifier<()>>, CompilerLocatableError>::Ok(id)
789 }
790 _ => {
791 Result::<Arc<Identifier<()>>, CompilerLocatableError>::Err(CompilerLocatableError {
792 error: CompilerError::EmptyContext,
793 location: syntax.into(),
794 })
795 }
796 }?;
797
798 Ok(MELCompilerContext::Expr(MemberAccess(Arc::new(
799 ast::MemberAccessExpression {
800 base,
801 member: (*member).clone(),
802 oper: ast::MemberAccessOperator::MemberAccess,
803 location: syntax.into(),
804 aug: (),
805 },
806 ))))
807 }
808
809 fn visit_member_access_oper(
810 &self,
811 syntax: Node,
812 _context: MELCompilerContext,
813 _driver: &SyntaxVisitorDriver,
814 ) -> SyntaxVisitorResult<MELCompilerContext> {
815 let mut walker = syntax.walk();
816 walker.goto_first_child();
817
818 if walker.node().grammar_name() == "member_access" {
819 return Ok(MELCompilerContext::BinaryOperator(
820 BinaryInfixOperator::MemberAccess(ast::MemberAccessOperator::MemberAccess),
821 ));
822 }
823 Err(CompilerLocatableError {
824 error: CompilerError::BadGrammarElement,
825 location: syntax.into(),
826 })
827 }
828
829 fn visit_regex_literal(
830 &self,
831 syntax: Node,
832 _context: MELCompilerContext,
833 _driver: &SyntaxVisitorDriver,
834 ) -> SyntaxVisitorResult<MELCompilerContext> {
835 let literal =
836 syntax
837 .utf8_text(self.source.as_bytes())
838 .map_err(|_| CompilerLocatableError {
839 error: CompilerError::InvalidRange,
840 location: syntax.into(),
841 })?;
842
843 let regex = match RegexBuilder::new(&utils::strip_slashes(literal)).build() {
844 Ok(regex) => regex,
845 Err(e) => {
846 return Err(CompilerLocatableError {
847 error: CompilerError::BadLiteral(e.to_string()),
848 location: syntax.into(),
849 });
850 }
851 };
852
853 Ok(MELCompilerContext::Expr(Expr::Literal(
854 ast::Literal::Regex(ast::RegexLiteral { literal: regex }),
855 syntax.into(),
856 (),
857 )))
858 }
859
860 fn visit_ipaddress_literal(
861 &self,
862 syntax: Node,
863 _context: MELCompilerContext,
864 _driver: &SyntaxVisitorDriver,
865 ) -> SyntaxVisitorResult<MELCompilerContext> {
866 let literal =
867 syntax
868 .utf8_text(self.source.as_bytes())
869 .map_err(|_| CompilerLocatableError {
870 error: CompilerError::InvalidRange,
871 location: syntax.into(),
872 })?;
873
874 let ip_addr: IpAddr = literal
875 .parse::<IpAddr>()
876 .map_err(|e| CompilerLocatableError {
877 error: CompilerError::BadLiteral(e.to_string()),
878 location: syntax.into(),
879 })?;
880
881 Ok(MELCompilerContext::Expr(Expr::Literal(
882 ast::Literal::IPAddress(ast::IPAddressLiteral { literal: ip_addr }),
883 syntax.into(),
884 (),
885 )))
886 }
887
888 fn visit_error(
889 &self,
890 syntax: Node,
891 _context: MELCompilerContext,
892 _driver: &SyntaxVisitorDriver,
893 ) -> CompilerLocatableError {
894 if syntax.is_error()
897 && let Some(child) = syntax.child(0)
898 {
899 self.extract_error(&child)
900 } else if syntax.is_missing() {
902 self.extract_error(&syntax)
903 } else {
904 CompilerLocatableError {
905 error: CompilerError::SyntaxError(
906 "Unknown syntax error (couldn't get token)".to_string(),
907 ),
908 location: syntax.into(),
909 }
910 }
911 }
912}
913
914pub struct SyntaxVisitorDriver {}
915
916impl SyntaxVisitorDriver {
917 pub fn visit<T, U: SyntaxVisitor<T>>(
918 &self,
919 node: Node,
920 visitor: &U,
921 context: T,
922 ) -> SyntaxVisitorResult<T> {
923 type Visitor<T, U> = fn(&U, Node, T, &SyntaxVisitorDriver) -> SyntaxVisitorResult<T>;
924
925 let mut hm: HashMap<String, Visitor<T, U>> = HashMap::new();
926
927 ast::FunctionCall::<()>::name().iter().for_each(|name| {
930 hm.insert(
931 name.clone(),
932 U::visit_function_call as fn(&U, Node, _, &Self) -> SyntaxVisitorResult<T>,
933 );
934 });
935 ast::Expr::<()>::name().iter().for_each(|name| {
936 hm.insert(
937 name.clone(),
938 U::visit_expr as fn(&U, Node, _, &Self) -> SyntaxVisitorResult<T>,
939 );
940 });
941 ast::Mel::<()>::name().iter().for_each(|name| {
942 hm.insert(
943 name.clone(),
944 U::visit_mel as fn(&U, Node, _, &Self) -> SyntaxVisitorResult<T>,
945 );
946 });
947 ast::Identifier::<()>::name().iter().for_each(|name| {
948 hm.insert(
949 name.clone(),
950 U::visit_identifier as fn(&U, Node, _, &Self) -> SyntaxVisitorResult<T>,
951 );
952 });
953 ast::ArgumentList::<()>::name().iter().for_each(|name| {
954 hm.insert(
955 name.clone(),
956 U::visit_argument_list as fn(&U, Node, _, &Self) -> SyntaxVisitorResult<T>,
957 );
958 });
959 ast::Argument::<()>::name().iter().for_each(|name| {
960 hm.insert(
961 name.clone(),
962 U::visit_argument as fn(&U, Node, _, &Self) -> SyntaxVisitorResult<T>,
963 );
964 });
965 ast::LogicOperator::name().iter().for_each(|name| {
966 hm.insert(
967 name.clone(),
968 U::visit_logic_operator as fn(&U, Node, _, &Self) -> SyntaxVisitorResult<T>,
969 );
970 });
971 ast::StringConcatOperator::name().iter().for_each(|name| {
972 hm.insert(
973 name.clone(),
974 U::visit_string_concat_operator as fn(&U, Node, _, &Self) -> SyntaxVisitorResult<T>,
975 );
976 });
977 ast::ComparisonOperator::name().iter().for_each(|name| {
978 hm.insert(
979 name.clone(),
980 U::visit_comparison_operator as fn(&U, Node, _, &Self) -> SyntaxVisitorResult<T>,
981 );
982 });
983 ast::BinaryExpr::<()>::name().iter().for_each(|name| {
984 hm.insert(
985 name.clone(),
986 U::visit_binary_expr as fn(&U, Node, _, &Self) -> SyntaxVisitorResult<T>,
987 );
988 });
989 ast::MemberAccessExpression::<()>::name()
990 .iter()
991 .for_each(|name| {
992 hm.insert(
993 name.clone(),
994 U::visit_member_access_expr as fn(&U, Node, _, &Self) -> SyntaxVisitorResult<T>,
995 );
996 });
997 ast::MemberAccessOperator::name().iter().for_each(|name| {
998 hm.insert(
999 name.clone(),
1000 U::visit_member_access_oper as fn(&U, Node, _, &Self) -> SyntaxVisitorResult<T>,
1001 );
1002 });
1003 ast::TernaryExpr::<()>::name().iter().for_each(|name| {
1004 hm.insert(
1005 name.clone(),
1006 U::visit_ternary_expr as fn(&U, Node, _, &Self) -> SyntaxVisitorResult<T>,
1007 );
1008 });
1009 ast::MathOperator::name().iter().for_each(|name| {
1010 hm.insert(
1011 name.clone(),
1012 U::visit_math_operator as fn(&U, Node, _, &Self) -> SyntaxVisitorResult<T>,
1013 );
1014 });
1015 ast::TernaryOperator::name().iter().for_each(|name| {
1016 hm.insert(
1017 name.clone(),
1018 U::visit_ternary_operator as fn(&U, Node, _, &Self) -> SyntaxVisitorResult<T>,
1019 );
1020 });
1021 ast::Literal::name().iter().for_each(|name| {
1022 hm.insert(
1023 name.clone(),
1024 U::visit_literal as fn(&U, Node, _, &Self) -> SyntaxVisitorResult<T>,
1025 );
1026 });
1027 ast::BooleanLiteral::name().iter().for_each(|name| {
1028 hm.insert(
1029 name.clone(),
1030 U::visit_boolean_literal as fn(&U, Node, _, &Self) -> SyntaxVisitorResult<T>,
1031 );
1032 });
1033 ast::NumberLiteral::name().iter().for_each(|name| {
1034 hm.insert(
1035 name.clone(),
1036 U::visit_number_literal as fn(&U, Node, _, &Self) -> SyntaxVisitorResult<T>,
1037 );
1038 });
1039 ast::StringLiteral::name().iter().for_each(|name| {
1040 hm.insert(
1041 name.clone(),
1042 U::visit_string_literal as fn(&U, Node, _, &Self) -> SyntaxVisitorResult<T>,
1043 );
1044 });
1045 ast::RegexLiteral::name().iter().for_each(|name| {
1046 hm.insert(
1047 name.clone(),
1048 U::visit_regex_literal as fn(&U, Node, _, &Self) -> SyntaxVisitorResult<T>,
1049 );
1050 });
1051 ast::IPAddressLiteral::name().iter().for_each(|name| {
1052 hm.insert(
1053 name.clone(),
1054 U::visit_ipaddress_literal as fn(&U, Node, _, &Self) -> SyntaxVisitorResult<T>,
1055 );
1056 });
1057
1058 if node.is_error() || node.is_missing() || node.is_extra() {
1060 Err(visitor.visit_error(node, context, self))
1061 } else {
1062 match hm.get(node.grammar_name()) {
1063 Some(callable) => (callable)(visitor, node, context, self),
1064 None => Err(CompilerLocatableError {
1065 error: CompilerError::NoSuchVisitor(node.grammar_name().into()),
1066 location: node.into(),
1067 }),
1068 }
1069 }
1070 }
1071}
1072
1073impl From<Node<'_>> for TextLocation {
1074 fn from(value: Node) -> Self {
1075 TextLocation {
1076 start: value.start_byte(),
1077 extent: value.end_byte() - value.start_byte(),
1078 }
1079 }
1080}