1use antex::{leaf, node, Color, ColorMode, StyledText, TreeNode};
4use dsntk_feel::{FeelType, 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(Box<AstNode>, bool),
157
158 IntervalStart(Box<AstNode>, bool),
160
161 Irrelevant,
163
164 IterationContexts(Vec<AstNode>),
166
167 IterationContextSingle(
169 Box<AstNode>,
171 Box<AstNode>,
173 ),
174
175 IterationContextInterval(
178 Box<AstNode>,
180 Box<AstNode>,
182 Box<AstNode>,
184 ),
185
186 Le(Box<AstNode>, Box<AstNode>),
188
189 Lt(Box<AstNode>, Box<AstNode>),
191
192 List(Vec<AstNode>),
194
195 ListType(Box<AstNode>),
197
198 Mul(Box<AstNode>, Box<AstNode>),
200
201 Name(Name),
203
204 NamedParameter(
206 Box<AstNode>,
208 Box<AstNode>,
210 ),
211
212 NamedParameters(Vec<AstNode>),
214
215 NegatedList(Vec<AstNode>),
217
218 Neg(Box<AstNode>),
220
221 Nq(Box<AstNode>, Box<AstNode>),
223
224 Null,
226
227 Numeric(
229 String,
231 String,
233 char,
235 String,
237 ),
238
239 Or(Box<AstNode>, Box<AstNode>),
241
242 Out(Box<AstNode>, Box<AstNode>),
244
245 ParameterName(Name),
247
248 ParameterTypes(Vec<AstNode>),
250
251 Path(Box<AstNode>, Box<AstNode>),
253
254 PositionalParameters(Vec<AstNode>),
256
257 QualifiedName(Vec<AstNode>),
259
260 QualifiedNameSegment(Name),
262
263 QuantifiedContexts(Vec<AstNode>),
265
266 QuantifiedContext(
268 Box<AstNode>,
270 Box<AstNode>,
272 ),
273
274 Range(Box<AstNode>, Box<AstNode>),
276
277 RangeType(Box<AstNode>),
279
280 Satisfies(Box<AstNode>),
282
283 Some(
285 Box<AstNode>,
287 Box<AstNode>,
289 ),
290
291 String(String),
293
294 Sub(Box<AstNode>, Box<AstNode>),
296
297 UnaryGe(Box<AstNode>),
299
300 UnaryGt(Box<AstNode>),
302
303 UnaryLe(Box<AstNode>),
305
306 UnaryLt(Box<AstNode>),
308
309 UnaryEq(Box<AstNode>),
311
312 UnaryNe(Box<AstNode>),
314}
315
316impl Display for AstNode {
317 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
319 write!(f, "{}", self.tree(0, ColorMode::Off))
320 }
321}
322
323impl AstNode {
324 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 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
342fn 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
421fn 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
426fn 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
437fn 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
449fn 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
462fn 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
467fn 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
473fn ast_leaf(leaf_caption: &str, cm: ColorMode) -> TreeNode {
475 leaf(cm).line().s(leaf_caption).end().end()
476}
477
478fn 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}