dsntk_feel_parser/
ast.rs

1//! Implementation of a node in Abstract Syntax Tree for `FEEL` grammar.
2
3use antex::{leaf, node, Color, ColorMode, StyledText, TreeNode};
4use dsntk_feel::{FeelType, Name};
5use std::fmt;
6use std::fmt::{Display, Write};
7
8/// Default color of the tree arms.
9const DEFAULT_COLOR: Color = Color::White;
10
11/// Node of the Abstract Syntax Tree for `FEEL` grammar.
12#[derive(Debug, Clone, PartialEq)]
13pub enum AstNode {
14  /// Node representing an arithmetic operator `+` (addition).
15  Add(Box<AstNode>, Box<AstNode>),
16
17  /// Node representing a logical operator `and` (conjunction).
18  And(Box<AstNode>, Box<AstNode>),
19
20  /// Node representing `@` (at) literal.
21  At(String),
22
23  /// Node representing a comparison operator `between`.
24  Between(Box<AstNode>, Box<AstNode>, Box<AstNode>),
25
26  /// Node representing a value of type `boolean`.
27  Boolean(bool),
28
29  /// Node representing a comma separated list of AST nodes, used internally by parser.
30  CommaList(Vec<AstNode>),
31
32  /// Node representing a context.
33  /// Context entries are stored in the order of appearance in definition.
34  Context(Vec<AstNode>),
35
36  /// Node representing single context entry; key-value pair.
37  ContextEntry(Box<AstNode>, Box<AstNode>),
38
39  /// Node representing the key of the context entry; the key in context entry
40  /// may be a name or string literal. String literals are converted to one segment names
41  /// containing exactly the value of the string.
42  ContextEntryKey(Name),
43
44  /// Node representing the type of the context. Context type is defined by names
45  /// and types of all entries. This node contains a collection of types
46  /// for all context entries in the order of appearance in context type definition.
47  ContextType(Vec<AstNode>),
48
49  /// Node representing single context type entry.
50  ContextTypeEntry(
51    /// Node representing entry name of the context key.
52    Box<AstNode>,
53    /// Node representing `FEEL` type of the context entry.
54    Box<AstNode>,
55  ),
56
57  /// Node representing the key of the entry in context type definition.
58  /// In context type definition, only `FEEL` name is allowed as an entry key.
59  ContextTypeEntryKey(Name),
60
61  /// Node representing arithmetic operator `/` (division).
62  Div(Box<AstNode>, Box<AstNode>),
63
64  /// Node representing `equal` comparison.
65  Eq(Box<AstNode>, Box<AstNode>),
66
67  /// Node representing an expression evaluated as a body of `for` expression.
68  EvaluatedExpression(Box<AstNode>),
69
70  /// Quantified expression `every`.
71  Every(
72    /// Node representing quantified contexts.
73    Box<AstNode>,
74    /// Node representing an expression after `satisfies` clause.
75    Box<AstNode>,
76  ),
77
78  /// Node representing exponential function.
79  Exp(Box<AstNode>, Box<AstNode>),
80
81  /// Node representing a list of expressions.
82  ExpressionList(Vec<AstNode>),
83
84  /// Node representing `FEEL` type.
85  FeelType(FeelType),
86
87  /// Node representing filter expression.
88  Filter(Box<AstNode>, Box<AstNode>),
89
90  /// Node representing `for` expression.
91  For(
92    /// Node representing [iteration contexts](AstNode::IterationContexts).
93    Box<AstNode>,
94    /// Node representing an expression to be evaluated.
95    Box<AstNode>,
96  ),
97
98  /// Node representing function's formal parameter.
99  FormalParameter(
100    /// Node representing the name of the parameter.
101    Box<AstNode>,
102    /// Node representing the `FEEL` type of the parameter.
103    Box<AstNode>,
104  ),
105
106  /// Node representing a list of formal parameters.
107  FormalParameters(Vec<AstNode>),
108
109  /// Node representing function's body. This node holds mandatory function body
110  /// and a flag indicating if the function is external.
111  FunctionBody(Box<AstNode>, bool),
112
113  /// Node representing function definition.
114  /// This node holds function's formal parameter list and  function's body.
115  FunctionDefinition(Box<AstNode>, Box<AstNode>),
116
117  /// Node representing function invocation.
118  FunctionInvocation(Box<AstNode>, Box<AstNode>),
119
120  /// Node representing function type.
121  FunctionType(
122    /// Node representing function's parameter types as [AstNode::ParameterTypes].
123    Box<AstNode>,
124    /// Node representing function's result type.
125    Box<AstNode>,
126  ),
127
128  /// Node representing `greater or equal` comparison.
129  Ge(Box<AstNode>, Box<AstNode>),
130
131  /// Node representing `greater than` comparison.
132  Gt(Box<AstNode>, Box<AstNode>),
133
134  /// Node representing `if` expression.
135  If(
136    /// Node representing the condition.
137    Box<AstNode>,
138    /// Node representing the expression to be evaluated when condition is `true`.
139    Box<AstNode>,
140    /// Node representing the expression to be evaluated when condition is `false`.
141    Box<AstNode>,
142  ),
143
144  /// Node representing `in` operator.
145  In(Box<AstNode>, Box<AstNode>),
146
147  /// Node representing type checking function.
148  InstanceOf(
149    /// Node representing the tested value.
150    Box<AstNode>,
151    /// Node representing `FELL` type to be checked.
152    Box<AstNode>,
153  ),
154
155  /// Node representing the interval end used in ranges.
156  IntervalEnd(Box<AstNode>, bool),
157
158  /// Node representing the interval start used in ranges.
159  IntervalStart(Box<AstNode>, bool),
160
161  /// Node representing the comparison operator `irrelevant`.
162  Irrelevant,
163
164  /// List of iteration contexts.
165  IterationContexts(Vec<AstNode>),
166
167  /// Node representing iteration context containing a single value to iterate over.
168  IterationContextSingle(
169    /// Node representing variable name used in this iteration context.
170    Box<AstNode>,
171    /// Node representing a single value to iterate over.
172    Box<AstNode>,
173  ),
174
175  /// Node representing iteration context containing the variable name
176  /// and a staring and ending value of the interval to iterate over.
177  IterationContextInterval(
178    /// Node representing variable name used in this iteration context.
179    Box<AstNode>,
180    /// Node representing the `start` value of the interval to iterate over.
181    Box<AstNode>,
182    /// Node representing the `end` value of the interval to iterate over.
183    Box<AstNode>,
184  ),
185
186  /// Node representing `less or equal` comparison.
187  Le(Box<AstNode>, Box<AstNode>),
188
189  /// Node representing `less than` comparison.
190  Lt(Box<AstNode>, Box<AstNode>),
191
192  /// Node representing a list.
193  List(Vec<AstNode>),
194
195  /// Node representing a list type.
196  ListType(Box<AstNode>),
197
198  /// Node representing arithmetic operator `*` (multiplication).
199  Mul(Box<AstNode>, Box<AstNode>),
200
201  /// Node representing a `FEEL` name.
202  Name(Name),
203
204  /// Node representing single named parameter.
205  NamedParameter(
206    /// Node representing parameter name.
207    Box<AstNode>,
208    /// Node representing parameter type.
209    Box<AstNode>,
210  ),
211
212  /// Node representing a collection of named parameters.
213  NamedParameters(Vec<AstNode>),
214
215  /// Node representing a negated list (used in negated unary tests).
216  NegatedList(Vec<AstNode>),
217
218  /// Node representing the unary arithmetic negation `-`.
219  Neg(Box<AstNode>),
220
221  /// Node representing `not equal` comparison.
222  Nq(Box<AstNode>, Box<AstNode>),
223
224  /// Node representing a value of type `Null`.
225  Null,
226
227  /// Node representing a value of type `number`.
228  Numeric(
229    /// Digits before decimal separator.
230    String,
231    /// Digits after decimal separator.
232    String,
233    /// Sign of the exponent.
234    char,
235    /// Digits of the exponent.
236    String,
237  ),
238
239  /// Node representing a logical operator `or` (disjunction).
240  Or(Box<AstNode>, Box<AstNode>),
241
242  /// Node representing expression for selecting decision table's output value.
243  Out(Box<AstNode>, Box<AstNode>),
244
245  /// Node representing a name of the function's formal parameter.
246  ParameterName(Name),
247
248  /// Node representing a collection of function parameter types.
249  ParameterTypes(Vec<AstNode>),
250
251  /// Node representing a path expression.
252  Path(Box<AstNode>, Box<AstNode>),
253
254  /// Node representing a collection of positional parameters.
255  PositionalParameters(Vec<AstNode>),
256
257  /// Node representing a collection of names that constitute a qualified name.
258  QualifiedName(Vec<AstNode>),
259
260  /// Node representing a segment of a qualified name.
261  QualifiedNameSegment(Name),
262
263  /// List of quantified contexts.
264  QuantifiedContexts(Vec<AstNode>),
265
266  /// Quantified context containing variable name and evaluation expression.
267  QuantifiedContext(
268    /// Node representing variable name used in this quantified context.
269    Box<AstNode>,
270    /// Node representing evaluation expression.
271    Box<AstNode>,
272  ),
273
274  /// Node representing a range of values.
275  Range(Box<AstNode>, Box<AstNode>),
276
277  /// Node representing range type.
278  RangeType(Box<AstNode>),
279
280  /// Node representing `satisfies` clause in quantified expression.
281  Satisfies(Box<AstNode>),
282
283  /// Node representing quantified expression `some`.
284  Some(
285    /// Node representing quantified contexts.
286    Box<AstNode>,
287    /// Node representing an expression after `satisfies` clause.
288    Box<AstNode>,
289  ),
290
291  /// Node representing a value of type `string`.
292  String(String),
293
294  /// Node representing an arithmetic operator `-` (subtraction).
295  Sub(Box<AstNode>, Box<AstNode>),
296
297  /// Node representing unary comparison operator `>=`.
298  UnaryGe(Box<AstNode>),
299
300  /// Node representing unary comparison operator `>`.
301  UnaryGt(Box<AstNode>),
302
303  /// Node representing unary comparison operator `<=>`.
304  UnaryLe(Box<AstNode>),
305
306  /// Node representing unary comparison operator `<less than>`.
307  UnaryLt(Box<AstNode>),
308
309  /// Node representing unary comparison operator `=`.
310  UnaryEq(Box<AstNode>),
311
312  /// Node representing unary comparison operator `!=`.
313  UnaryNe(Box<AstNode>),
314}
315
316impl Display for AstNode {
317  /// Converts [AstNode] to its textual representation.
318  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
319    write!(f, "{}", self.tree(0, ColorMode::Off))
320  }
321}
322
323impl AstNode {
324  /// Converts [AstNode] to its textual representation with indentation and color mode.
325  pub fn tree(&self, indent: usize, cm: ColorMode) -> String {
326    let root = ast_node_to_tree(self, cm);
327    let mut output = String::new();
328    let _ = root.write_indent(&mut output, indent);
329    output
330  }
331
332  /// Returns AST as text for testing purposes.
333  pub fn trace(&self) -> String {
334    let root = ast_node_to_tree(self, ColorMode::Off);
335    let mut output = "\n".to_string();
336    let _ = root.write_indent(&mut output, 6);
337    let _ = write!(output, "    ");
338    output
339  }
340}
341
342/// Converts [AstNode] into ASCII [TreeNode] node.
343fn ast_node_to_tree(node: &AstNode, cm: ColorMode) -> TreeNode {
344  match node {
345    AstNode::Add(lhs, rhs) => ast_node_2("Add", lhs, rhs, cm),
346    AstNode::And(lhs, rhs) => ast_node_2("And", lhs, rhs, cm),
347    AstNode::At(mid) => ast_node_and_leaf("At", &format!("`{mid}`"), cm),
348    AstNode::Between(lhs, mid, rhs) => ast_node_3("Between", lhs, mid, rhs, cm),
349    AstNode::Boolean(mid) => ast_node_and_leaf("Boolean", &format!("`{mid}`"), cm),
350    AstNode::CommaList(mid) => ast_node_n("CommaList", mid, cm),
351    AstNode::Context(items) => ast_node_n("Context", items, cm),
352    AstNode::ContextEntry(lhs, rhs) => ast_node_2("ContextEntry", lhs, rhs, cm),
353    AstNode::ContextEntryKey(mid) => ast_node_and_leaf("ContextEntryKey", &format!("`{mid}`"), cm),
354    AstNode::ContextType(items) => ast_node_n("ContextType", items, cm),
355    AstNode::ContextTypeEntry(lhs, rhs) => ast_node_2("ContextTypeEntry", lhs, rhs, cm),
356    AstNode::ContextTypeEntryKey(mid) => ast_node_and_leaf("Name", &format!("`{mid}`"), cm),
357    AstNode::Div(lhs, rhs) => ast_node_2("Div", lhs, rhs, cm),
358    AstNode::Eq(lhs, rhs) => ast_node_2("Eq", lhs, rhs, cm),
359    AstNode::EvaluatedExpression(mid) => ast_node_1("EvaluatedExpression", mid, cm),
360    AstNode::Every(lhs, rhs) => ast_node_2("Every", lhs, rhs, cm),
361    AstNode::Exp(lhs, rhs) => ast_node_2("Exp", lhs, rhs, cm),
362    AstNode::ExpressionList(items) => ast_node_n("ExpressionList", items, cm),
363    AstNode::FeelType(lhs) => ast_node_and_leaf("FeelType", &lhs.to_string(), cm),
364    AstNode::Filter(lhs, rhs) => ast_node_2("Filter", lhs, rhs, cm),
365    AstNode::For(lhs, rhs) => ast_node_2("For", lhs, rhs, cm),
366    AstNode::FormalParameter(lhs, rhs) => ast_node_2("FormalParameter", lhs, rhs, cm),
367    AstNode::FormalParameters(items) => ast_node_n("FormalParameters", items, cm),
368    AstNode::FunctionBody(lhs, external) => ast_node_and_label("FunctionBody", lhs, " (external)", "", *external, cm),
369    AstNode::FunctionDefinition(lhs, rhs) => ast_node_2("FunctionDefinition", lhs, rhs, cm),
370    AstNode::FunctionInvocation(lhs, rhs) => ast_node_2("FunctionInvocation", lhs, rhs, cm),
371    AstNode::FunctionType(lhs, rhs) => ast_node_2("FunctionType", lhs, rhs, cm),
372    AstNode::Ge(lhs, rhs) => ast_node_2("Ge", lhs, rhs, cm),
373    AstNode::Gt(lhs, rhs) => ast_node_2("Gt", lhs, rhs, cm),
374    AstNode::If(lhs, mid, rhs) => ast_node_3("If", lhs, mid, rhs, cm),
375    AstNode::In(lhs, rhs) => ast_node_2("In", lhs, rhs, cm),
376    AstNode::InstanceOf(lhs, rhs) => ast_node_2("InstanceOf", lhs, rhs, cm),
377    AstNode::IntervalEnd(lhs, closed) => ast_node_and_label("IntervalEnd", lhs, " (closed)", " (opened)", *closed, cm),
378    AstNode::IntervalStart(lhs, closed) => ast_node_and_label("IntervalStart", lhs, " (closed)", " (opened)", *closed, cm),
379    AstNode::Irrelevant => ast_leaf("Irrelevant", cm),
380    AstNode::IterationContexts(items) => ast_node_n("IterationContexts", items, cm),
381    AstNode::IterationContextSingle(lhs, rhs) => ast_node_2("IterationContextSingle", lhs, rhs, cm),
382    AstNode::IterationContextInterval(lhs, mid, rhs) => ast_node_3("IterationContextInterval", lhs, mid, rhs, cm),
383    AstNode::Le(lhs, rhs) => ast_node_2("Le", lhs, rhs, cm),
384    AstNode::List(mid) => ast_node_n("List", mid, cm),
385    AstNode::ListType(lhs) => ast_node_1("ListType", lhs, cm),
386    AstNode::Lt(lhs, rhs) => ast_node_2("Lt", lhs, rhs, cm),
387    AstNode::Mul(lhs, rhs) => ast_node_2("Mul", lhs, rhs, cm),
388    AstNode::Name(mid) => ast_node_and_leaf("Name", &format!("`{mid}`"), cm),
389    AstNode::NamedParameter(lhs, rhs) => ast_node_2("NamedParameter", lhs, rhs, cm),
390    AstNode::NamedParameters(items) => ast_node_n("NamedParameters", items, cm),
391    AstNode::Neg(mid) => ast_node_1("Neg", mid, cm),
392    AstNode::NegatedList(mid) => ast_node_n("NegatedList", mid, cm),
393    AstNode::Nq(lhs, rhs) => ast_node_2("Nq", lhs, rhs, cm),
394    AstNode::Null => ast_leaf("Null", cm),
395    AstNode::Numeric(before, after, sign, exponent) => ast_node_and_leaf("Numeric", &numeric_to_string(before, after, sign, exponent), cm),
396    AstNode::Or(lhs, rhs) => ast_node_2("Or", lhs, rhs, cm),
397    AstNode::Out(lhs, rhs) => ast_node_2("Out", lhs, rhs, cm),
398    AstNode::ParameterName(lhs) => ast_node_and_leaf("ParameterName", &format!("`{lhs}`"), cm),
399    AstNode::ParameterTypes(items) => ast_node_n("ParameterTypes", items, cm),
400    AstNode::Path(lhs, rhs) => ast_node_2("Path", lhs, rhs, cm),
401    AstNode::PositionalParameters(items) => ast_node_n("PositionalParameters", items, cm),
402    AstNode::QualifiedName(items) => ast_node_n("QualifiedName", items, cm),
403    AstNode::QualifiedNameSegment(lhs) => ast_node_and_leaf("Name", &format!("`{lhs}`"), cm),
404    AstNode::QuantifiedContext(lhs, rhs) => ast_node_2("QuantifiedContext", lhs, rhs, cm),
405    AstNode::QuantifiedContexts(items) => ast_node_n("QuantifiedContexts", items, cm),
406    AstNode::Range(lhs, rhs) => ast_node_2("Range", lhs, rhs, cm),
407    AstNode::RangeType(lhs) => ast_node_1("RangeType", lhs, cm),
408    AstNode::Satisfies(mid) => ast_node_1("Satisfies", mid, cm),
409    AstNode::Some(lhs, rhs) => ast_node_2("Some", lhs, rhs, cm),
410    AstNode::String(mid) => ast_node_and_leaf("String", &format!("`{mid}`"), cm),
411    AstNode::Sub(lhs, rhs) => ast_node_2("Sub", lhs, rhs, cm),
412    AstNode::UnaryGe(mid) => ast_node_1("UnaryGe", mid, cm),
413    AstNode::UnaryGt(mid) => ast_node_1("UnaryGt", mid, cm),
414    AstNode::UnaryLe(mid) => ast_node_1("UnaryLe", mid, cm),
415    AstNode::UnaryLt(mid) => ast_node_1("UnaryLt", mid, cm),
416    AstNode::UnaryEq(mid) => ast_node_1("UnaryEq", mid, cm),
417    AstNode::UnaryNe(mid) => ast_node_1("UnaryNe", mid, cm),
418  }
419}
420
421/// Creates a tree node with one child node.
422fn ast_node_1(name: &str, mid: &AstNode, cm: ColorMode) -> TreeNode {
423  node(DEFAULT_COLOR, cm).line().s(name).end().child(ast_node_to_tree(mid, cm)).end()
424}
425
426/// Creates a tree node with two child nodes.
427fn ast_node_2(name: &str, lhs: &AstNode, rhs: &AstNode, cm: ColorMode) -> TreeNode {
428  node(DEFAULT_COLOR, cm)
429    .line()
430    .s(name)
431    .end()
432    .child(ast_node_to_tree(lhs, cm))
433    .child(ast_node_to_tree(rhs, cm))
434    .end()
435}
436
437/// Creates a tree node with three child nodes.
438fn ast_node_3(name: &str, lhs: &AstNode, mid: &AstNode, rhs: &AstNode, cm: ColorMode) -> TreeNode {
439  node(DEFAULT_COLOR, cm)
440    .line()
441    .s(name)
442    .end()
443    .child(ast_node_to_tree(lhs, cm))
444    .child(ast_node_to_tree(mid, cm))
445    .child(ast_node_to_tree(rhs, cm))
446    .end()
447}
448
449/// Creates a tree node with multiple child nodes.
450fn ast_node_n(name: &str, items: &[AstNode], cm: ColorMode) -> TreeNode {
451  let mut node_builder = node(DEFAULT_COLOR, cm).line().s(name).end();
452  if items.is_empty() {
453    node_builder.add_child(leaf(cm).line().s("(empty)").end().end());
454  } else {
455    for item in items {
456      node_builder.add_child(ast_node_to_tree(item, cm));
457    }
458  }
459  node_builder.end()
460}
461
462/// Creates a node with single leaf node.
463fn ast_node_and_leaf(name: &str, leaf_caption: &str, cm: ColorMode) -> TreeNode {
464  node(DEFAULT_COLOR, cm).line().s(name).end().child(leaf(cm).line().s(leaf_caption).end().end()).end()
465}
466
467/// Creates a single node with additional label.
468fn ast_node_and_label(name: &str, lhs: &AstNode, label_true: &str, label_false: &str, label_flag: bool, cm: ColorMode) -> TreeNode {
469  let name_label = if label_flag { label_true } else { label_false };
470  node(DEFAULT_COLOR, cm).line().s(name).s(name_label).end().child(ast_node_to_tree(lhs, cm)).end()
471}
472
473/// Creates a leaf node.
474fn ast_leaf(leaf_caption: &str, cm: ColorMode) -> TreeNode {
475  leaf(cm).line().s(leaf_caption).end().end()
476}
477
478/// Converts a numeric AST node into string representation used in tree visualisation.
479fn numeric_to_string(before: &str, after: &str, sign: &char, exponent: &str) -> String {
480  let mut output = String::new();
481  let _ = write!(&mut output, "`{before}");
482  if !after.is_empty() {
483    let _ = write!(&mut output, ".{after}");
484  }
485  if !exponent.is_empty() {
486    let _ = write!(&mut output, "e{sign}{exponent}");
487  }
488  let _ = write!(&mut output, "`");
489  output
490}