ClickHouse/dbms/Interpreters/InDepthNodeVisitor.h

81 lines
1.9 KiB
C++
Raw Normal View History

#pragma once
2019-02-22 13:33:56 +00:00
#include <typeinfo>
#include <vector>
#include <Common/typeid_cast.h>
#include <Parsers/DumpASTNode.h>
namespace DB
{
/// Visits AST tree in depth, call functions for nodes according to Matcher type data.
2019-02-22 13:33:56 +00:00
/// You need to define Data, visit() and needChildVisit() in Matcher class.
2019-10-21 16:22:54 +00:00
template <typename Matcher, bool _top_to_bottom, typename T = ASTPtr>
class InDepthNodeVisitor
{
public:
using Data = typename Matcher::Data;
2019-10-21 16:22:54 +00:00
InDepthNodeVisitor(Data & data_, std::ostream * ostr_ = nullptr)
: data(data_),
visit_depth(0),
ostr(ostr_)
{}
2019-07-23 19:49:15 +00:00
void visit(T & ast)
{
2019-02-22 13:33:56 +00:00
DumpASTNode dump(*ast, ostr, visit_depth, typeid(Matcher).name());
if constexpr (!_top_to_bottom)
visitChildren(ast);
2019-02-22 13:33:56 +00:00
Matcher::visit(ast, data);
if constexpr (_top_to_bottom)
visitChildren(ast);
}
private:
Data & data;
size_t visit_depth;
std::ostream * ostr;
2019-07-23 19:49:15 +00:00
void visitChildren(T & ast)
{
for (auto & child : ast->children)
if (Matcher::needChildVisit(ast, child))
visit(child);
}
};
2019-07-23 19:49:15 +00:00
template <typename Matcher, bool top_to_bottom>
2019-10-21 16:22:54 +00:00
using ConstInDepthNodeVisitor = InDepthNodeVisitor<Matcher, top_to_bottom, const ASTPtr>;
2019-07-23 19:49:15 +00:00
/// Simple matcher for one node type without complex traversal logic.
2019-10-21 16:22:54 +00:00
template <typename Data_, bool visit_children = true, typename T = ASTPtr>
class OneTypeMatcher
{
public:
2019-10-21 16:22:54 +00:00
using Data = Data_;
using TypeToVisit = typename Data::TypeToVisit;
2019-12-18 03:56:03 +00:00
static bool needChildVisit(const ASTPtr & node, const ASTPtr &)
{
if (node && node->as<TypeToVisit>())
return visit_children;
return true;
}
2019-10-21 16:22:54 +00:00
static void visit(T & ast, Data & data)
{
if (auto * t = typeid_cast<TypeToVisit *>(ast.get()))
data.visit(*t, ast);
}
};
2019-10-21 16:22:54 +00:00
template <typename Data, bool visit_children = true>
using ConstOneTypeMatcher = OneTypeMatcher<Data, visit_children, const ASTPtr>;
}