以编程方式构建c声AST

时间:2018-12-27 14:02:07

标签: c++ llvm-clang

我正在编写一个可以将源语言翻译成C ++的编译器。我为此使用flex,bison和clang-AST。我将从一个空的AST开始,并在解析每个语义动作时,将节点添加到clang-AST中。

问题是我找不到以编程方式构建AST的方法。假设我想为下面的代码生成一个AST而没有RecursiveASTVisitor(因为我的源语​​言不是C ++)

#include <iostream>

int main()
{
  std::cout << "Hello World " << std::endl;

  return 0;
}

因此可以生成AST的相应代码应如下所示

#include "clang/AST/ASTContext.h"

int main(int argc, const char **argv)
{

    //Create an empty context
    clang::ASTContext *context = new clang::ASTContext(NULL, NULL, NULL, NULL, NULL);

    //Declare a main function
    clang::FunctionDecl *FD = clang::FunctionDecl::Create(Context, "main");

    //Declare params
    std::vector<clang::ParmVarDecl*> NewParamInfo;
    NewParamInfo.push_back(clang::ParmVarDecl::Create(Context, FD, "argc"));
    NewParamInfo.push_back(clang::ParmVarDecl::Create(Context, FD, "argv"));

    //set params to function
    FD->setParams(ArrayRef<clang::ParmVarDecl*>(NewParamInfo));

    //Declare a compund stament
    clang::CompoundStmt *CS = new (Context) clang::CompoundStmt(clang::SourceLocation());

    //Declare a Statement to print
    clang::Stmt *S = new (Context) clang::ReturnStmt("std::cout << \"Hello World \" << std::endl;");

    //Add print statement to compund statement
    CS->setStmts(Context, S, 1);

    //Add compund statement to body of function
    FD->setBody(CS);

    return 0;
}

上面提到的代码不是有效的代码,查看llvm或clang的文档是否是PITA,有人可以帮助我完成谁的类似工作吗?

1 个答案:

答案 0 :(得分:0)

  • 像 clang 一样从头开始编写 clang 的 AST,不是使用 API,而是使用其内部函数;可以想象,您可以走那条路,但会在您将使用的非公共非 API 函数中遭受流失。目前尚不清楚您的预期目的是否需要 AST 创作函数的最前沿,而 clang 本身在开发 C++20 和 C++2b 及更高版本时需要这些函数。
  • 但是还有重构 API,如 Clang: write a function's AST from original file to a new file 中所述,但您的预期目的并不是重构本身,但是您可以稍微扭曲一下您的想法,以利用 clang 中相对稳定的重构 API 来构建将您寻求从无到有/从头开始“重构”的 AST。

也有许多评论者嘲笑将 clang 的 AST 用作数据结构。他们会避免使用 clang 的 AST 来“发出源代码”,但要发出非平凡的源代码,必须重新发明自己的 AST。为什么要重新发明 C++-AST 轮子?只需通过重构 API 构建 clang 的 AST,而不是从头开始设计您自己的 AST。然后作为您对预期转译的所有“重构”完成后的最后一步,通过访问者遍历从 clang AST 读取生成的 C++ 源代码。