1 | #pragma once |
2 | |
3 | #include <typeinfo> |
4 | #include <vector> |
5 | #include <Common/typeid_cast.h> |
6 | #include <Parsers/DumpASTNode.h> |
7 | |
8 | namespace DB |
9 | { |
10 | |
11 | /// Visits AST tree in depth, call functions for nodes according to Matcher type data. |
12 | /// You need to define Data, visit() and needChildVisit() in Matcher class. |
13 | template <typename Matcher, bool _top_to_bottom, typename T = ASTPtr> |
14 | class InDepthNodeVisitor |
15 | { |
16 | public: |
17 | using Data = typename Matcher::Data; |
18 | |
19 | InDepthNodeVisitor(Data & data_, std::ostream * ostr_ = nullptr) |
20 | : data(data_), |
21 | visit_depth(0), |
22 | ostr(ostr_) |
23 | {} |
24 | |
25 | void visit(T & ast) |
26 | { |
27 | DumpASTNode dump(*ast, ostr, visit_depth, typeid(Matcher).name()); |
28 | |
29 | if constexpr (!_top_to_bottom) |
30 | visitChildren(ast); |
31 | |
32 | Matcher::visit(ast, data); |
33 | |
34 | if constexpr (_top_to_bottom) |
35 | visitChildren(ast); |
36 | } |
37 | |
38 | private: |
39 | Data & data; |
40 | size_t visit_depth; |
41 | std::ostream * ostr; |
42 | |
43 | void visitChildren(T & ast) |
44 | { |
45 | for (auto & child : ast->children) |
46 | if (Matcher::needChildVisit(ast, child)) |
47 | visit(child); |
48 | } |
49 | }; |
50 | |
51 | template <typename Matcher, bool top_to_bottom> |
52 | using ConstInDepthNodeVisitor = InDepthNodeVisitor<Matcher, top_to_bottom, const ASTPtr>; |
53 | |
54 | /// Simple matcher for one node type without complex traversal logic. |
55 | template <typename Data_, bool visit_children = true, typename T = ASTPtr> |
56 | class OneTypeMatcher |
57 | { |
58 | public: |
59 | using Data = Data_; |
60 | using TypeToVisit = typename Data::TypeToVisit; |
61 | |
62 | static bool needChildVisit(const ASTPtr &, const ASTPtr &) { return visit_children; } |
63 | |
64 | static void visit(T & ast, Data & data) |
65 | { |
66 | if (auto * t = typeid_cast<TypeToVisit *>(ast.get())) |
67 | data.visit(*t, ast); |
68 | } |
69 | }; |
70 | |
71 | template <typename Data, bool visit_children = true> |
72 | using ConstOneTypeMatcher = OneTypeMatcher<Data, visit_children, const ASTPtr>; |
73 | |
74 | } |
75 | |