访问 C++ 源文件的标记化

Accessing tokenization of a C++ source file

我的理解是,程序编译的一个步骤(我想与语言无关)是将源文件解析为某种 space 分隔的标记(这种标记化将由在 this answer 中称为 scanner。例如,我了解到在编译过程中的某个时刻,包含 x += fun(nullptr); 的行被分隔为 [=23] =]

这是真的吗?如果是这样,有没有办法访问 C++ 源代码的这种标记化?

我问这个问题主要是出于好奇,我确实打算自己写一个词法分析器

我很好奇是否可以利用编译器的原因是,举个例子,在遇到 [[noreturn]] & Co. 之前,我从来没有考虑过 [[ 作为一个有效的令牌,如果我自己写一个词法分析器。

我们是否一定需要真实的实际用例?我想我们不会,如果我想知道是否有现成的工具来做某事。

但是,如果我们真的需要一个用例,

假设我的目标是编写一个 C++ 函数,该函数读取 C++ 源文件和 returns 它所组成的词素的 std::vector。显然,一个要求是连接输出的元素应该再次组成整个文本,包括换行符和它的每个其他字节。

C++ 是一种非常复杂的编程语言。

在尝试解析 C++ 代码之前,请务必阅读 C++11 标准草案 n3337

查看现有开源C++编译器的源代码,比如GCC (at least GCC 10 in October 2020) or Clang (at least Clang 102020年10月)

如果您必须从头开始编写 C++ 解析器,请确保至少有一个人一年的工作预算。

另请查看 现有的 C++ 静态源代码分析器,例如 Frama-C++ or Clang static analyzer. Consider adapting one of them to your needs, but do document in writing your needs before starting coding. Be aware of Rice's theorem.

如果您想解析 C++ 的 小子集 (您需要记录并指定该子集),请考虑使用像 ANTLR or GNU bison 这样的解析器生成器。

大多数编译器都在构建一些内部表示,特别是一些抽象语法树。阅读 Dragon book 了解更多。

我建议您自己编写 GCC plugin

确实,它会与 GCC 的某些主要版本相关联,但您将赢得数月的工作。

Is this true? If so, is there a way to have access to this tokenization of a C++ source code?

是的,通过修补一些 现有的 开源 C++ 编译器,或使用您的插件扩展它(两种方法都有相关的许可条件)。

let's say my target is to write a C++ function which reads in a C++ source file and returns a std::vector of the lexemes it's made up of.

以上说明有歧义。

你想要 C++ 预处理阶段之前还是之后的词位? 换句话说,例如,什么是词位? __DATE__ 还是 __TIME__?阅读例如GNU cpp ... If you happen to use GCC on Linux (see gcc(1)) and have some C++ translation unit foo.cc, try running g++ -C -E -Wall foo.cc > foo.ii and look (using less(1)...) into the generated preprocessed form foo.ii ? And what about template expansion, or preprocessor conditionals or preprocessor stringizing ?

的文档

我建议您编写 GCC 插件来处理 GENERIC 表示。你也可以开始与你的目标相关的博士工作。

请注意,生成 C++ 代码比解析它容易得多。

查看内部 Qt for an example of software generating C++ code. Yo could consider using GNU m4, or GNU gawk, or GNU autoconf, or GPP, or your own C++ source generator (perhaps with the help of GNU bison or of ANTLR) 以生成一些 C++ 代码。

PS。在我的主页上,您会找到一个指向与您的问题相关的报告草稿的超链接,以及另一个指向生成 C++ 代码的开源程序的超链接。遗憾的是,我在这里似乎被禁止提供这些超链接,但您可以通过单击两次鼠标找到它们。您还可以查看资助该报告草案的两个欧洲 H2020 项目:CHARIOT & DECODER.

由于评论中提到的限制(标记化保持 __DATE__),它似乎更易于管理。您需要预处理令牌。 Boost::Wave 预处理器必须创建一个标记列表,因为它必须处理这些标记。

Basile 正确地指出很难为这些标记赋予意义。