C++代码与AST compiler

C++代码与AST compiler

Compiler3_语法制导翻译&AST

语法制导翻译(Syntax Directed Translation)的任务

解析输入的字符串时,在特定位置执行指定的动作。

基本思想

 

 

 抽象语法树

分析树与抽象语法树

 

 

 分析树:

  • 编码了句子的推导过程
  • 但是包含很多不必要的信息,节点占用存储空间
  • 需要知道那些信息是重要的
    • 对于表达式而言,只需要知道运算符和运算数
      • 优先级,结合性等已经在语法分析部分处理掉了
    • 对于语句,函数等其他构造而言也一样
      • 比如,编译器不关心赋值符号是=还是:=

具体语法和抽象语法

  • 具体语法是语法分析器使用的语法
  • 抽象语法是用来表达语法结构的内部表示
  • 早期的编译器有的不采用抽象语法树数据结构
  • 现代编译器一般都采用抽象语法树作为语法分析器的输出
    • 必须适合于语法分析,如各种分隔符,消除左递归,提取公因子等
    • 现代编译器一般采用抽象语法作为前端(词法/语法分析器)和后端(代码生成)的接口
    • 直接在语法制导翻译中生成代码
    • 更好的系统的支持
    • 简化编译器的设计

抽象语法树的自动生成

  • 在语法动作中,加入生成语法树的代码片段
    • 片段一般是语法树的构造函数
  • 在产生式规约的时候,会自底向上构造整棵数
    • 从叶子到根

 

  • 抽象语法树是编译器前端和后端的接口
    • 程序一旦被转换成抽象语法树,则源代码即被丢弃
    • 后续阶段只处理抽象语法树
  • 所以抽象语法树必须编码足够多的源代码信息
    • 例如,语法结构所在位置(文件、行号、列号等)

觉得自动生成方面LL比LR好,自顶向下更符合人类认知,代表生成器:antlr

Cppinsights: C++的见解——用编译器的眼睛查看源代码

Contents

  • What
  • Why
  • Building
  • Usage
  • Get Involved
  • Support

What

C++见解是一种基于CLAN的工具,它可以进行源到源转换。它的目标是让事情变得可见,而这些事情通常是故意发生在幕后的。它是关于编译器为我们所做的神奇的事情。

以这段代码为例:

class Base {

};

 

class Derived : public Base {

};

 

int main() {

  Derived d;

  Base& b = d;

}

没什么特别的,当然是编译的。下面是编译器的视图:

class Base {

/* public: inline constexpr Base() noexcept; */

/* public: inline ~Base(); */

/* public: inline constexpr Base(const Base &); */

/* public: inline constexpr Base(Base &&); */

};

 

class Derived : public Base {

/* public: inline constexpr Derived() noexcept; */

/* public: inline constexpr Derived(const Derived &); */

/* public: inline constexpr Derived(Derived &&); */

};

 

int main(){

  Derived d;

  Base& b = static_cast<Base&>(d);

}

您可以看到编译器提供的所有函数。还有从Derived到Base的向下转换。

我并不是说所有的事情都是对的。这只是我认为足够好的见解的初始版本,可以将其交给公众。请记住,这完全是基于clang及其对AST的理解。

Why

C++见解是一种基于CLAN的工具,它可以进行源到源转换。它的目标是让人们看到那些通常是故意发生在幕后的事情。它是关于编译器为我们所做的神奇的事情。或者查看编译器的类。

不久前,我开始研究一些新的东西,我们用C++ 11,C++ 14和C++ 17得到。像lambdas、range-basedfor-loops和结构化绑定之类的惊人功能。我把它放在一个谈话中。你可以在网上找到幻灯片和视频。

然而,所有的研究和我的一些训练和教学让我开始思考,如果我们能用编译器的眼睛看的话。当然,对于clang至少有一个AST-dump。使用编译器编译器这样的工具,我们可以看到编译器从C++源代码段生成的代码。然而,我们看到的是汇编程序。AST和Compiler Explorer输出都不是我编写代码的语言,因此我最熟悉。另外,当教学生C++显示AST并解释它在那里时,对我来说并不十分令人满意。

我开始编写一个clang-based工具,能够将range-basedfor-loop转换为compiler-internal版本。然后,我对结构化绑定和lambdas做了同样的处理。最后,我按照最初的计划做了很多事情。它显示了调用运算符的位置,以及编译器执行强制转换的位置。C++的见解能够推断出auto或decltype后面的类型。目标是生成可编译的代码。然而,并非所有地方都能做到这一点。

不过,还有工作要做。

我并不是说所有的事情都是对的。这只是C++的见解的最初版本,我认为它足够好,可以将它交给公众。此外,请记住,它是完全基于CLAN和我的理解C++和AST。

例如,您可以看到lamda、range-basedfor-loop或auto的转换。当然,您可以转换任何其他C++片段。

看到你自己,C++的见解是在线可获得的:cppinsights.io公司.

Building

C++的洞察力可以在clang-source树或外部构建。

在Windows上构建

See Readme_Windows.md

在Arch Linux上构建

要使用extra/clang生成,请使用以下额外的标志:-DINSIGHTS_USE_SYSTEM_INCLUDES=off -DCLANG_LINK_CLANG_DYLIB=on -DLLVM_LINK_LLVM_DYLIB=on

关于INSIGHTS_USE_SYSTEM_INCLUDES需要关闭的解释,请参见https://github.com/andreasfertig/cppinsights/issues/186。

extra/clang和extra/llvm提供/usr/lib/{libclangAST.so,libLLVM*.a,libLLVM.so}。libclangAST.so需要libLLVM.so,如果libLLVM*.a(而不是libLLVM.so)链接,则会发生冲突。见https://bugs.archlinux.org/task/60512

外面的建筑叮当作响

需要在搜索路径中安装clang。

git clone https://github.com/andreasfertig/cppinsights.git

mkdir build && cd build

cmake -G"Ninja" ../cppinsights

ninja

生成的二进制文件(insights)可以在build-folder中找到。

建筑内部叮当作响

对于在clang-source树中构建它,假设您已经准备好了source-tree:

cd llvm/tools/clang/tools/extra

git clone https://github.com/andreasfertig/cppinsights.git

echo "add_subdirectory(cppinsights)" >> CMakeLists.txt

然后像平常一样发出叮当声。

cmake options

有几个选项可以通过cmake启用:

Option

Description

Default

INSIGHTS_STRIP

构建后剥离细节

ON

INSIGHTS_STATIC

使用静态链接

OFF

INSIGHTS_COVERAGE

启用代码覆盖率

OFF

INSIGHTS_USE_LIBCPP

使用libc++进行测试

OFF

DEBUG

Enable debug

OFF

与Ceevelop一起使用

git clone https://github.com/andreasfertig/cppinsights.git

mkdir build_eclipse

cd build_eclipse

cmake -G"Eclipse CDT4 - Unix Makefiles" ../cppinsights/

然后在cedevelopimport->General->Existing Project into Workspace。选择build_eclipse。享受与Cevelop编辑。

Usage

使用C++的见解相当简单:

insights <YOUR_CPP_FILE> -- -std=c++17

当涉及到系统包括路径时,事情变得复杂起来。二进制中有路径hard-coded,似乎来自编译器C++的见解。来帮助你完成检查脚本/getinclude.py. 它尝试从编译器收集系统包含路径。如果没有使用g++的选项,也可以将另一个编译器作为第一个参数传递。

下面是一个例子:

./scripts/getinclude.py

-isystem/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1 -isystem/usr/local/include -isystem/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/7.3.0/include -isystem/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include -isystem/usr/include

该脚本可以与C++的见解一起使用:

insights <YOUR_CPP_FILE> -- -std=c++17 `./scripts/getinclude.py`

还有一个GITHUB项目,它设置了一个docker容器,其中包含了最新的C++透视版:C++见解-Docker。

Compatibility

目前,支持clang的最新稳定版本以及当前的开发分支。

ToDo's

See TODO.

Get Involved

  • 通过提交GitHub问题来报告错误/问题。
  • 使用拉取请求提交稿件。

 

参考文献了解

https://www.kirito.info/compiler3-syntax-directed-translation-and-ast/

https://www.5axxw.com/wiki/content/bp9kmi

posted @ 2023-01-17 04:21  吴建明wujianming  阅读(213)  评论(0编辑  收藏  举报