我正在寻找一种可用于常见命令式语言(Java、C、python、ruby 等)的抽象语法树表示。我希望它尽可能接近源代码(而不是像 LLVM 这样的东西)。我在网上找到了Rose,但它只能处理 C 和 Fortran。这存在吗?
1 回答
您不会找到可以代表多种语言的“一个”通用 AST。人们已经寻找了50年。
本质原因是 AST 节点隐含地表示了它编码的运算符的精确语言语义,而不同的语言对于显然相同的运算符有不同的语义。
例如,现代 Fortran 中的“+”运算符将添加整数、实数、复数值和此类事物的数组切片。Java "+" 将整数、实数和粘合字符串相加。如果我在“通用 AST”中写了“a+b”,你怎么知道对应的 AST 编码的语义效果是什么?
您可以做的是构建一个系统,其中统一表示不同语言的 AST,以便您可以跨多种语言共享工具基础架构。这是由许多程序转换系统 (PTS)完成的,您可以在其中提供语法(或从可用库中选择一个),然后 PTS 使用其统一表示来解析和构建 AST。大多数 PTS 提供额外的支持来分析和转换代码。
所以,你所需要的只是一个 PTS 和一些汗水来定义一个语法。这真的不是真的。为真正的语言找到正确的语法实际上非常困难。更糟糕的是,解析后的生活有很多,因为您需要符号的含义和额外的推断,例如控制和数据流分析。因此,您需要完整的前端(例如,解析、名称/类型解析、流分析……),或者尽可能多的,如果您不想在开始真正的工作前几个月分心的话。
这在实践中意味着你想找到一个工具来处理你感兴趣的语言,并且已经有成熟的前端可用:
- Rose(你已经找到了)处理 C、C++ 和 Fortran。它没有自己的内置解析能力;它的前端是定制的。因此,显然很难扩展到其他语言。但它具有良好的流分析能力,并提供了通过手写 AST walks/smashes 转换代码的方法。
Clang处理 C 和 C++。Clang 还使用手工构建的前端。它还可以通过手写 AST walks/smashes 转换代码,并提供少量模式匹配支持。据我了解,您必须使用 Clang 的 LLVM 部分进行流分析。
我们的DMS 软件再造工具包具有适用于 C、C++、Java 和 COBOL 的完整前端,以及适用于 Python 等更多语言的完整解析器。DMS 提供基于模式的分析和源到源的转换。它直接根据语法进行操作(参见Oberon,Nicklaus Wirth 的最新语言)。(我不知道任何处理 Ruby 的工具,它以难以解析着称;我知道它的语法是模棱两可的,而 DMS 擅长处理模棱两可的语法)。