2018-12-06 15:29:55 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <unordered_set>
|
|
|
|
#include <unordered_map>
|
|
|
|
#include <Parsers/DumpASTNode.h>
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
/// Visits AST tree in depth, call fucntions for nodes according to Matcher type data.
|
|
|
|
/// You need to define Data, label, visit() and needChildVisit() in Matcher class.
|
|
|
|
template <typename Matcher, bool _topToBottom>
|
|
|
|
class InDepthNodeVisitor
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
using Data = typename Matcher::Data;
|
|
|
|
|
|
|
|
InDepthNodeVisitor(Data & data_, std::ostream * ostr_ = nullptr)
|
|
|
|
: data(data_),
|
|
|
|
visit_depth(0),
|
|
|
|
ostr(ostr_)
|
|
|
|
{}
|
|
|
|
|
|
|
|
void visit(ASTPtr & ast)
|
|
|
|
{
|
|
|
|
DumpASTNode dump(*ast, ostr, visit_depth, Matcher::label);
|
|
|
|
|
|
|
|
if constexpr (!_topToBottom)
|
|
|
|
visitChildren(ast);
|
|
|
|
|
2018-12-07 14:24:47 +00:00
|
|
|
/// It operates with ASTPtr * cause we may want to rewrite ASTPtr in visit().
|
|
|
|
std::vector<ASTPtr *> additional_nodes = Matcher::visit(ast, data);
|
|
|
|
|
2018-12-06 15:29:55 +00:00
|
|
|
/// visit additional nodes (ex. only part of children)
|
2018-12-07 14:24:47 +00:00
|
|
|
for (ASTPtr * node : additional_nodes)
|
|
|
|
visit(*node);
|
2018-12-06 15:29:55 +00:00
|
|
|
|
|
|
|
if constexpr (_topToBottom)
|
|
|
|
visitChildren(ast);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2018-12-06 19:02:42 +00:00
|
|
|
Data & data;
|
2018-12-06 15:29:55 +00:00
|
|
|
size_t visit_depth;
|
|
|
|
std::ostream * ostr;
|
|
|
|
|
|
|
|
void visitChildren(ASTPtr & ast)
|
|
|
|
{
|
|
|
|
for (auto & child : ast->children)
|
|
|
|
if (Matcher::needChildVisit(ast, child))
|
|
|
|
visit(child);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|