cel_parser/
parser.rs

1use crate::ast::{
2    operators, CallExpr, EntryExpr, Expr, IdedEntryExpr, IdedExpr, ListExpr, MapEntryExpr, MapExpr,
3    SelectExpr, SourceInfo, StructExpr, StructFieldExpr,
4};
5use crate::gen::{
6    BoolFalseContext, BoolTrueContext, BytesContext, CalcContext, CalcContextAttrs,
7    ConditionalAndContext, ConditionalOrContext, ConstantLiteralContext,
8    ConstantLiteralContextAttrs, CreateListContext, CreateMessageContext, CreateStructContext,
9    DoubleContext, ExprContext, FieldInitializerListContext, GlobalCallContext, IdentContext,
10    IndexContext, IndexContextAttrs, IntContext, ListInitContextAll, LogicalNotContext,
11    LogicalNotContextAttrs, MapInitializerListContextAll, MemberCallContext,
12    MemberCallContextAttrs, MemberExprContext, MemberExprContextAttrs, NegateContext,
13    NegateContextAttrs, NestedContext, NullContext, OptFieldContextAttrs, PrimaryExprContext,
14    PrimaryExprContextAttrs, RelationContext, RelationContextAttrs, SelectContext,
15    SelectContextAttrs, StartContext, StartContextAttrs, StringContext, UintContext,
16};
17use crate::reference::Val;
18use crate::{ast, gen, macros, parse};
19use antlr4rust::common_token_stream::CommonTokenStream;
20use antlr4rust::error_listener::ErrorListener;
21use antlr4rust::errors::ANTLRError;
22use antlr4rust::parser::ParserNodeType;
23use antlr4rust::parser_rule_context::ParserRuleContext;
24use antlr4rust::recognizer::Recognizer;
25use antlr4rust::token::{CommonToken, Token};
26use antlr4rust::token_factory::TokenFactory;
27use antlr4rust::tree::{ParseTree, ParseTreeVisitorCompat, VisitChildren};
28use antlr4rust::{InputStream, Parser as AntlrParser};
29use std::cell::RefCell;
30use std::error::Error;
31use std::fmt::Display;
32use std::mem;
33use std::ops::Deref;
34use std::rc::Rc;
35
36pub struct MacroExprHelper<'a> {
37    helper: &'a mut ParserHelper,
38    id: u64,
39}
40
41impl MacroExprHelper<'_> {
42    pub fn next_expr(&mut self, expr: Expr) -> IdedExpr {
43        self.helper.next_expr_for(self.id, expr)
44    }
45
46    pub(crate) fn pos_for(&self, id: u64) -> Option<(isize, isize)> {
47        self.helper.source_info.pos_for(id)
48    }
49}
50
51#[derive(Debug)]
52pub struct ParseErrors {
53    pub errors: Vec<ParseError>,
54}
55
56impl Display for ParseErrors {
57    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58        for (i, e) in self.errors.iter().enumerate() {
59            if i != 0 {
60                writeln!(f)?;
61            }
62            write!(f, "{}", e)?;
63        }
64        Ok(())
65    }
66}
67
68impl Error for ParseErrors {}
69
70#[allow(dead_code)]
71#[derive(Debug)]
72pub struct ParseError {
73    pub source: Option<Box<dyn Error>>,
74    pub pos: (isize, isize),
75    pub msg: String,
76    pub expr_id: u64,
77    pub source_info: Option<Rc<SourceInfo>>,
78}
79
80impl Display for ParseError {
81    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82        write!(
83            f,
84            "ERROR: <input>:{}:{}: {}",
85            self.pos.0, self.pos.1, self.msg
86        )?;
87        if let Some(info) = &self.source_info {
88            if let Some(line) = info.snippet(self.pos.0 - 1) {
89                write!(f, "\n| {}", line)?;
90                write!(f, "\n| {:.>width$}", "^", width = self.pos.1 as usize)?;
91            }
92        }
93        Ok(())
94    }
95}
96
97impl Error for ParseError {}
98
99pub struct Parser {
100    ast: ast::Ast,
101    helper: ParserHelper,
102    errors: Vec<ParseError>,
103}
104
105impl Parser {
106    pub fn new() -> Self {
107        Self {
108            ast: ast::Ast {
109                expr: IdedExpr::default(),
110            },
111            helper: ParserHelper::default(),
112            errors: Vec::default(),
113        }
114    }
115
116    fn new_logic_manager(&self, func: &str, term: IdedExpr) -> LogicManager {
117        LogicManager {
118            function: func.to_string(),
119            terms: vec![term],
120            ops: vec![],
121        }
122    }
123
124    fn global_call_or_macro(
125        &mut self,
126        id: u64,
127        func_name: String,
128        args: Vec<IdedExpr>,
129    ) -> IdedExpr {
130        match macros::find_expander(&func_name, None, &args) {
131            None => IdedExpr {
132                id,
133                expr: Expr::Call(CallExpr {
134                    target: None,
135                    func_name,
136                    args,
137                }),
138            },
139            Some(expander) => {
140                let mut helper = MacroExprHelper {
141                    helper: &mut self.helper,
142                    id,
143                };
144                match expander(&mut helper, None, args) {
145                    Ok(expr) => expr,
146                    Err(err) => self.report_parse_error(None, err),
147                }
148            }
149        }
150    }
151
152    fn receiver_call_or_macro(
153        &mut self,
154        id: u64,
155        func_name: String,
156        target: IdedExpr,
157        args: Vec<IdedExpr>,
158    ) -> IdedExpr {
159        match macros::find_expander(&func_name, Some(&target), &args) {
160            None => IdedExpr {
161                id,
162                expr: Expr::Call(CallExpr {
163                    target: Some(Box::new(target)),
164                    func_name,
165                    args,
166                }),
167            },
168            Some(expander) => {
169                let mut helper = MacroExprHelper {
170                    helper: &mut self.helper,
171                    id,
172                };
173                match expander(&mut helper, Some(target), args) {
174                    Ok(expr) => expr,
175                    Err(err) => self.report_parse_error(None, err),
176                }
177            }
178        }
179    }
180
181    pub fn parse(mut self, source: &str) -> Result<IdedExpr, ParseErrors> {
182        let parse_errors = Rc::new(RefCell::new(Vec::<ParseError>::new()));
183        let stream = InputStream::new(source);
184        let mut lexer = gen::CELLexer::new(stream);
185        lexer.remove_error_listeners();
186        lexer.add_error_listener(Box::new(ParserErrorListener {
187            parse_errors: parse_errors.clone(),
188        }));
189
190        // todo! might want to avoid this cloning here...
191        self.helper.source_info.source = source.into();
192
193        let mut prsr = gen::CELParser::new(CommonTokenStream::new(lexer));
194        prsr.remove_error_listeners();
195        prsr.add_error_listener(Box::new(ParserErrorListener {
196            parse_errors: parse_errors.clone(),
197        }));
198        let r = match prsr.start() {
199            Ok(t) => Ok(self.visit(t.deref())),
200            Err(e) => Err(ParseError {
201                source: Some(Box::new(e)),
202                pos: (0, 0),
203                msg: "UNKNOWN".to_string(),
204                expr_id: 0,
205                source_info: None,
206            }),
207        };
208
209        let info = self.helper.source_info;
210        let source_info = Rc::new(info);
211
212        let mut errors = parse_errors.take();
213        errors.extend(self.errors);
214        errors.sort_by(|a, b| a.pos.cmp(&b.pos));
215
216        if errors.is_empty() {
217            r.map_err(|e| ParseErrors { errors: vec![e] })
218        } else {
219            Err(ParseErrors {
220                errors: errors
221                    .into_iter()
222                    .map(|mut e: ParseError| {
223                        e.source_info = Some(source_info.clone());
224                        e
225                    })
226                    .collect(),
227            })
228        }
229    }
230
231    fn field_initializer_list(
232        &mut self,
233        ctx: &FieldInitializerListContext<'_>,
234    ) -> Vec<IdedEntryExpr> {
235        let mut fields = Vec::with_capacity(ctx.fields.len());
236        for (i, field) in ctx.fields.iter().enumerate() {
237            if i >= ctx.cols.len() || i >= ctx.values.len() {
238                return vec![];
239            }
240            let id = self.helper.next_id(&ctx.cols[i]);
241
242            match field.escapeIdent() {
243                None => {
244                    self.report_error::<ParseError, _>(
245                        field.start().deref(),
246                        None,
247                        "unsupported ident type",
248                    );
249                    continue;
250                }
251                Some(ident) => {
252                    let field_name = ident.get_text().to_string();
253                    let value = self.visit(ctx.values[i].as_ref());
254                    if let Some(opt) = &field.opt {
255                        self.report_error::<ParseError, _>(
256                            opt.as_ref(),
257                            None,
258                            "unsupported syntax '?'",
259                        );
260                        continue;
261                    }
262                    fields.push(IdedEntryExpr {
263                        id,
264                        expr: EntryExpr::StructField(StructFieldExpr {
265                            field: field_name,
266                            value,
267                            optional: false,
268                        }),
269                    });
270                }
271            }
272        }
273        fields
274    }
275
276    fn map_initializer_list(&mut self, ctx: &MapInitializerListContextAll) -> Vec<IdedEntryExpr> {
277        if ctx.keys.is_empty() {
278            return vec![];
279        }
280        let mut entries = Vec::with_capacity(ctx.cols.len());
281        let keys = &ctx.keys;
282        let vals = &ctx.values;
283        for (i, col) in ctx.cols.iter().enumerate() {
284            if i >= keys.len() || i >= vals.len() {
285                return vec![];
286            }
287            let id = self.helper.next_id(col);
288            let key = self.visit(keys[i].as_ref());
289            if let Some(opt) = &keys[i].opt {
290                self.report_error::<ParseError, _>(opt.as_ref(), None, "unsupported syntax '?'");
291                continue;
292            }
293            let value = self.visit(vals[i].as_ref());
294            entries.push(IdedEntryExpr {
295                id,
296                expr: EntryExpr::MapEntry(MapEntryExpr {
297                    key,
298                    value,
299                    optional: false,
300                }),
301            })
302        }
303        entries
304    }
305
306    fn list_initializer_list(&mut self, ctx: &ListInitContextAll) -> Vec<IdedExpr> {
307        let mut list = Vec::default();
308        for e in &ctx.elems {
309            match &e.e {
310                None => return Vec::default(),
311                Some(exp) => {
312                    if let Some(opt) = &e.opt {
313                        self.report_error::<ParseError, _>(
314                            opt.as_ref(),
315                            None,
316                            "unsupported syntax '?'",
317                        );
318                        continue;
319                    }
320                    list.push(self.visit(exp.as_ref()));
321                }
322            }
323        }
324        list
325    }
326
327    fn report_error<E: Error + 'static, S: Into<String>>(
328        &mut self,
329        token: &CommonToken,
330        e: Option<E>,
331        s: S,
332    ) -> IdedExpr {
333        let error = ParseError {
334            source: e.map(|e| e.into()),
335            pos: (token.line, token.column + 1),
336            msg: s.into(),
337            expr_id: 0,
338            source_info: None,
339        };
340        self.report_parse_error(Some(token), error)
341    }
342
343    fn report_parse_error(&mut self, token: Option<&CommonToken>, mut e: ParseError) -> IdedExpr {
344        let expr = if let Some(token) = token {
345            self.helper.next_expr(token, Expr::default())
346        } else {
347            IdedExpr {
348                id: 0,
349                expr: Expr::default(),
350            }
351        };
352        e.expr_id = expr.id;
353        self.errors.push(e);
354        expr
355    }
356}
357
358struct ParserErrorListener {
359    parse_errors: Rc<RefCell<Vec<ParseError>>>,
360}
361
362impl<'a, T: Recognizer<'a>> ErrorListener<'a, T> for ParserErrorListener {
363    fn syntax_error(
364        &self,
365        _recognizer: &T,
366        offending_symbol: Option<&<T::TF as TokenFactory<'a>>::Inner>,
367        line: isize,
368        column: isize,
369        msg: &str,
370        _error: Option<&ANTLRError>,
371    ) {
372        match offending_symbol {
373            Some(offending_symbol)
374                if offending_symbol.get_token_type() == gen::cellexer::WHITESPACE => {}
375            _ => self.parse_errors.borrow_mut().push(ParseError {
376                source: None,
377                pos: (line, column + 1),
378                msg: format!("Syntax error: {msg}"),
379                expr_id: 0,
380                source_info: None,
381            }),
382        }
383    }
384}
385
386impl Default for Parser {
387    fn default() -> Self {
388        Self::new()
389    }
390}
391
392impl ParseTreeVisitorCompat<'_> for Parser {
393    type Node = gen::CELParserContextType;
394    type Return = IdedExpr;
395    fn temp_result(&mut self) -> &mut Self::Return {
396        &mut self.ast.expr
397    }
398
399    fn visit(&mut self, node: &<Self::Node as ParserNodeType<'_>>::Type) -> Self::Return {
400        //println!("{node:?}");
401        self.visit_node(node);
402        mem::take(self.temp_result())
403    }
404
405    fn aggregate_results(&self, _aggregate: Self::Return, next: Self::Return) -> Self::Return {
406        next
407    }
408}
409
410impl gen::CELVisitorCompat<'_> for Parser {
411    fn visit_start(&mut self, ctx: &StartContext<'_>) -> Self::Return {
412        match &ctx.expr() {
413            None => self.report_error::<ParseError, _>(
414                ctx.start().deref(),
415                None,
416                "No `ExprContextAll`!",
417            ),
418            Some(expr) => self.visit(expr.as_ref()),
419        }
420    }
421
422    fn visit_expr(&mut self, ctx: &ExprContext<'_>) -> Self::Return {
423        match &ctx.op {
424            None => match &ctx.e {
425                None => self.report_error::<ParseError, _>(
426                    ctx.start().deref(),
427                    None,
428                    "No `ConditionalOrContextAll`!",
429                ),
430                Some(e) => <Self as ParseTreeVisitorCompat>::visit(self, e.as_ref()),
431            },
432            Some(op) => {
433                if let (Some(e), Some(e1), Some(e2)) = (&ctx.e, &ctx.e1, &ctx.e2) {
434                    let result = self.visit(e.as_ref());
435                    let op_id = self.helper.next_id(op);
436                    let if_true = self.visit(e1.as_ref());
437                    let if_false = self.visit(e2.as_ref());
438                    self.global_call_or_macro(
439                        op_id,
440                        operators::CONDITIONAL.to_string(),
441                        vec![result, if_true, if_false],
442                    )
443                } else {
444                    self.report_error::<ParseError, _>(
445                        ctx.start().deref(),
446                        None,
447                        format!(
448                            "Incomplete `ExprContext` for `{}` expression!",
449                            operators::CONDITIONAL
450                        ),
451                    )
452                }
453            }
454        }
455    }
456
457    fn visit_conditionalOr(&mut self, ctx: &ConditionalOrContext<'_>) -> Self::Return {
458        let result = match &ctx.e {
459            None => {
460                self.report_error::<ParseError, _>(
461                    ctx.start().deref(),
462                    None,
463                    "No `ConditionalAndContextAll`!",
464                );
465                IdedExpr::default()
466            }
467            Some(e) => <Self as ParseTreeVisitorCompat>::visit(self, e.as_ref()),
468        };
469        if ctx.ops.is_empty() {
470            result
471        } else {
472            let mut l = self.new_logic_manager(operators::LOGICAL_OR, result);
473            let rest = &ctx.e1;
474            if ctx.ops.len() > rest.len() {
475                // why is >= not ok?
476                self.report_error::<ParseError, _>(
477                    &ctx.start(),
478                    None,
479                    "unexpected character, wanted '||'",
480                );
481                return IdedExpr::default();
482            }
483            for (i, op) in ctx.ops.iter().enumerate() {
484                let next = self.visit(rest[i].deref());
485                let op_id = self.helper.next_id(op);
486                l.add_term(op_id, next)
487            }
488            l.expr()
489        }
490    }
491
492    fn visit_conditionalAnd(&mut self, ctx: &ConditionalAndContext<'_>) -> Self::Return {
493        let result = match &ctx.e {
494            None => self.report_error::<ParseError, _>(
495                ctx.start().deref(),
496                None,
497                "No `RelationContextAll`!",
498            ),
499            Some(e) => <Self as ParseTreeVisitorCompat>::visit(self, e.as_ref()),
500        };
501        if ctx.ops.is_empty() {
502            result
503        } else {
504            let mut l = self.new_logic_manager(operators::LOGICAL_AND, result);
505            let rest = &ctx.e1;
506            if ctx.ops.len() > rest.len() {
507                // why is >= not ok?
508                self.report_error::<ParseError, _>(
509                    &ctx.start(),
510                    None,
511                    "unexpected character, wanted '&&'",
512                );
513                return IdedExpr::default();
514            }
515            for (i, op) in ctx.ops.iter().enumerate() {
516                let next = self.visit(rest[i].deref());
517                let op_id = self.helper.next_id(op);
518                l.add_term(op_id, next)
519            }
520            l.expr()
521        }
522    }
523
524    fn visit_relation(&mut self, ctx: &RelationContext<'_>) -> Self::Return {
525        if ctx.op.is_none() {
526            match ctx.calc() {
527                None => self.report_error::<ParseError, _>(
528                    ctx.start().deref(),
529                    None,
530                    "No `CalcContextAll`!",
531                ),
532                Some(calc) => <Self as ParseTreeVisitorCompat>::visit(self, calc.as_ref()),
533            }
534        } else {
535            match &ctx.op {
536                None => <Self as ParseTreeVisitorCompat>::visit_children(self, ctx),
537                Some(op) => {
538                    if let (Some(lhs), Some(rhs)) = (ctx.relation(0), ctx.relation(1)) {
539                        let lhs = self.visit(lhs.as_ref());
540                        let op_id = self.helper.next_id(op.as_ref());
541                        let rhs = self.visit(rhs.as_ref());
542                        match operators::find_operator(op.get_text()) {
543                            None => {
544                                self.report_error::<ParseError, _>(
545                                    op.as_ref(),
546                                    None,
547                                    format!("Unknown `{}` operator!", op.get_text()),
548                                );
549                                IdedExpr::default()
550                            }
551                            Some(op) => {
552                                self.global_call_or_macro(op_id, op.to_string(), vec![lhs, rhs])
553                            }
554                        }
555                    } else {
556                        self.report_error::<ParseError, _>(
557                            ctx.start().deref(),
558                            None,
559                            format!("Incomplete `RelationContext` for `{:?}`!", ctx.op),
560                        )
561                    }
562                }
563            }
564        }
565    }
566
567    fn visit_calc(&mut self, ctx: &CalcContext<'_>) -> Self::Return {
568        match &ctx.op {
569            None => match &ctx.unary() {
570                None => self.report_error::<ParseError, _>(
571                    ctx.start().deref(),
572                    None,
573                    "No `UnaryContextAll`!",
574                ),
575                Some(unary) => self.visit(unary.as_ref()),
576            },
577            Some(op) => {
578                if let (Some(lhs), Some(rhs)) = (ctx.calc(0), ctx.calc(1)) {
579                    let lhs = self.visit(lhs.as_ref());
580                    let op_id = self.helper.next_id(op);
581                    let rhs = self.visit(rhs.as_ref());
582                    match operators::find_operator(op.get_text()) {
583                        None => self.report_error::<ParseError, _>(
584                            op,
585                            None,
586                            format!("Unknown `{}` operator!", op.get_text()),
587                        ),
588                        Some(op) => {
589                            self.global_call_or_macro(op_id, op.to_string(), vec![lhs, rhs])
590                        }
591                    }
592                } else {
593                    self.report_error::<ParseError, _>(
594                        ctx.start().deref(),
595                        None,
596                        "Incomplete `CalcContext`!",
597                    )
598                }
599            }
600        }
601    }
602
603    fn visit_MemberExpr(&mut self, ctx: &MemberExprContext<'_>) -> Self::Return {
604        match &ctx.member() {
605            None => {
606                self.report_error::<ParseError, _>(&ctx.start(), None, "No `MemberContextAll`!")
607            }
608            Some(ctx) => <Self as ParseTreeVisitorCompat>::visit(self, ctx.as_ref()),
609        }
610    }
611
612    fn visit_LogicalNot(&mut self, ctx: &LogicalNotContext<'_>) -> Self::Return {
613        match &ctx.member() {
614            None => {
615                self.report_error::<ParseError, _>(&ctx.start(), None, "No `MemberContextAll`!");
616                IdedExpr::default()
617            }
618            Some(member) => {
619                if ctx.ops.len() % 2 == 0 {
620                    self.visit(member.as_ref());
621                }
622                let op_id = self.helper.next_id(&ctx.ops[0]);
623                let target = self.visit(member.as_ref());
624                self.global_call_or_macro(op_id, operators::LOGICAL_NOT.to_string(), vec![target])
625            }
626        }
627    }
628
629    fn visit_Negate(&mut self, ctx: &NegateContext<'_>) -> Self::Return {
630        match &ctx.member() {
631            None => {
632                self.report_error::<ParseError, _>(&ctx.start(), None, "No `MemberContextAll`!")
633            }
634            Some(member) => {
635                if ctx.ops.len() % 2 == 0 {
636                    self.visit(member.as_ref());
637                }
638                let op_id = self.helper.next_id(&ctx.ops[0]);
639                let target = self.visit(member.as_ref());
640                self.global_call_or_macro(op_id, operators::NEGATE.to_string(), vec![target])
641            }
642        }
643    }
644
645    fn visit_MemberCall(&mut self, ctx: &MemberCallContext<'_>) -> Self::Return {
646        if let (Some(operand), Some(id), Some(open)) = (&ctx.member(), &ctx.id, &ctx.open) {
647            let operand = self.visit(operand.as_ref());
648            let id = id.get_text();
649            let op_id = self.helper.next_id(open.as_ref());
650            let args = ctx
651                .args
652                .iter()
653                .flat_map(|arg| &arg.e)
654                .map(|arg| self.visit(arg.deref()))
655                .collect::<Vec<IdedExpr>>();
656            self.receiver_call_or_macro(op_id, id.to_string(), operand, args)
657        } else {
658            self.report_error::<ParseError, _>(
659                &ctx.start(),
660                None,
661                "Incomplete `MemberCallContext`!",
662            )
663        }
664    }
665
666    fn visit_Select(&mut self, ctx: &SelectContext<'_>) -> Self::Return {
667        if let (Some(member), Some(id), Some(op)) = (&ctx.member(), &ctx.id, &ctx.op) {
668            let operand = self.visit(member.as_ref());
669            let field = id.get_text();
670            if let Some(_opt) = &ctx.opt {
671                return self.report_error::<ParseError, _>(
672                    op.as_ref(),
673                    None,
674                    "unsupported syntax '.?'",
675                );
676            }
677            self.helper.next_expr(
678                op.as_ref(),
679                Expr::Select(SelectExpr {
680                    operand: Box::new(operand),
681                    field,
682                    test: false,
683                }),
684            )
685        } else {
686            self.report_error::<ParseError, _>(&ctx.start(), None, "Incomplete `SelectContext`!")
687        }
688    }
689
690    fn visit_PrimaryExpr(&mut self, ctx: &PrimaryExprContext<'_>) -> Self::Return {
691        match &ctx.primary() {
692            None => {
693                self.report_error::<ParseError, _>(&ctx.start(), None, "No `PrimaryContextAll`!")
694            }
695            Some(primary) => <Self as ParseTreeVisitorCompat>::visit(self, primary.as_ref()),
696        }
697    }
698
699    fn visit_Index(&mut self, ctx: &IndexContext<'_>) -> Self::Return {
700        if let (Some(member), Some(index)) = (&ctx.member(), &ctx.index) {
701            let target = self.visit(member.as_ref());
702            match &ctx.op {
703                None => self.report_error::<ParseError, _>(&ctx.start(), None, "No `Index`!"),
704                Some(op) => {
705                    let op_id = self.helper.next_id(op);
706                    let index = self.visit(index.as_ref());
707                    if let Some(_opt) = &ctx.opt {
708                        return self.report_error::<ParseError, _>(
709                            op.as_ref(),
710                            None,
711                            "unsupported syntax '[?'",
712                        );
713                    }
714                    self.global_call_or_macro(
715                        op_id,
716                        operators::INDEX.to_string(),
717                        vec![target, index],
718                    )
719                }
720            }
721        } else {
722            self.report_error::<ParseError, _>(&ctx.start(), None, "Incomplete `IndexContext`!")
723        }
724    }
725
726    fn visit_Ident(&mut self, ctx: &IdentContext<'_>) -> Self::Return {
727        match &ctx.id {
728            None => {
729                self.report_error::<ParseError, _>(&ctx.start(), None, "No `Identifier`!");
730                IdedExpr::default()
731            }
732            Some(id) => {
733                let ident = id.clone().text;
734                self.helper
735                    .next_expr(id.deref(), Expr::Ident(ident.to_string()))
736            }
737        }
738    }
739
740    fn visit_GlobalCall(&mut self, ctx: &GlobalCallContext<'_>) -> Self::Return {
741        match &ctx.id {
742            None => IdedExpr::default(),
743            Some(id) => {
744                let mut id = id.get_text().to_string();
745                if ctx.leadingDot.is_some() {
746                    id = format!(".{}", id);
747                }
748                let op_id = self.helper.next_id_for_token(ctx.op.as_deref());
749                let args = ctx
750                    .args
751                    .iter()
752                    .flat_map(|arg| &arg.e)
753                    .map(|arg| self.visit(arg.deref()))
754                    .collect::<Vec<IdedExpr>>();
755                self.global_call_or_macro(op_id, id, args)
756            }
757        }
758    }
759
760    fn visit_Nested(&mut self, ctx: &NestedContext<'_>) -> Self::Return {
761        match &ctx.e {
762            None => {
763                self.report_error::<ParseError, _>(
764                    ctx.start().deref(),
765                    None,
766                    "No `ExprContextAll`!",
767                );
768                IdedExpr::default()
769            }
770            Some(e) => self.visit(e.as_ref()),
771        }
772    }
773
774    fn visit_CreateList(&mut self, ctx: &CreateListContext<'_>) -> Self::Return {
775        let list_id = self.helper.next_id_for_token(ctx.op.as_deref());
776        let elements = match &ctx.elems {
777            None => Vec::default(),
778            Some(elements) => self.list_initializer_list(elements.deref()),
779        };
780        IdedExpr {
781            id: list_id,
782            expr: Expr::List(ListExpr { elements }),
783        }
784    }
785
786    fn visit_CreateStruct(&mut self, ctx: &CreateStructContext<'_>) -> Self::Return {
787        let struct_id = self.helper.next_id_for_token(ctx.op.as_deref());
788        let entries = match &ctx.entries {
789            Some(entries) => self.map_initializer_list(entries.deref()),
790            None => Vec::default(),
791        };
792        IdedExpr {
793            id: struct_id,
794            expr: Expr::Map(MapExpr { entries }),
795        }
796    }
797
798    fn visit_CreateMessage(&mut self, ctx: &CreateMessageContext<'_>) -> Self::Return {
799        let mut message_name = String::new();
800        for id in &ctx.ids {
801            if !message_name.is_empty() {
802                message_name.push('.');
803            }
804            message_name.push_str(id.get_text());
805        }
806        if ctx.leadingDot.is_some() {
807            message_name = format!(".{}", message_name);
808        }
809        let op_id = match &ctx.op {
810            None => {
811                self.report_error::<ParseError, _>(&ctx.start(), None, "No `CommonToken`!");
812                return IdedExpr::default();
813            }
814            Some(op) => self.helper.next_id(op.as_ref()),
815        };
816        let entries = match &ctx.entries {
817            None => vec![],
818            Some(entries) => self.field_initializer_list(entries),
819        };
820        IdedExpr {
821            id: op_id,
822            expr: Expr::Struct(StructExpr {
823                type_name: message_name,
824                entries,
825            }),
826        }
827    }
828
829    fn visit_ConstantLiteral(&mut self, ctx: &ConstantLiteralContext<'_>) -> Self::Return {
830        <Self as ParseTreeVisitorCompat>::visit(
831            self,
832            ctx.literal().as_deref().expect("Has to have literal!"),
833        )
834    }
835
836    fn visit_Int(&mut self, ctx: &IntContext<'_>) -> Self::Return {
837        let string = ctx.get_text();
838        let token = ctx.tok.as_ref().expect("Has to have int!");
839        let val = match if let Some(string) = string.strip_prefix("0x") {
840            i64::from_str_radix(string, 16)
841        } else {
842            string.parse::<i64>()
843        } {
844            Ok(v) => v,
845            Err(e) => return self.report_error(token, Some(e), "invalid int literal"),
846        };
847        self.helper.next_expr(token, Expr::Literal(Val::Int(val)))
848    }
849
850    fn visit_Uint(&mut self, ctx: &UintContext<'_>) -> Self::Return {
851        let mut string = ctx.get_text();
852        string.truncate(string.len() - 1);
853        let token = ctx.tok.as_ref().expect("Has to have uint!");
854        let val = match if let Some(string) = string.strip_prefix("0x") {
855            u64::from_str_radix(string, 16)
856        } else {
857            string.parse::<u64>()
858        } {
859            Ok(v) => v,
860            Err(e) => return self.report_error(token, Some(e), "invalid uint literal"),
861        };
862        self.helper.next_expr(token, Expr::Literal(Val::UInt(val)))
863    }
864
865    fn visit_Double(&mut self, ctx: &DoubleContext<'_>) -> Self::Return {
866        let string = ctx.get_text();
867        let token = ctx.tok.as_ref().expect("Has to have double!");
868        match string.parse::<f64>() {
869            Ok(d) if d.is_finite() => self.helper.next_expr(token, Expr::Literal(Val::Double(d))),
870            Err(e) => self.report_error(token, Some(e), "invalid double literal"),
871            _ => self.report_error(token, None::<ParseError>, "invalid double literal"),
872        }
873    }
874
875    fn visit_String(&mut self, ctx: &StringContext<'_>) -> Self::Return {
876        let token = ctx.tok.as_deref().expect("Has to have string!");
877        match parse::parse_string(&ctx.get_text()) {
878            Ok(string) => self
879                .helper
880                .next_expr(token, Expr::Literal(Val::String(string))),
881            Err(e) => self.report_error::<ParseError, _>(
882                token,
883                None,
884                format!("invalid string literal: {e:?}"),
885            ),
886        }
887    }
888
889    fn visit_Bytes(&mut self, ctx: &BytesContext<'_>) -> Self::Return {
890        let token = ctx.tok.as_deref().expect("Has to have bytes!");
891        let string = ctx.get_text();
892        match parse::parse_bytes(&string[2..string.len() - 1]) {
893            Ok(bytes) => self
894                .helper
895                .next_expr(token, Expr::Literal(Val::Bytes(bytes))),
896            Err(e) => {
897                self.report_error::<ParseError, _>(
898                    token,
899                    None,
900                    format!("invalid bytes literal: {e:?}"),
901                );
902                IdedExpr::default()
903            }
904        }
905    }
906
907    fn visit_BoolTrue(&mut self, ctx: &BoolTrueContext<'_>) -> Self::Return {
908        self.helper.next_expr(
909            ctx.tok.as_deref().expect("Has to be `true`!"),
910            Expr::Literal(Val::Boolean(true)),
911        )
912    }
913
914    fn visit_BoolFalse(&mut self, ctx: &BoolFalseContext<'_>) -> Self::Return {
915        self.helper.next_expr(
916            ctx.tok.as_deref().expect("Has to be `false`!"),
917            Expr::Literal(Val::Boolean(false)),
918        )
919    }
920
921    fn visit_Null(&mut self, ctx: &NullContext<'_>) -> Self::Return {
922        self.helper.next_expr(
923            ctx.tok.as_deref().expect("Has to be `null`!"),
924            Expr::Literal(Val::Null),
925        )
926    }
927}
928
929pub struct ParserHelper {
930    source_info: SourceInfo,
931    next_id: u64,
932}
933
934impl Default for ParserHelper {
935    fn default() -> Self {
936        Self {
937            source_info: SourceInfo::default(),
938            next_id: 1,
939        }
940    }
941}
942
943impl ParserHelper {
944    fn next_id(&mut self, token: &CommonToken) -> u64 {
945        let id = self.next_id;
946        self.source_info
947            .add_offset(id, token.start as u32, token.stop as u32);
948        self.next_id += 1;
949        id
950    }
951
952    fn next_id_for_token(&mut self, token: Option<&CommonToken>) -> u64 {
953        match token {
954            None => 0,
955            Some(token) => self.next_id(token),
956        }
957    }
958
959    fn next_id_for(&mut self, id: u64) -> u64 {
960        let (start, stop) = self.source_info.offset_for(id).expect("invalid offset");
961        let id = self.next_id;
962        self.source_info.add_offset(id, start, stop);
963        self.next_id += 1;
964        id
965    }
966
967    pub fn next_expr(&mut self, token: &CommonToken, expr: Expr) -> IdedExpr {
968        IdedExpr {
969            id: self.next_id(token),
970            expr,
971        }
972    }
973
974    pub fn next_expr_for(&mut self, id: u64, expr: Expr) -> IdedExpr {
975        IdedExpr {
976            id: self.next_id_for(id),
977            expr,
978        }
979    }
980}
981
982struct LogicManager {
983    function: String,
984    terms: Vec<IdedExpr>,
985    ops: Vec<u64>,
986}
987
988impl LogicManager {
989    pub(crate) fn expr(mut self) -> IdedExpr {
990        if self.terms.len() == 1 {
991            self.terms.pop().expect("expected at least one term")
992        } else {
993            self.balanced_tree(0, self.ops.len() - 1)
994        }
995    }
996
997    pub(crate) fn add_term(&mut self, op_id: u64, expr: IdedExpr) {
998        self.terms.push(expr);
999        self.ops.push(op_id);
1000    }
1001
1002    fn balanced_tree(&mut self, lo: usize, hi: usize) -> IdedExpr {
1003        let mid = (lo + hi).div_ceil(2);
1004
1005        let left = if mid == lo {
1006            mem::take(&mut self.terms[mid])
1007        } else {
1008            self.balanced_tree(lo, mid - 1)
1009        };
1010
1011        let right = if mid == hi {
1012            mem::take(&mut self.terms[mid + 1])
1013        } else {
1014            self.balanced_tree(mid + 1, hi)
1015        };
1016
1017        IdedExpr {
1018            id: self.ops[mid],
1019            expr: Expr::Call(CallExpr {
1020                target: None,
1021                func_name: self.function.clone(),
1022                args: vec![left, right],
1023            }),
1024        }
1025    }
1026}
1027
1028#[cfg(test)]
1029mod tests {
1030    use super::*;
1031    use crate::ast::{ComprehensionExpr, Expr};
1032    use crate::reference::Val;
1033    use std::iter;
1034
1035    struct TestInfo {
1036        // I contains the input expression to be parsed.
1037        i: &'static str,
1038
1039        // P contains the type/id adorned debug output of the expression tree.
1040        p: &'static str,
1041
1042        // E contains the expected error output for a failed parse, or "" if the parse is expected to be successful.
1043        e: &'static str,
1044        // L contains the expected source adorned debug output of the expression tree.
1045        // l: String,
1046
1047        // M contains the expected adorned debug output of the macro calls map
1048        // m: String,
1049
1050        // Opts contains the list of options to be configured with the parser before parsing the expression.
1051        // Opts []Option
1052    }
1053    #[test]
1054    fn test() {
1055        let test_cases = [
1056            TestInfo {
1057                i: r#""A""#,
1058                p: r#""A"^#1:*expr.Constant_StringValue#"#,
1059                e: "",
1060            },
1061            TestInfo {
1062                i: r#"true"#,
1063                p: r#"true^#1:*expr.Constant_BoolValue#"#,
1064                e: "",
1065            },
1066            TestInfo {
1067                i: r#"false"#,
1068                p: r#"false^#1:*expr.Constant_BoolValue#"#,
1069                e: "",
1070            },
1071            TestInfo {
1072                i: "0",
1073                p: "0^#1:*expr.Constant_Int64Value#",
1074                e: "",
1075            },
1076            TestInfo {
1077                i: "42",
1078                p: "42^#1:*expr.Constant_Int64Value#",
1079                e: "",
1080            },
1081            TestInfo {
1082                i: "0xF",
1083                p: "15^#1:*expr.Constant_Int64Value#",
1084                e: "",
1085            },
1086            TestInfo {
1087                i: "0u",
1088                p: "0u^#1:*expr.Constant_Uint64Value#",
1089                e: "",
1090            },
1091            TestInfo {
1092                i: "23u",
1093                p: "23u^#1:*expr.Constant_Uint64Value#",
1094                e: "",
1095            },
1096            TestInfo {
1097                i: "24u",
1098                p: "24u^#1:*expr.Constant_Uint64Value#",
1099                e: "",
1100            },
1101            TestInfo {
1102                i: "0xFu",
1103                p: "15u^#1:*expr.Constant_Uint64Value#",
1104                e: "",
1105            },
1106            TestInfo {
1107                i: "-1",
1108                p: "-1^#1:*expr.Constant_Int64Value#",
1109                e: "",
1110            },
1111            TestInfo {
1112                i: "4--4",
1113                p: r#"_-_(
1114    4^#1:*expr.Constant_Int64Value#,
1115    -4^#3:*expr.Constant_Int64Value#
1116)^#2:*expr.Expr_CallExpr#"#,
1117                e: "",
1118            },
1119            TestInfo {
1120                i: "4--4.1",
1121                p: r#"_-_(
1122    4^#1:*expr.Constant_Int64Value#,
1123    -4.1^#3:*expr.Constant_DoubleValue#
1124)^#2:*expr.Expr_CallExpr#"#,
1125                e: "",
1126            },
1127            TestInfo {
1128                i: r#"b"abc""#,
1129                p: r#"b"abc"^#1:*expr.Constant_BytesValue#"#,
1130                e: "",
1131            },
1132            TestInfo {
1133                i: "23.39",
1134                p: "23.39^#1:*expr.Constant_DoubleValue#",
1135                e: "",
1136            },
1137            TestInfo {
1138                i: "!a",
1139                p: "!_(
1140    a^#2:*expr.Expr_IdentExpr#
1141)^#1:*expr.Expr_CallExpr#",
1142                e: "",
1143            },
1144            TestInfo {
1145                i: "null",
1146                p: "null^#1:*expr.Constant_NullValue#",
1147                e: "",
1148            },
1149            TestInfo {
1150                i: "a",
1151                p: "a^#1:*expr.Expr_IdentExpr#",
1152                e: "",
1153            },
1154            TestInfo {
1155                i: "a?b:c",
1156                p: "_?_:_(
1157    a^#1:*expr.Expr_IdentExpr#,
1158    b^#3:*expr.Expr_IdentExpr#,
1159    c^#4:*expr.Expr_IdentExpr#
1160)^#2:*expr.Expr_CallExpr#",
1161                e: "",
1162            },
1163            TestInfo {
1164                i: "a || b",
1165                p: "_||_(
1166    a^#1:*expr.Expr_IdentExpr#,
1167    b^#2:*expr.Expr_IdentExpr#
1168)^#3:*expr.Expr_CallExpr#",
1169                e: "",
1170            },
1171            TestInfo {
1172                i: "a || b || c || d || e || f ",
1173                p: "_||_(
1174    _||_(
1175        _||_(
1176            a^#1:*expr.Expr_IdentExpr#,
1177            b^#2:*expr.Expr_IdentExpr#
1178        )^#3:*expr.Expr_CallExpr#,
1179        c^#4:*expr.Expr_IdentExpr#
1180    )^#5:*expr.Expr_CallExpr#,
1181    _||_(
1182        _||_(
1183            d^#6:*expr.Expr_IdentExpr#,
1184            e^#8:*expr.Expr_IdentExpr#
1185        )^#9:*expr.Expr_CallExpr#,
1186        f^#10:*expr.Expr_IdentExpr#
1187    )^#11:*expr.Expr_CallExpr#
1188)^#7:*expr.Expr_CallExpr#",
1189                e: "",
1190            },
1191            TestInfo {
1192                i: "a && b",
1193                p: "_&&_(
1194    a^#1:*expr.Expr_IdentExpr#,
1195    b^#2:*expr.Expr_IdentExpr#
1196)^#3:*expr.Expr_CallExpr#",
1197                e: "",
1198            },
1199            TestInfo {
1200                i: "a && b && c && d && e && f && g",
1201                p: "_&&_(
1202    _&&_(
1203        _&&_(
1204            a^#1:*expr.Expr_IdentExpr#,
1205            b^#2:*expr.Expr_IdentExpr#
1206        )^#3:*expr.Expr_CallExpr#,
1207        _&&_(
1208            c^#4:*expr.Expr_IdentExpr#,
1209            d^#6:*expr.Expr_IdentExpr#
1210        )^#7:*expr.Expr_CallExpr#
1211    )^#5:*expr.Expr_CallExpr#,
1212    _&&_(
1213        _&&_(
1214            e^#8:*expr.Expr_IdentExpr#,
1215            f^#10:*expr.Expr_IdentExpr#
1216        )^#11:*expr.Expr_CallExpr#,
1217        g^#12:*expr.Expr_IdentExpr#
1218    )^#13:*expr.Expr_CallExpr#
1219)^#9:*expr.Expr_CallExpr#",
1220                e: "",
1221            },
1222            TestInfo {
1223                i: "a && b && c && d || e && f && g && h",
1224                p: "_||_(
1225    _&&_(
1226        _&&_(
1227            a^#1:*expr.Expr_IdentExpr#,
1228            b^#2:*expr.Expr_IdentExpr#
1229        )^#3:*expr.Expr_CallExpr#,
1230        _&&_(
1231            c^#4:*expr.Expr_IdentExpr#,
1232            d^#6:*expr.Expr_IdentExpr#
1233        )^#7:*expr.Expr_CallExpr#
1234    )^#5:*expr.Expr_CallExpr#,
1235    _&&_(
1236        _&&_(
1237            e^#8:*expr.Expr_IdentExpr#,
1238            f^#9:*expr.Expr_IdentExpr#
1239        )^#10:*expr.Expr_CallExpr#,
1240        _&&_(
1241            g^#11:*expr.Expr_IdentExpr#,
1242            h^#13:*expr.Expr_IdentExpr#
1243        )^#14:*expr.Expr_CallExpr#
1244    )^#12:*expr.Expr_CallExpr#
1245)^#15:*expr.Expr_CallExpr#",
1246                e: "",
1247            },
1248            TestInfo {
1249                i: "a + b",
1250                p: "_+_(
1251    a^#1:*expr.Expr_IdentExpr#,
1252    b^#3:*expr.Expr_IdentExpr#
1253)^#2:*expr.Expr_CallExpr#",
1254                e: "",
1255            },
1256            TestInfo {
1257                i: "a - b",
1258                p: "_-_(
1259    a^#1:*expr.Expr_IdentExpr#,
1260    b^#3:*expr.Expr_IdentExpr#
1261)^#2:*expr.Expr_CallExpr#",
1262                e: "",
1263            },
1264            TestInfo {
1265                i: "a * b",
1266                p: "_*_(
1267    a^#1:*expr.Expr_IdentExpr#,
1268    b^#3:*expr.Expr_IdentExpr#
1269)^#2:*expr.Expr_CallExpr#",
1270                e: "",
1271            },
1272            TestInfo {
1273                i: "a / b",
1274                p: "_/_(
1275    a^#1:*expr.Expr_IdentExpr#,
1276    b^#3:*expr.Expr_IdentExpr#
1277)^#2:*expr.Expr_CallExpr#",
1278                e: "",
1279            },
1280            TestInfo {
1281                i: "a % b",
1282                p: "_%_(
1283    a^#1:*expr.Expr_IdentExpr#,
1284    b^#3:*expr.Expr_IdentExpr#
1285)^#2:*expr.Expr_CallExpr#",
1286                e: "",
1287            },
1288            TestInfo {
1289                i: "a in b",
1290                p: "@in(
1291    a^#1:*expr.Expr_IdentExpr#,
1292    b^#3:*expr.Expr_IdentExpr#
1293)^#2:*expr.Expr_CallExpr#",
1294                e: "",
1295            },
1296            TestInfo {
1297                i: "a == b",
1298                p: "_==_(
1299    a^#1:*expr.Expr_IdentExpr#,
1300    b^#3:*expr.Expr_IdentExpr#
1301)^#2:*expr.Expr_CallExpr#",
1302                e: "",
1303            },
1304            TestInfo {
1305                i: "a != b",
1306                p: "_!=_(
1307    a^#1:*expr.Expr_IdentExpr#,
1308    b^#3:*expr.Expr_IdentExpr#
1309)^#2:*expr.Expr_CallExpr#",
1310                e: "",
1311            },
1312            TestInfo {
1313                i: "a > b",
1314                p: "_>_(
1315    a^#1:*expr.Expr_IdentExpr#,
1316    b^#3:*expr.Expr_IdentExpr#
1317)^#2:*expr.Expr_CallExpr#",
1318                e: "",
1319            },
1320            TestInfo {
1321                i: "a >= b",
1322                p: "_>=_(
1323    a^#1:*expr.Expr_IdentExpr#,
1324    b^#3:*expr.Expr_IdentExpr#
1325)^#2:*expr.Expr_CallExpr#",
1326                e: "",
1327            },
1328            TestInfo {
1329                i: "a < b",
1330                p: "_<_(
1331    a^#1:*expr.Expr_IdentExpr#,
1332    b^#3:*expr.Expr_IdentExpr#
1333)^#2:*expr.Expr_CallExpr#",
1334                e: "",
1335            },
1336            TestInfo {
1337                i: "a <= b",
1338                p: "_<=_(
1339    a^#1:*expr.Expr_IdentExpr#,
1340    b^#3:*expr.Expr_IdentExpr#
1341)^#2:*expr.Expr_CallExpr#",
1342                e: "",
1343            },
1344            TestInfo {
1345                i: "a.b",
1346                p: "a^#1:*expr.Expr_IdentExpr#.b^#2:*expr.Expr_SelectExpr#",
1347                e: "",
1348            },
1349            TestInfo {
1350                i: "a.b.c",
1351                p: "a^#1:*expr.Expr_IdentExpr#.b^#2:*expr.Expr_SelectExpr#.c^#3:*expr.Expr_SelectExpr#",
1352                e: "",
1353            },
1354            TestInfo {
1355                i: "a[b]",
1356                p: "_[_](
1357    a^#1:*expr.Expr_IdentExpr#,
1358    b^#3:*expr.Expr_IdentExpr#
1359)^#2:*expr.Expr_CallExpr#",
1360                e: "",
1361            },
1362            TestInfo {
1363                i: "(a)",
1364                p: "a^#1:*expr.Expr_IdentExpr#",
1365                e: "",
1366            },
1367            TestInfo {
1368                i: "((a))",
1369                p: "a^#1:*expr.Expr_IdentExpr#",
1370                e: "",
1371            },
1372            TestInfo {
1373                i: "a()",
1374                p: "a()^#1:*expr.Expr_CallExpr#",
1375                e: "",
1376            },
1377            TestInfo {
1378                i: "a(b)",
1379                p: "a(
1380    b^#2:*expr.Expr_IdentExpr#
1381)^#1:*expr.Expr_CallExpr#",
1382                e: "",
1383            },
1384            TestInfo {
1385                i: "a(b, c)",
1386                p: "a(
1387    b^#2:*expr.Expr_IdentExpr#,
1388    c^#3:*expr.Expr_IdentExpr#
1389)^#1:*expr.Expr_CallExpr#",
1390                e: "",
1391            },
1392            TestInfo {
1393                i: "a.b()",
1394                p: "a^#1:*expr.Expr_IdentExpr#.b()^#2:*expr.Expr_CallExpr#",
1395                e: "",
1396            },
1397            TestInfo {
1398                i: "a.b(c)",
1399                p: "a^#1:*expr.Expr_IdentExpr#.b(
1400    c^#3:*expr.Expr_IdentExpr#
1401)^#2:*expr.Expr_CallExpr#",
1402                e: "",
1403            },
1404            TestInfo {
1405                i: "foo{ }",
1406                p: "foo{}^#1:*expr.Expr_StructExpr#",
1407                e: "",
1408            },
1409            TestInfo {
1410                i: "foo{ a:b }",
1411                p: "foo{
1412    a:b^#3:*expr.Expr_IdentExpr#^#2:*expr.Expr_CreateStruct_Entry#
1413}^#1:*expr.Expr_StructExpr#",
1414                e: "",
1415            },
1416            TestInfo {
1417                i: "foo{ a:b, c:d }",
1418                p: "foo{
1419    a:b^#3:*expr.Expr_IdentExpr#^#2:*expr.Expr_CreateStruct_Entry#,
1420    c:d^#5:*expr.Expr_IdentExpr#^#4:*expr.Expr_CreateStruct_Entry#
1421}^#1:*expr.Expr_StructExpr#",
1422                e: "",
1423            },
1424            TestInfo {
1425                i: "{}",
1426                p: "{}^#1:*expr.Expr_StructExpr#",
1427                e: "",
1428            },
1429            TestInfo {
1430                i: "{a: b, c: d}",
1431                p: "{
1432    a^#3:*expr.Expr_IdentExpr#:b^#4:*expr.Expr_IdentExpr#^#2:*expr.Expr_CreateStruct_Entry#,
1433    c^#6:*expr.Expr_IdentExpr#:d^#7:*expr.Expr_IdentExpr#^#5:*expr.Expr_CreateStruct_Entry#
1434}^#1:*expr.Expr_StructExpr#",
1435                e: "",
1436            },
1437            TestInfo {
1438                i: "[]",
1439                p: "[]^#1:*expr.Expr_ListExpr#",
1440                e: "",
1441            },
1442            TestInfo {
1443                i: "[a]",
1444                p: "[
1445    a^#2:*expr.Expr_IdentExpr#
1446]^#1:*expr.Expr_ListExpr#",
1447                e: "",
1448            },
1449            TestInfo {
1450                i: "[a, b, c]",
1451                p: "[
1452    a^#2:*expr.Expr_IdentExpr#,
1453    b^#3:*expr.Expr_IdentExpr#,
1454    c^#4:*expr.Expr_IdentExpr#
1455]^#1:*expr.Expr_ListExpr#",
1456                e: "",
1457            },
1458            TestInfo {
1459                i: "has(m.f)",
1460                p: "m^#2:*expr.Expr_IdentExpr#.f~test-only~^#4:*expr.Expr_SelectExpr#",
1461                e: "",
1462            },
1463            TestInfo {
1464                i: "m.exists(v, f)",
1465                p: "__comprehension__(
1466// Variable
1467v,
1468// Target
1469m^#1:*expr.Expr_IdentExpr#,
1470// Accumulator
1471@result,
1472// Init
1473false^#5:*expr.Constant_BoolValue#,
1474// LoopCondition
1475@not_strictly_false(
1476    !_(
1477        @result^#6:*expr.Expr_IdentExpr#
1478    )^#7:*expr.Expr_CallExpr#
1479)^#8:*expr.Expr_CallExpr#,
1480// LoopStep
1481_||_(
1482    @result^#9:*expr.Expr_IdentExpr#,
1483    f^#4:*expr.Expr_IdentExpr#
1484)^#10:*expr.Expr_CallExpr#,
1485// Result
1486@result^#11:*expr.Expr_IdentExpr#)^#12:*expr.Expr_ComprehensionExpr#",
1487                e: "",
1488            },
1489            TestInfo {
1490                i: "m.all(v, f)",
1491                p: "__comprehension__(
1492// Variable
1493v,
1494// Target
1495m^#1:*expr.Expr_IdentExpr#,
1496// Accumulator
1497@result,
1498// Init
1499true^#5:*expr.Constant_BoolValue#,
1500// LoopCondition
1501@not_strictly_false(
1502    @result^#6:*expr.Expr_IdentExpr#
1503)^#7:*expr.Expr_CallExpr#,
1504// LoopStep
1505_&&_(
1506    @result^#8:*expr.Expr_IdentExpr#,
1507    f^#4:*expr.Expr_IdentExpr#
1508)^#9:*expr.Expr_CallExpr#,
1509// Result
1510@result^#10:*expr.Expr_IdentExpr#)^#11:*expr.Expr_ComprehensionExpr#",
1511                e: "",
1512            },
1513            TestInfo {
1514                i: "m.existsOne(v, f)",
1515                p: "__comprehension__(
1516// Variable
1517v,
1518// Target
1519m^#1:*expr.Expr_IdentExpr#,
1520// Accumulator
1521@result,
1522// Init
15230^#5:*expr.Constant_Int64Value#,
1524// LoopCondition
1525true^#6:*expr.Constant_BoolValue#,
1526// LoopStep
1527_?_:_(
1528    f^#4:*expr.Expr_IdentExpr#,
1529    _+_(
1530        @result^#7:*expr.Expr_IdentExpr#,
1531        1^#8:*expr.Constant_Int64Value#
1532    )^#9:*expr.Expr_CallExpr#,
1533    @result^#10:*expr.Expr_IdentExpr#
1534)^#11:*expr.Expr_CallExpr#,
1535// Result
1536_==_(
1537    @result^#12:*expr.Expr_IdentExpr#,
1538    1^#13:*expr.Constant_Int64Value#
1539)^#14:*expr.Expr_CallExpr#)^#15:*expr.Expr_ComprehensionExpr#",
1540                e: "",
1541            },
1542            TestInfo {
1543                i: "m.map(v, f)",
1544                p: "__comprehension__(
1545// Variable
1546v,
1547// Target
1548m^#1:*expr.Expr_IdentExpr#,
1549// Accumulator
1550@result,
1551// Init
1552[]^#5:*expr.Expr_ListExpr#,
1553// LoopCondition
1554true^#6:*expr.Constant_BoolValue#,
1555// LoopStep
1556_+_(
1557    @result^#7:*expr.Expr_IdentExpr#,
1558    [
1559        f^#4:*expr.Expr_IdentExpr#
1560    ]^#8:*expr.Expr_ListExpr#
1561)^#9:*expr.Expr_CallExpr#,
1562// Result
1563@result^#10:*expr.Expr_IdentExpr#)^#11:*expr.Expr_ComprehensionExpr#",
1564                e: "",
1565            },
1566            TestInfo {
1567                i: "m.map(v, p, f)",
1568                p: "__comprehension__(
1569// Variable
1570v,
1571// Target
1572m^#1:*expr.Expr_IdentExpr#,
1573// Accumulator
1574@result,
1575// Init
1576[]^#6:*expr.Expr_ListExpr#,
1577// LoopCondition
1578true^#7:*expr.Constant_BoolValue#,
1579// LoopStep
1580_?_:_(
1581    p^#4:*expr.Expr_IdentExpr#,
1582    _+_(
1583        @result^#8:*expr.Expr_IdentExpr#,
1584        [
1585            f^#5:*expr.Expr_IdentExpr#
1586        ]^#9:*expr.Expr_ListExpr#
1587    )^#10:*expr.Expr_CallExpr#,
1588    @result^#11:*expr.Expr_IdentExpr#
1589)^#12:*expr.Expr_CallExpr#,
1590// Result
1591@result^#13:*expr.Expr_IdentExpr#)^#14:*expr.Expr_ComprehensionExpr#",
1592                e: "",
1593            },
1594            TestInfo {
1595                i: "m.filter(v, p)",
1596                p: "__comprehension__(
1597// Variable
1598v,
1599// Target
1600m^#1:*expr.Expr_IdentExpr#,
1601// Accumulator
1602@result,
1603// Init
1604[]^#5:*expr.Expr_ListExpr#,
1605// LoopCondition
1606true^#6:*expr.Constant_BoolValue#,
1607// LoopStep
1608_?_:_(
1609    p^#4:*expr.Expr_IdentExpr#,
1610    _+_(
1611        @result^#7:*expr.Expr_IdentExpr#,
1612        [
1613            v^#3:*expr.Expr_IdentExpr#
1614        ]^#8:*expr.Expr_ListExpr#
1615    )^#9:*expr.Expr_CallExpr#,
1616    @result^#10:*expr.Expr_IdentExpr#
1617)^#11:*expr.Expr_CallExpr#,
1618// Result
1619@result^#12:*expr.Expr_IdentExpr#)^#13:*expr.Expr_ComprehensionExpr#",
1620                e: "",
1621            },
1622            // Parse error tests
1623            TestInfo {
1624                i: "0xFFFFFFFFFFFFFFFFF",
1625                p: "",
1626                e: "ERROR: <input>:1:1: invalid int literal
1627| 0xFFFFFFFFFFFFFFFFF
1628| ^",
1629            },
1630            TestInfo {
1631                i: "0xFFFFFFFFFFFFFFFFFu",
1632                p: "",
1633                e: "ERROR: <input>:1:1: invalid uint literal
1634| 0xFFFFFFFFFFFFFFFFFu
1635| ^",
1636            },
1637            TestInfo {
1638                i: "1.99e90000009",
1639                p: "",
1640                e: "ERROR: <input>:1:1: invalid double literal
1641| 1.99e90000009
1642| ^",
1643            },
1644            TestInfo {
1645                i: "{",
1646                p: "",
1647                e: "ERROR: <input>:1:2: Syntax error: mismatched input '<EOF>' expecting {'[', '{', '}', '(', '.', ',', '-', '!', '?', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER}
1648| {
1649| .^",
1650            },
1651            TestInfo {
1652                i: "*@a | b",
1653                p: "",
1654                e: "ERROR: <input>:1:1: Syntax error: extraneous input '*' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER}
1655| *@a | b
1656| ^
1657ERROR: <input>:1:2: Syntax error: token recognition error at: '@'
1658| *@a | b
1659| .^
1660ERROR: <input>:1:5: Syntax error: token recognition error at: '| '
1661| *@a | b
1662| ....^
1663ERROR: <input>:1:7: Syntax error: extraneous input 'b' expecting <EOF>
1664| *@a | b
1665| ......^", 
1666            },
1667            TestInfo {
1668                i: "a | b",
1669                p: "",
1670                e: "ERROR: <input>:1:3: Syntax error: token recognition error at: '| '
1671| a | b
1672| ..^
1673ERROR: <input>:1:5: Syntax error: extraneous input 'b' expecting <EOF>
1674| a | b
1675| ....^",
1676            },
1677            TestInfo {
1678                i: "a.?b && a[?b]",
1679                p: "",
1680                e: "ERROR: <input>:1:2: unsupported syntax '.?'
1681| a.?b && a[?b]
1682| .^
1683ERROR: <input>:1:10: unsupported syntax '[?'
1684| a.?b && a[?b]
1685| .........^",
1686            },
1687            TestInfo {
1688                i: "a.?b && a[?b]",
1689                p: "",
1690                e: "ERROR: <input>:1:2: unsupported syntax '.?'
1691| a.?b && a[?b]
1692| .^
1693ERROR: <input>:1:10: unsupported syntax '[?'
1694| a.?b && a[?b]
1695| .........^",
1696            },
1697            TestInfo {
1698                i: "Msg{?field: value} && {?'key': value}",
1699                p: "",
1700                e: "ERROR: <input>:1:5: unsupported syntax '?'
1701| Msg{?field: value} && {?'key': value}
1702| ....^
1703ERROR: <input>:1:24: unsupported syntax '?'
1704| Msg{?field: value} && {?'key': value}
1705| .......................^",
1706            },
1707            TestInfo 	{
1708                i: "has(m)",
1709                p: "",
1710                e: "ERROR: <input>:1:5: invalid argument to has() macro
1711| has(m)
1712| ....^"
1713            },
1714            TestInfo {
1715                i: "1.all(2, 3)",
1716                p: "",
1717                e: "ERROR: <input>:1:7: argument must be a simple name
1718| 1.all(2, 3)
1719| ......^",
1720            },
1721        ];
1722
1723        for test_case in test_cases {
1724            let parser = Parser::new();
1725            let result = parser.parse(test_case.i);
1726            if !test_case.p.is_empty() {
1727                assert_eq!(
1728                    to_go_like_string(result.as_ref().expect("Expected an AST")),
1729                    test_case.p,
1730                    "Expr `{}` failed",
1731                    test_case.i
1732                );
1733            }
1734
1735            if !test_case.e.is_empty() {
1736                assert_eq!(
1737                    format!("{}", result.as_ref().expect_err("Expected an Err!")),
1738                    test_case.e,
1739                    "Error on `{}` failed",
1740                    test_case.i
1741                )
1742            }
1743        }
1744    }
1745
1746    fn to_go_like_string(expr: &IdedExpr) -> String {
1747        let mut writer = DebugWriter::default();
1748        writer.buffer(expr);
1749        writer.done()
1750    }
1751
1752    struct DebugWriter {
1753        buffer: String,
1754        indents: usize,
1755        line_start: bool,
1756    }
1757
1758    impl Default for DebugWriter {
1759        fn default() -> Self {
1760            Self {
1761                buffer: String::default(),
1762                indents: 0,
1763                line_start: true,
1764            }
1765        }
1766    }
1767
1768    impl DebugWriter {
1769        fn buffer(&mut self, expr: &IdedExpr) -> &Self {
1770            let e = match &expr.expr {
1771                Expr::Unspecified => "UNSPECIFIED!",
1772                Expr::Call(call) => {
1773                    if let Some(target) = &call.target {
1774                        self.buffer(target);
1775                        self.push(".");
1776                    }
1777                    self.push(call.func_name.as_str());
1778                    self.push("(");
1779                    if !call.args.is_empty() {
1780                        self.inc_indent();
1781                        self.newline();
1782                        for i in 0..call.args.len() {
1783                            if i > 0 {
1784                                self.push(",");
1785                                self.newline();
1786                            }
1787                            self.buffer(&call.args[i]);
1788                        }
1789                        self.dec_indent();
1790                        self.newline();
1791                    }
1792                    self.push(")");
1793                    &format!("^#{}:{}#", expr.id, "*expr.Expr_CallExpr")
1794                }
1795                Expr::Comprehension(comprehension) => {
1796                    self.push("__comprehension__(\n");
1797                    self.push_comprehension(comprehension);
1798                    &format!(")^#{}:{}#", expr.id, "*expr.Expr_ComprehensionExpr")
1799                }
1800                Expr::Ident(id) => &format!("{}^#{}:{}#", id, expr.id, "*expr.Expr_IdentExpr"),
1801                Expr::List(list) => {
1802                    self.push("[");
1803                    if !list.elements.is_empty() {
1804                        self.inc_indent();
1805                        self.newline();
1806                        for (i, element) in list.elements.iter().enumerate() {
1807                            if i > 0 {
1808                                self.push(",");
1809                                self.newline();
1810                            }
1811                            self.buffer(element);
1812                        }
1813                        self.dec_indent();
1814                        self.newline();
1815                    }
1816                    self.push("]");
1817                    &format!("^#{}:{}#", expr.id, "*expr.Expr_ListExpr")
1818                }
1819                Expr::Literal(val) => match val {
1820                    Val::String(s) => {
1821                        &format!("\"{s}\"^#{}:{}#", expr.id, "*expr.Constant_StringValue")
1822                    }
1823                    Val::Boolean(b) => &format!("{b}^#{}:{}#", expr.id, "*expr.Constant_BoolValue"),
1824                    Val::Int(i) => &format!("{i}^#{}:{}#", expr.id, "*expr.Constant_Int64Value"),
1825                    Val::UInt(u) => &format!("{u}u^#{}:{}#", expr.id, "*expr.Constant_Uint64Value"),
1826                    Val::Double(f) => {
1827                        &format!("{f}^#{}:{}#", expr.id, "*expr.Constant_DoubleValue")
1828                    }
1829                    Val::Bytes(bytes) => &format!(
1830                        "b\"{}\"^#{}:{}#",
1831                        String::from_utf8_lossy(bytes),
1832                        expr.id,
1833                        "*expr.Constant_BytesValue"
1834                    ),
1835                    Val::Null => &format!("null^#{}:{}#", expr.id, "*expr.Constant_NullValue"),
1836                },
1837                Expr::Map(map) => {
1838                    self.push("{");
1839                    self.inc_indent();
1840                    if !map.entries.is_empty() {
1841                        self.newline();
1842                    }
1843                    for (i, entry) in map.entries.iter().enumerate() {
1844                        match &entry.expr {
1845                            EntryExpr::StructField(_) => panic!("WAT?!"),
1846                            EntryExpr::MapEntry(e) => {
1847                                self.buffer(&e.key);
1848                                self.push(":");
1849                                self.buffer(&e.value);
1850                                self.push(&format!(
1851                                    "^#{}:{}#",
1852                                    entry.id, "*expr.Expr_CreateStruct_Entry"
1853                                ));
1854                            }
1855                        }
1856                        if i < map.entries.len() - 1 {
1857                            self.push(",");
1858                        }
1859                        self.newline();
1860                    }
1861                    self.dec_indent();
1862                    self.push("}");
1863                    &format!("^#{}:{}#", expr.id, "*expr.Expr_StructExpr")
1864                }
1865                Expr::Select(select) => {
1866                    self.buffer(select.operand.deref());
1867                    let suffix = if select.test { "~test-only~" } else { "" };
1868                    &format!(
1869                        ".{}{}^#{}:{}#",
1870                        select.field, suffix, expr.id, "*expr.Expr_SelectExpr"
1871                    )
1872                }
1873                Expr::Struct(s) => {
1874                    self.push(&s.type_name);
1875                    self.push("{");
1876                    self.inc_indent();
1877                    if !s.entries.is_empty() {
1878                        self.newline();
1879                    }
1880                    for (i, entry) in s.entries.iter().enumerate() {
1881                        match &entry.expr {
1882                            EntryExpr::StructField(field) => {
1883                                self.push(&field.field);
1884                                self.push(":");
1885                                self.buffer(&field.value);
1886                                self.push(&format!(
1887                                    "^#{}:{}#",
1888                                    entry.id, "*expr.Expr_CreateStruct_Entry"
1889                                ));
1890                            }
1891                            EntryExpr::MapEntry(_) => panic!("WAT?!"),
1892                        }
1893                        if i < s.entries.len() - 1 {
1894                            self.push(",");
1895                        }
1896                        self.newline();
1897                    }
1898                    self.dec_indent();
1899                    self.push("}");
1900                    &format!("^#{}:{}#", expr.id, "*expr.Expr_StructExpr")
1901                }
1902            };
1903            self.push(e);
1904            self
1905        }
1906
1907        fn push(&mut self, literal: &str) {
1908            self.indent();
1909            self.buffer.push_str(literal);
1910        }
1911
1912        fn indent(&mut self) {
1913            if self.line_start {
1914                self.line_start = false;
1915                self.buffer.push_str(
1916                    iter::repeat_n("    ", self.indents)
1917                        .collect::<String>()
1918                        .as_str(),
1919                )
1920            }
1921        }
1922
1923        fn newline(&mut self) {
1924            self.buffer.push('\n');
1925            self.line_start = true;
1926        }
1927
1928        fn inc_indent(&mut self) {
1929            self.indents += 1;
1930        }
1931
1932        fn dec_indent(&mut self) {
1933            self.indents -= 1;
1934        }
1935
1936        fn done(self) -> String {
1937            self.buffer
1938        }
1939
1940        fn push_comprehension(&mut self, comprehension: &ComprehensionExpr) {
1941            self.push("// Variable\n");
1942            self.push(comprehension.iter_var.as_str());
1943            self.push(",\n");
1944            self.push("// Target\n");
1945            self.buffer(comprehension.iter_range.as_ref());
1946            self.push(",\n");
1947            self.push("// Accumulator\n");
1948            self.push(comprehension.accu_var.as_str());
1949            self.push(",\n");
1950            self.push("// Init\n");
1951            self.buffer(comprehension.accu_init.as_ref());
1952            self.push(",\n");
1953            self.push("// LoopCondition\n");
1954            self.buffer(comprehension.loop_cond.as_ref());
1955            self.push(",\n");
1956            self.push("// LoopStep\n");
1957            self.buffer(comprehension.loop_step.as_ref());
1958            self.push(",\n");
1959            self.push("// Result\n");
1960            self.buffer(comprehension.result.as_ref());
1961        }
1962    }
1963}