dumps_ast/
dumps_ast.rs

1use rscel::{
2    Addition, AstNode, ConditionalAnd, ConditionalOr, Expr, ExprList, Ident, Member, MemberPrime,
3    Multiplication, NegList, NotList, ObjInit, ObjInits, Primary, Relation, Unary,
4};
5
6fn main() {
7    let args: Vec<_> = std::env::args().collect();
8
9    if args.len() < 2 {
10        eprintln!("Usage: {} <prog>", args[0]);
11        return;
12    }
13
14    let prog = rscel::Program::from_source(&args[1]).expect("Failed to compile");
15    let ast = prog.details().ast().unwrap();
16
17    AstDumper::with_source(&args[1]).dump_expr_node(ast, 0);
18}
19
20struct AstDumper<'a> {
21    source: &'a str,
22}
23
24impl<'a> AstDumper<'a> {
25    fn with_source(s: &'a str) -> Self {
26        AstDumper { source: s }
27    }
28
29    fn dump_expr_node(&self, node: &AstNode<Expr>, depth: usize) {
30        self.format_output(node, depth);
31        match node.node() {
32            Expr::Unary(nxt) => self.dump_or_node(nxt, depth + 1),
33            Expr::Ternary {
34                condition,
35                true_clause,
36                false_clause,
37            } => {
38                self.dump_or_node(condition, depth + 1);
39                self.dump_or_node(true_clause, depth + 1);
40                self.dump_expr_node(false_clause, depth + 1);
41            }
42            Expr::Match { .. } => todo!(),
43        }
44    }
45
46    fn dump_or_node(&self, node: &AstNode<ConditionalOr>, depth: usize) {
47        self.format_output(node, depth);
48        match node.node() {
49            ConditionalOr::Unary(nxt) => self.dump_and_node(nxt, depth + 1),
50            ConditionalOr::Binary { lhs, rhs } => {
51                self.dump_or_node(lhs, depth + 1);
52                self.dump_and_node(rhs, depth + 1)
53            }
54        }
55    }
56
57    fn dump_and_node(&self, node: &AstNode<ConditionalAnd>, depth: usize) {
58        self.format_output(node, depth);
59        match node.node() {
60            ConditionalAnd::Unary(nxt) => self.dump_relation(nxt, depth + 1),
61            ConditionalAnd::Binary { lhs, rhs } => {
62                self.dump_and_node(lhs, depth + 1);
63                self.dump_relation(rhs, depth + 1);
64            }
65        }
66    }
67
68    fn dump_relation(&self, node: &AstNode<Relation>, depth: usize) {
69        self.format_output(node, depth);
70        match node.node() {
71            Relation::Unary(nxt) => self.dump_addition(nxt, depth + 1),
72            Relation::Binary { lhs, op: _op, rhs } => {
73                self.dump_relation(lhs, depth + 1);
74                self.dump_addition(rhs, depth + 1);
75            }
76        }
77    }
78
79    fn dump_addition(&self, node: &AstNode<Addition>, depth: usize) {
80        self.format_output(node, depth);
81        match node.node() {
82            Addition::Unary(nxt) => self.dump_multiplication(nxt, depth + 1),
83            Addition::Binary { lhs, op: _op, rhs } => {
84                self.dump_addition(lhs, depth + 1);
85                self.dump_multiplication(rhs, depth + 1);
86            }
87        }
88    }
89
90    fn dump_multiplication(&self, node: &AstNode<Multiplication>, depth: usize) {
91        self.format_output(node, depth);
92        match node.node() {
93            Multiplication::Unary(nxt) => self.dump_uniary(nxt, depth + 1),
94            Multiplication::Binary { lhs, op: _op, rhs } => {
95                self.dump_multiplication(lhs, depth + 1);
96                self.dump_uniary(rhs, depth + 1);
97            }
98        }
99    }
100
101    fn dump_uniary(&self, node: &AstNode<Unary>, depth: usize) {
102        self.format_output(node, depth);
103        match node.node() {
104            Unary::Member(nxt) => self.dump_member(nxt, depth + 1),
105            Unary::NegMember { negs, member } => {
106                self.dump_neg(negs, depth + 1);
107                self.dump_member(member, depth + 1);
108            }
109            Unary::NotMember { nots, member } => {
110                self.dump_not(nots, depth + 1);
111                self.dump_member(member, depth + 1);
112            }
113        }
114    }
115
116    fn dump_neg(&self, node: &AstNode<NegList>, depth: usize) {
117        self.format_output(node, depth);
118        match node.node() {
119            NegList::List { tail } => self.dump_neg(tail, depth + 1),
120            NegList::EmptyList => {}
121        }
122    }
123
124    fn dump_not(&self, node: &AstNode<NotList>, depth: usize) {
125        self.format_output(node, depth);
126        match node.node() {
127            NotList::List { tail } => self.dump_not(tail, depth + 1),
128            NotList::EmptyList => {}
129        }
130    }
131
132    fn dump_member(&self, node: &AstNode<Member>, depth: usize) {
133        self.format_output(node, depth);
134        self.dump_primary(&node.node().primary, depth + 1);
135        for member in node.node().member.iter() {
136            self.dump_member_prime(member, depth + 1);
137        }
138    }
139
140    fn dump_primary(&self, node: &AstNode<Primary>, depth: usize) {
141        self.format_output(node, depth);
142        match node.node() {
143            Primary::Type => {}
144            Primary::Ident(_) => {}
145            Primary::Parens(expr) => self.dump_expr_node(expr, depth + 1),
146            Primary::ListConstruction(exprs) => self.dump_expr_list(exprs, depth + 1),
147            Primary::ObjectInit(objinits) => self.dump_obj_inits(objinits, depth + 1),
148            Primary::Literal(_) => {}
149        }
150    }
151
152    fn dump_member_prime(&self, node: &AstNode<MemberPrime>, depth: usize) {
153        self.format_output(node, depth);
154        match node.node() {
155            MemberPrime::MemberAccess { ident } => {
156                self.dump_ident(&ident, depth + 1);
157            }
158            MemberPrime::Call { call } => self.dump_expr_list(call, depth + 1),
159            MemberPrime::ArrayAccess { access } => self.dump_expr_node(access, depth + 1),
160            MemberPrime::Empty => {}
161        }
162    }
163
164    fn dump_ident(&self, node: &AstNode<Ident>, depth: usize) {
165        self.format_output(node, depth);
166    }
167
168    fn dump_expr_list(&self, node: &AstNode<ExprList>, depth: usize) {
169        self.format_output(node, depth);
170        for expr in node.node().exprs.iter() {
171            self.dump_expr_node(expr, depth + 1);
172        }
173    }
174
175    fn dump_obj_inits(&self, node: &AstNode<ObjInits>, depth: usize) {
176        self.format_output(node, depth);
177        for init in node.node().inits.iter() {
178            self.dump_obj_init(init, depth + 1);
179        }
180    }
181
182    fn dump_obj_init(&self, node: &AstNode<ObjInit>, depth: usize) {
183        self.format_output(node, depth);
184        self.dump_expr_node(&node.node().key, depth + 1);
185        self.dump_expr_node(&node.node().value, depth + 1);
186    }
187
188    fn format_output<T>(&self, ast: &AstNode<T>, depth: usize) {
189        let spacing: String = std::iter::repeat(' ').take(depth).collect();
190
191        println!(
192            "{} {} -- '{}'::{},{}",
193            spacing,
194            std::any::type_name::<T>().split("::").last().unwrap(),
195            &self.source.to_string()[ast.start().col()..ast.end().col()],
196            ast.start().col(),
197            ast.end().col()
198        );
199    }
200}