plotnik_compiler/analyze/
visitor.rs

1//! AST Visitor pattern.
2//!
3//! # Usage
4//!
5//! Implement `Visitor` for your struct. Override `visit_*` methods to add logic.
6//! Call `walk_*` within your override to continue recursion (or omit it to stop).
7//!
8//! ```ignore
9//! impl Visitor for MyPass {
10//!     fn visit_named_node(&mut self, node: &NamedNode) {
11//!         // Pre-order logic
12//!         walk_named_node(self, node);
13//!         // Post-order logic
14//!     }
15//! }
16//! ```
17
18use crate::parser::{
19    AltExpr, AnonymousNode, CapturedExpr, Def, Expr, FieldExpr, NamedNode, QuantifiedExpr, Ref,
20    Root, SeqExpr,
21};
22
23pub trait Visitor: Sized {
24    fn visit(&mut self, ast: &Root) {
25        walk(self, ast);
26    }
27
28    fn visit_def(&mut self, def: &Def) {
29        walk_def(self, def);
30    }
31
32    fn visit_expr(&mut self, expr: &Expr) {
33        walk_expr(self, expr);
34    }
35
36    fn visit_named_node(&mut self, node: &NamedNode) {
37        walk_named_node(self, node);
38    }
39
40    fn visit_anonymous_node(&mut self, _node: &AnonymousNode) {}
41
42    fn visit_ref(&mut self, _ref: &Ref) {}
43
44    fn visit_alt_expr(&mut self, alt: &AltExpr) {
45        walk_alt_expr(self, alt);
46    }
47
48    fn visit_seq_expr(&mut self, seq: &SeqExpr) {
49        walk_seq_expr(self, seq);
50    }
51
52    fn visit_captured_expr(&mut self, cap: &CapturedExpr) {
53        walk_captured_expr(self, cap);
54    }
55
56    fn visit_quantified_expr(&mut self, quant: &QuantifiedExpr) {
57        walk_quantified_expr(self, quant);
58    }
59
60    fn visit_field_expr(&mut self, field: &FieldExpr) {
61        walk_field_expr(self, field);
62    }
63}
64
65pub fn walk<V: Visitor>(visitor: &mut V, ast: &Root) {
66    for def in ast.defs() {
67        visitor.visit_def(&def);
68    }
69}
70
71pub fn walk_def<V: Visitor>(visitor: &mut V, def: &Def) {
72    if let Some(body) = def.body() {
73        visitor.visit_expr(&body);
74    }
75}
76
77pub fn walk_expr<V: Visitor>(visitor: &mut V, expr: &Expr) {
78    match expr {
79        Expr::NamedNode(n) => visitor.visit_named_node(n),
80        Expr::AnonymousNode(n) => visitor.visit_anonymous_node(n),
81        Expr::Ref(r) => visitor.visit_ref(r),
82        Expr::AltExpr(a) => visitor.visit_alt_expr(a),
83        Expr::SeqExpr(s) => visitor.visit_seq_expr(s),
84        Expr::CapturedExpr(c) => visitor.visit_captured_expr(c),
85        Expr::QuantifiedExpr(q) => visitor.visit_quantified_expr(q),
86        Expr::FieldExpr(f) => visitor.visit_field_expr(f),
87    }
88}
89
90pub fn walk_named_node<V: Visitor>(visitor: &mut V, node: &NamedNode) {
91    for child in node.children() {
92        visitor.visit_expr(&child);
93    }
94}
95
96pub fn walk_alt_expr<V: Visitor>(visitor: &mut V, alt: &AltExpr) {
97    for branch in alt.branches() {
98        if let Some(body) = branch.body() {
99            visitor.visit_expr(&body);
100        }
101    }
102
103    for expr in alt.exprs() {
104        visitor.visit_expr(&expr);
105    }
106}
107
108pub fn walk_seq_expr<V: Visitor>(visitor: &mut V, seq: &SeqExpr) {
109    for child in seq.children() {
110        visitor.visit_expr(&child);
111    }
112}
113
114pub fn walk_captured_expr<V: Visitor>(visitor: &mut V, cap: &CapturedExpr) {
115    if let Some(inner) = cap.inner() {
116        visitor.visit_expr(&inner);
117    }
118}
119
120pub fn walk_quantified_expr<V: Visitor>(visitor: &mut V, quant: &QuantifiedExpr) {
121    if let Some(inner) = quant.inner() {
122        visitor.visit_expr(&inner);
123    }
124}
125
126pub fn walk_field_expr<V: Visitor>(visitor: &mut V, field: &FieldExpr) {
127    if let Some(val) = field.value() {
128        visitor.visit_expr(&val);
129    }
130}