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