1use antex::{Color, ColorMode, StyledText, TreeNode, leaf, node};
4use dsntk_feel::{FeelType, IntervalType, Name};
5use std::fmt;
6use std::fmt::{Display, Write};
7
8const DEFAULT_COLOR: Color = Color::White;
10
11#[derive(Debug, Clone, PartialEq)]
13pub enum AstNode {
14 Add(Box<AstNode>, Box<AstNode>),
16
17 And(Box<AstNode>, Box<AstNode>),
19
20 At(String),
22
23 Between(Box<AstNode>, Box<AstNode>, Box<AstNode>),
25
26 Boolean(bool),
28
29 CommaList(Vec<AstNode>),
31
32 Context(Vec<AstNode>),
35
36 ContextEntry(Box<AstNode>, Box<AstNode>),
38
39 ContextEntryKey(Name),
43
44 ContextType(Vec<AstNode>),
48
49 ContextTypeEntry(
51 Box<AstNode>,
53 Box<AstNode>,
55 ),
56
57 ContextTypeEntryKey(Name),
60
61 Div(Box<AstNode>, Box<AstNode>),
63
64 Eq(Box<AstNode>, Box<AstNode>),
66
67 EvaluatedExpression(Box<AstNode>),
69
70 Every(
72 Box<AstNode>,
74 Box<AstNode>,
76 ),
77
78 Exp(Box<AstNode>, Box<AstNode>),
80
81 ExpressionList(Vec<AstNode>),
83
84 FeelType(FeelType),
86
87 Filter(Box<AstNode>, Box<AstNode>),
89
90 For(
92 Box<AstNode>,
94 Box<AstNode>,
96 ),
97
98 FormalParameter(
100 Box<AstNode>,
102 Box<AstNode>,
104 ),
105
106 FormalParameters(Vec<AstNode>),
108
109 FunctionBody(Box<AstNode>, bool),
112
113 FunctionDefinition(Box<AstNode>, Box<AstNode>),
116
117 FunctionInvocation(Box<AstNode>, Box<AstNode>),
119
120 FunctionType(
122 Box<AstNode>,
124 Box<AstNode>,
126 ),
127
128 Ge(Box<AstNode>, Box<AstNode>),
130
131 Gt(Box<AstNode>, Box<AstNode>),
133
134 If(
136 Box<AstNode>,
138 Box<AstNode>,
140 Box<AstNode>,
142 ),
143
144 In(Box<AstNode>, Box<AstNode>),
146
147 InstanceOf(
149 Box<AstNode>,
151 Box<AstNode>,
153 ),
154
155 IntervalEnd(
157 Box<AstNode>,
159 IntervalType,
161 ),
162
163 IntervalStart(
165 Box<AstNode>,
167 IntervalType,
169 ),
170
171 Irrelevant,
173
174 IterationContexts(Vec<AstNode>),
176
177 IterationContextSingle(
179 Box<AstNode>,
181 Box<AstNode>,
183 ),
184
185 IterationContextInterval(
188 Box<AstNode>,
190 Box<AstNode>,
192 Box<AstNode>,
194 ),
195
196 Le(Box<AstNode>, Box<AstNode>),
198
199 Lt(Box<AstNode>, Box<AstNode>),
201
202 List(Vec<AstNode>),
204
205 ListType(Box<AstNode>),
207
208 Mul(Box<AstNode>, Box<AstNode>),
210
211 Name(Name),
213
214 NamedParameter(
216 Box<AstNode>,
218 Box<AstNode>,
220 ),
221
222 NamedParameters(Vec<AstNode>),
224
225 NegatedList(Vec<AstNode>),
227
228 Neg(Box<AstNode>),
230
231 Nq(Box<AstNode>, Box<AstNode>),
233
234 Null,
236
237 Numeric(
239 String,
241 String,
243 char,
245 String,
247 ),
248
249 Or(Box<AstNode>, Box<AstNode>),
251
252 Out(Box<AstNode>, Box<AstNode>),
254
255 ParameterName(Name),
257
258 ParameterTypes(Vec<AstNode>),
260
261 Path(Box<AstNode>, Box<AstNode>),
263
264 PositionalParameters(Vec<AstNode>),
266
267 QualifiedName(Vec<AstNode>),
269
270 QualifiedNameSegment(Name),
272
273 QuantifiedContexts(Vec<AstNode>),
275
276 QuantifiedContext(
278 Box<AstNode>,
280 Box<AstNode>,
282 ),
283
284 Range(Box<AstNode>, Box<AstNode>),
286
287 RangeType(Box<AstNode>),
289
290 Satisfies(Box<AstNode>),
292
293 Some(
295 Box<AstNode>,
297 Box<AstNode>,
299 ),
300
301 String(String),
303
304 Sub(Box<AstNode>, Box<AstNode>),
306
307 UnaryGe(Box<AstNode>),
309
310 UnaryGt(Box<AstNode>),
312
313 UnaryLe(Box<AstNode>),
315
316 UnaryLt(Box<AstNode>),
318
319 UnaryEq(Box<AstNode>),
321
322 UnaryNe(Box<AstNode>),
324}
325
326impl Display for AstNode {
327 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
329 write!(f, "{}", self.tree(0, ColorMode::Off))
330 }
331}
332
333impl AstNode {
334 pub fn tree(&self, indent: usize, cm: ColorMode) -> String {
336 let root = ast_node_to_tree(self, cm);
337 let mut output = String::new();
338 _ = write!(output, "{:indent$}", root);
339 output
340 }
341
342 pub fn trace(&self) -> String {
344 let root = ast_node_to_tree(self, ColorMode::Off);
345 let mut output = String::new();
346 _ = write!(output, "\n{:6} ", root);
347 output
348 }
349}
350
351fn ast_node_to_tree(node: &AstNode, cm: ColorMode) -> TreeNode {
353 match node {
354 AstNode::Add(lhs, rhs) => ast_node_2("Add", lhs, rhs, cm),
355 AstNode::And(lhs, rhs) => ast_node_2("And", lhs, rhs, cm),
356 AstNode::At(mid) => ast_node_and_leaf("At", &format!("`{mid}`"), cm),
357 AstNode::Between(lhs, mid, rhs) => ast_node_3("Between", lhs, mid, rhs, cm),
358 AstNode::Boolean(mid) => ast_node_and_leaf("Boolean", &format!("`{mid}`"), cm),
359 AstNode::CommaList(mid) => ast_node_n("CommaList", mid, cm),
360 AstNode::Context(items) => ast_node_n("Context", items, cm),
361 AstNode::ContextEntry(lhs, rhs) => ast_node_2("ContextEntry", lhs, rhs, cm),
362 AstNode::ContextEntryKey(mid) => ast_node_and_leaf("ContextEntryKey", &format!("`{mid}`"), cm),
363 AstNode::ContextType(items) => ast_node_n("ContextType", items, cm),
364 AstNode::ContextTypeEntry(lhs, rhs) => ast_node_2("ContextTypeEntry", lhs, rhs, cm),
365 AstNode::ContextTypeEntryKey(mid) => ast_node_and_leaf("Name", &format!("`{mid}`"), cm),
366 AstNode::Div(lhs, rhs) => ast_node_2("Div", lhs, rhs, cm),
367 AstNode::Eq(lhs, rhs) => ast_node_2("Eq", lhs, rhs, cm),
368 AstNode::EvaluatedExpression(mid) => ast_node_1("EvaluatedExpression", mid, cm),
369 AstNode::Every(lhs, rhs) => ast_node_2("Every", lhs, rhs, cm),
370 AstNode::Exp(lhs, rhs) => ast_node_2("Exp", lhs, rhs, cm),
371 AstNode::ExpressionList(items) => ast_node_n("ExpressionList", items, cm),
372 AstNode::FeelType(lhs) => ast_node_and_leaf("FeelType", &lhs.to_string(), cm),
373 AstNode::Filter(lhs, rhs) => ast_node_2("Filter", lhs, rhs, cm),
374 AstNode::For(lhs, rhs) => ast_node_2("For", lhs, rhs, cm),
375 AstNode::FormalParameter(lhs, rhs) => ast_node_2("FormalParameter", lhs, rhs, cm),
376 AstNode::FormalParameters(items) => ast_node_n("FormalParameters", items, cm),
377 AstNode::FunctionBody(lhs, external) => ast_node_and_conditional_label("FunctionBody", lhs, " (external)", "", *external, cm),
378 AstNode::FunctionDefinition(lhs, rhs) => ast_node_2("FunctionDefinition", lhs, rhs, cm),
379 AstNode::FunctionInvocation(lhs, rhs) => ast_node_2("FunctionInvocation", lhs, rhs, cm),
380 AstNode::FunctionType(lhs, rhs) => ast_node_2("FunctionType", lhs, rhs, cm),
381 AstNode::Ge(lhs, rhs) => ast_node_2("Ge", lhs, rhs, cm),
382 AstNode::Gt(lhs, rhs) => ast_node_2("Gt", lhs, rhs, cm),
383 AstNode::If(lhs, mid, rhs) => ast_node_3("If", lhs, mid, rhs, cm),
384 AstNode::In(lhs, rhs) => ast_node_2("In", lhs, rhs, cm),
385 AstNode::InstanceOf(lhs, rhs) => ast_node_2("InstanceOf", lhs, rhs, cm),
386 AstNode::IntervalEnd(lhs, interval_type) => ast_node_and_label("IntervalEnd", lhs, interval_type.to_string(), cm),
387 AstNode::IntervalStart(lhs, interval_type) => ast_node_and_label("IntervalStart", lhs, interval_type.to_string(), cm),
388 AstNode::Irrelevant => ast_leaf("Irrelevant", cm),
389 AstNode::IterationContexts(items) => ast_node_n("IterationContexts", items, cm),
390 AstNode::IterationContextSingle(lhs, rhs) => ast_node_2("IterationContextSingle", lhs, rhs, cm),
391 AstNode::IterationContextInterval(lhs, mid, rhs) => ast_node_3("IterationContextInterval", lhs, mid, rhs, cm),
392 AstNode::Le(lhs, rhs) => ast_node_2("Le", lhs, rhs, cm),
393 AstNode::List(mid) => ast_node_n("List", mid, cm),
394 AstNode::ListType(lhs) => ast_node_1("ListType", lhs, cm),
395 AstNode::Lt(lhs, rhs) => ast_node_2("Lt", lhs, rhs, cm),
396 AstNode::Mul(lhs, rhs) => ast_node_2("Mul", lhs, rhs, cm),
397 AstNode::Name(mid) => ast_node_and_leaf("Name", &format!("`{mid}`"), cm),
398 AstNode::NamedParameter(lhs, rhs) => ast_node_2("NamedParameter", lhs, rhs, cm),
399 AstNode::NamedParameters(items) => ast_node_n("NamedParameters", items, cm),
400 AstNode::Neg(mid) => ast_node_1("Neg", mid, cm),
401 AstNode::NegatedList(mid) => ast_node_n("NegatedList", mid, cm),
402 AstNode::Nq(lhs, rhs) => ast_node_2("Nq", lhs, rhs, cm),
403 AstNode::Null => ast_leaf("Null", cm),
404 AstNode::Numeric(before, after, sign, exponent) => ast_node_and_leaf("Numeric", &numeric_to_string(before, after, sign, exponent), cm),
405 AstNode::Or(lhs, rhs) => ast_node_2("Or", lhs, rhs, cm),
406 AstNode::Out(lhs, rhs) => ast_node_2("Out", lhs, rhs, cm),
407 AstNode::ParameterName(lhs) => ast_node_and_leaf("ParameterName", &format!("`{lhs}`"), cm),
408 AstNode::ParameterTypes(items) => ast_node_n("ParameterTypes", items, cm),
409 AstNode::Path(lhs, rhs) => ast_node_2("Path", lhs, rhs, cm),
410 AstNode::PositionalParameters(items) => ast_node_n("PositionalParameters", items, cm),
411 AstNode::QualifiedName(items) => ast_node_n("QualifiedName", items, cm),
412 AstNode::QualifiedNameSegment(lhs) => ast_node_and_leaf("Name", &format!("`{lhs}`"), cm),
413 AstNode::QuantifiedContext(lhs, rhs) => ast_node_2("QuantifiedContext", lhs, rhs, cm),
414 AstNode::QuantifiedContexts(items) => ast_node_n("QuantifiedContexts", items, cm),
415 AstNode::Range(lhs, rhs) => ast_node_2("Range", lhs, rhs, cm),
416 AstNode::RangeType(lhs) => ast_node_1("RangeType", lhs, cm),
417 AstNode::Satisfies(mid) => ast_node_1("Satisfies", mid, cm),
418 AstNode::Some(lhs, rhs) => ast_node_2("Some", lhs, rhs, cm),
419 AstNode::String(mid) => ast_node_and_leaf("String", &format!("`{mid}`"), cm),
420 AstNode::Sub(lhs, rhs) => ast_node_2("Sub", lhs, rhs, cm),
421 AstNode::UnaryGe(mid) => ast_node_1("UnaryGe", mid, cm),
422 AstNode::UnaryGt(mid) => ast_node_1("UnaryGt", mid, cm),
423 AstNode::UnaryLe(mid) => ast_node_1("UnaryLe", mid, cm),
424 AstNode::UnaryLt(mid) => ast_node_1("UnaryLt", mid, cm),
425 AstNode::UnaryEq(mid) => ast_node_1("UnaryEq", mid, cm),
426 AstNode::UnaryNe(mid) => ast_node_1("UnaryNe", mid, cm),
427 }
428}
429
430fn ast_node_1(name: &str, mid: &AstNode, cm: ColorMode) -> TreeNode {
432 node(DEFAULT_COLOR, cm).line().s(name).end().child(ast_node_to_tree(mid, cm)).end()
433}
434
435fn ast_node_2(name: &str, lhs: &AstNode, rhs: &AstNode, cm: ColorMode) -> TreeNode {
437 node(DEFAULT_COLOR, cm)
438 .line()
439 .s(name)
440 .end()
441 .child(ast_node_to_tree(lhs, cm))
442 .child(ast_node_to_tree(rhs, cm))
443 .end()
444}
445
446fn ast_node_3(name: &str, lhs: &AstNode, mid: &AstNode, rhs: &AstNode, cm: ColorMode) -> TreeNode {
448 node(DEFAULT_COLOR, cm)
449 .line()
450 .s(name)
451 .end()
452 .child(ast_node_to_tree(lhs, cm))
453 .child(ast_node_to_tree(mid, cm))
454 .child(ast_node_to_tree(rhs, cm))
455 .end()
456}
457
458fn ast_node_n(name: &str, items: &[AstNode], cm: ColorMode) -> TreeNode {
460 let mut node_builder = node(DEFAULT_COLOR, cm).line().s(name).end();
461 if items.is_empty() {
462 node_builder.add_child(leaf(cm).line().s("(empty)").end().end());
463 } else {
464 for item in items {
465 node_builder.add_child(ast_node_to_tree(item, cm));
466 }
467 }
468 node_builder.end()
469}
470
471fn ast_node_and_leaf(name: &str, leaf_caption: &str, cm: ColorMode) -> TreeNode {
473 node(DEFAULT_COLOR, cm).line().s(name).end().child(leaf(cm).line().s(leaf_caption).end().end()).end()
474}
475
476fn ast_node_and_conditional_label(name: &str, lhs: &AstNode, label_true: &str, label_false: &str, label_flag: bool, cm: ColorMode) -> TreeNode {
478 let name_label = if label_flag { label_true } else { label_false };
479 node(DEFAULT_COLOR, cm).line().s(name).s(name_label).end().child(ast_node_to_tree(lhs, cm)).end()
480}
481
482fn ast_node_and_label(name: &str, lhs: &AstNode, label: impl AsRef<str>, cm: ColorMode) -> TreeNode {
484 let label = format!(" ({})", label.as_ref());
485 node(DEFAULT_COLOR, cm).line().s(name).s(label).end().child(ast_node_to_tree(lhs, cm)).end()
486}
487
488fn ast_leaf(leaf_caption: &str, cm: ColorMode) -> TreeNode {
490 leaf(cm).line().s(leaf_caption).end().end()
491}
492
493fn numeric_to_string(before: &str, after: &str, sign: &char, exponent: &str) -> String {
495 let mut output = String::new();
496 let _ = write!(&mut output, "`{before}");
497 if !after.is_empty() {
498 let _ = write!(&mut output, ".{after}");
499 }
500 if !exponent.is_empty() {
501 let _ = write!(&mut output, "e{sign}{exponent}");
502 }
503 let _ = write!(&mut output, "`");
504 output
505}