dmntk_feel_parser/
ast.rs

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