Skip to main content

bel/parser/
parser.rs

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