递归AST访问者


文档摘要

递归AST访问者解决了与专用访问者观察到的局限性。创建相同的程序,该程序搜索并打印函数声明及其参数,但这次我们将使用递归访问者。 递归访问者测试工具的CMakeLists.txt将以与之前类似的方式使用,只有项目名称(图3.20第2行和第15-17行)和源文件名(图3.20第14行)发生了变化: 图3.20: 递归访问者测试工具的CMakeLists.txt文件 工具的主函数与图3.7中定义的’DeclVisitor’主函数类似。 \#include "clang/Tooling/CommonOptionsParser.h" \#include "clang/Tooling/Tooling.h" \#include "llvm/Support/CommandLine.

递归AST访问者解决了与专用访问者观察到的局限性。创建相同的程序,该程序搜索并打印函数声明及其参数,但这次我们将使用递归访问者。

递归访问者测试工具的CMakeLists.txt将以与之前类似的方式使用,只有项目名称(图3.20第2行和第15-17行)和源文件名(图3.20第14行)发生了变化:

图3.20: 递归访问者测试工具的CMakeLists.txt文件

工具的主函数与图3.7中定义的’DeclVisitor’主函数类似。

#include "clang/Tooling/CommonOptionsParser.h" #include
"clang/Tooling/Tooling.h" #include "llvm/Support/CommandLine.h" //
llvm:🆑:extrahelp

#include "FrontendAction.hpp"

namespace llvm:🆑:OptionCategory TestCategory("Test project");
llvm:🆑:extrahelp
CommonHelp(clang::tooling::CommonOptionsParser::HelpMessage); //
namespace

int main(int argc, const char **argv)
llvm::Expected<clang::tooling::CommonOptionsParser> OptionsParser =
clang::tooling::CommonOptionsParser::create(argc, argv, TestCategory);
if (!OptionsParser) llvm::errs() << OptionsParser.takeError(); return
1; clang::tooling::ClangTool Tool(OptionsParser->getCompilations(),
OptionsParser->getSourcePathList()); return
Tool.run(clang::tooling::newFrontendActionFactory<
clangbook::recursivevisitor::FrontendAction>() .get());

图3.21: 递归访问者测试工具的主函数

在第23行只更改了自定义前端动作的命名空间名称。

前端动作和消费者的代码与图3.8和图3.9中的代码相同,唯一的区别是命名空间从declvisitor更改为recursivevisitor。程序中最有趣的部分是,访问者类的实现。

#include "clang/AST/RecursiveASTVisitor.h"

namespace clangbook namespace recursivevisitor class Visitor : public
clang::RecursiveASTVisitor<Visitor> public: bool
VisitFunctionDecl(const clang::FunctionDecl *FD) llvm::outs() <<
"Function: ’" << FD->getName() << "’"; return true; bool
VisitParmVarDecl(const clang::ParmVarDecl *PVD) llvm::outs() << ": ’"
<< PVD->getName() << "’"; return true; ; // namespace
recursivevisitor // namespace clangbook

图3.22: 访问者类的实现

与’DeclVisitor’的代码(见图3.10)相比,有几个变化。首先,递归没有实现,只实现了对我们感兴趣的节点的回调。随之而来的是一个合理的问题:递归是如何控制的?答案在于另一个变化:回调现在返回一个布尔结果。false值表示递归应该停止,而true信号访问者继续遍历。

程序可以使用之前使用的相同的命令序列进行编译。见图3.11。

可以像这样运行程序,见图3.23:

图3.23: 在测试文件上运行递归访问者实用程序的结果

它产生了与使用DeclVisitor实现获得的结果相同的输出。目前为止,考虑的AST遍历方法,并不是进行AST遍历的唯一方法。我们稍后考虑的大多数工具,将使用基于AST匹配器的不同方法。


发布者: 作者: 转发
评论区 (0)
U