Skip to main content

cel/parser/
parser.rs

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