ROSE 0.11.145.147
AST/Traversal.h
1#ifndef ROSE_AST_Traversal_H
2#define ROSE_AST_Traversal_H
3
4#include <RoseFirst.h>
5#include <vector>
6
7// A version of AST traversal that doesn't require huge header files to be included into the compilation unit that's calling the
8// traversal.
9
10class SgNode;
11
12namespace Rose {
13namespace AST {
14
16namespace Traversal {
17
19enum class Order { // bit flags
20 PRE = 0x01,
21 POST = 0x02
22};
23
25// Implementation
27
28namespace detail {
29
30// Base visitor class. The idea is that the base class is abstract so it can be implemented in a single .C file. It is implemented
31// in terms of ROSE's `AstPrePostProcessing` which requires definitions for every Sg node. It's fine to #include all those
32// definitions into that one .C file were we need them, but we want to avoid having to #include all those definitions into every
33// .C file that needs to do an AST traversal.
34//
35// Classes derived from `VisitorBase` are defined by templates, but they've been designed so as to not require any class definitions
36// except for `T` (and T's base classes).
38public:
39 virtual ~VisitorBase() {}
40 virtual void operator()(SgNode*, Order) const = 0;
41};
42
43// Calls functor before and after (pre and post) with the node pointer and an indication of when it is being called.
44template<class T, class Functor>
46 Functor &f;
47public:
48 explicit VisitorOrdered(Functor &f)
49 : f(f) {}
50
51 void operator()(SgNode *node, const Order order) const override {
52 if (T *typedNode = dynamic_cast<T*>(node))
53 f(typedNode, order);
54 }
55};
56
57// Calls functor only before visiting related nodes. Functor is called with only the node pointer argument.
58template<class T, class Functor>
59class VisitorPre: public VisitorBase {
60 Functor &f;
61public:
62 explicit VisitorPre(Functor &f)
63 : f(f) {}
64
65 void operator()(SgNode *node, const Order order) const override {
66 if (Order::PRE == order) {
67 if (T *typedNode = dynamic_cast<T*>(node))
68 f(typedNode);
69 }
70 }
71};
72
73// Calls functor only after visiting related nodes. Functor is called with only the node pointer argument.
74template<class T, class Functor>
75class VisitorPost: public VisitorBase {
76 Functor &f;
77public:
78 explicit VisitorPost(Functor &f)
79 : f(f) {}
80
81 void operator()(SgNode *node, const Order order) const override {
82 if (Order::POST == order) {
83 if (T *typedNode = dynamic_cast<T*>(node))
84 f(typedNode);
85 }
86 }
87};
88
89// Base class for finding a particular node. This works similarly to the `VisitorBase` in that this abstract base class is
90// what's passed across compilation units so that only the one .C file that implements the traversal needs to include the whole
91// world.
92//
93// The derived classes, which are class templates, only need the definition for their `T` type (and it's base classes), and do not
94// need the definitions for all AST node classes.
96public:
97 SgNode *found = nullptr;
98
99 virtual ~FinderBase() {}
100 virtual bool operator()(SgNode *node) = 0;
101};
102
103// Calls the specified predicate for each visited node of the correct dynamic type.
104template<class T, class Functor>
105class Finder: public FinderBase {
106 Functor &f;
107public:
108 explicit Finder(Functor &f)
109 : f(f) {}
110
111 bool operator()(SgNode *node) override {
112 if (T *typedNode = dynamic_cast<T*>(node)) {
113 return f(typedNode);
114 } else {
115 return false;
116 }
117 }
118};
119
120// Traverse an AST in a forward direction, calling the visitor for a node before and then after visiting the node's children.
121void forwardHelper(SgNode *ast, const VisitorBase&);
122
123// Traverse an AST in the reverse direction, calling the visitor for a node before and then after visiting the node's parents.
124void reverseHelper(SgNode *ast, const VisitorBase&);
125
126// Traverse an AST in reverse to find the first occurrence of a particular node, and saves that node in the `FinderBase`.
127void findReverseHelper(SgNode *ast, FinderBase&);
128
129} // namespace
130
132// Traversals
134
182template<class T, class Functor>
183void forward(SgNode *ast, Functor functor) {
184 detail::forwardHelper(ast, detail::VisitorOrdered<T, Functor>(functor));
185}
186
192template<class T, class Functor>
193void forwardPre(SgNode *ast, Functor functor) {
194 detail::forwardHelper(ast, detail::VisitorPre<T, Functor>(functor));
195}
196
202template<class T, class Functor>
203void forwardPost(SgNode *ast, Functor functor) {
204 detail::forwardHelper(ast, detail::VisitorPost<T, Functor>(functor));
205}
206
213template<class T, class Functor>
214void reverse(SgNode *ast, Functor functor) {
215 detail::reverseHelper(ast, detail::VisitorOrdered<T, Functor>(functor));
216}
217
222template<class T, class Functor>
223void reversePre(SgNode *ast, Functor functor) {
224 detail::reverseHelper(ast, detail::VisitorPre<T, Functor>(functor));
225}
226
231template<class T, class Functor>
232void reversePost(SgNode *ast, Functor functor) {
233 detail::reverseHelper(ast, detail::VisitorPost<T, Functor>(functor));
234}
235
242template<class T, class Functor>
243T*
244findParentSatisying(SgNode *ast, Functor functor) {
245 detail::Finder<T, Functor> finder(functor);
246 detail::findReverseHelper(ast, finder /*in,out*/);
247 return dynamic_cast<T*>(finder.found);
248}
249
254template<class T>
255T*
257 auto yes = [](SgNode*) { return true; };
258 detail::Finder<T, decltype(yes)> finder(yes);
259 detail::findReverseHelper(ast, finder /*in,out*/);
260 return dynamic_cast<T*>(finder.found);
261}
262
267template<class T>
268std::vector<T*>
270 std::vector<T*> retval;
271 forwardPre<T>(ast, [&retval](T *node) {
272 retval.push_back(node);
273 });
274 return retval;
275}
276
277} // namespace
278} // namespace
279} // namespace
280
281#endif
This class represents the base class for all IR nodes within Sage III.
void forward(SgNode *ast, Functor functor)
Traverse an AST in a forward direction.
std::vector< T * > findDescendantsTyped(SgNode *ast)
Find all descendants of specified type.
T * findParentTyped(SgNode *ast)
Find the closest parent of specified type.
void reversePost(SgNode *ast, Functor functor)
Traverse an AST in the reverse with post-visit only.
void forwardPost(SgNode *ast, Functor functor)
Traverse an AST in a forward direction with post-visit only.
Order
Order that visitor is called for node w.r.t.
@ POST
Visitor is called after visiting the node's children.
@ PRE
Visitor is called before visiting the node's children.
void forwardPre(SgNode *ast, Functor functor)
Traverse an AST in a forward direction with pre-visit only.
T * findParentSatisying(SgNode *ast, Functor functor)
Reverse traversal that finds the first node satisfying the predicate.
void reverse(SgNode *ast, Functor functor)
Traverse an AST in the reverse direction.
void reversePre(SgNode *ast, Functor functor)
Traverse an AST in the reverse with pre-visit only.
The ROSE library.