Skip to main content

bel/parser/
parser.rs

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