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