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