代码如何在抽象语法树中表示?

时间:2014-05-24 16:50:08

标签: abstract-syntax-tree

我正在研究我的自定义gcc前端,并且关于AST结构的问题很少但尚未解答。

在将程序代码解析为AST的上下文中,AST是树还是森林?

如何在AST中出现这样的简单示例? 假设我们有一个var声明,一个函数声明和一个带有几个赋值的main函数。这只是一个例子。

会是这样的吗?

                  root

       /           |           \
      /            |            \
    var           func         main
   / | \       /   |   \       /   \
 int x  5    args foo  int   asgn asgn
             / \             / \   /  \
           var var          a   x x    2 
           ... ...

所以,如果我以中缀顺序读取树,我会得到实际的代码序列吗?

更新

2 个答案:

答案 0 :(得分:2)

通常,无论您如何重新排列,“AST”都不包含“实际代码序列”。这就是为什么它被称为“抽象”:细节已被删除。它包含足够的信息来表示程序文本所说的内容。

具体的语法树可以说包含足够的信息来重新生成源;它需要花费足够的时间来重新生成原始程序,特别是如果你需要文字格式信息,如数字基数和分数后的尾随零数。

是否存储信息以便按顺序访问,预订或后序,或者每个节点不同,这是实施的问题。 (大多数AST和CST树在顺序遍历时倾向于匹配程序文本顺序。)

[EDIT 7/3/2014回答关于“单树与森林”的问题]

作为一般规则,人们希望将单个源文件解析为单个AST。然而,真正的程序有很多有趣的复杂功能;例如,C中的#include语句引用另一个文件(抽象地扩展到位),Java中的包引用引用另一个文件。因此,如果单个源文件引用了许多其他源文件,并且解析了单个源文件,那么是否应该为单个源文件生成一个AST,而其他文件没有AST?

这个问题的答案取决于您正在构建的工具的性质。 C编译器扩展#include,解析C文件往往会产生一个 AST。 Java编译器不会扩展包引用,但可能需要解析包源文件以了解它包含的内容;在这种情况下,您倾向于获得一个AST,一个用于“主”程序,一个用于它引用的每个包,一个用于它们引用的每个(唯一)包等。如果您的工具没有编译,但是想要修改C源代码,你可能不希望在适当的位置扩展#include,因此这样的工具将有一个主C程序的源文件,并且每个#include遇到一个。因此,根据您的目的,您的(复杂)解析器可能只生成一个AST或一个集合(通常称为“森林”)。

答案 1 :(得分:1)

您可以通过一个有用的Eclipse插件消除任何疑问,该插件允许您从代码中的任何位置查看ast: - 安装插件 - 在源代码中的任何位置创建位置(cusror) - 进入" Ast视图" - 点击"层次结构"按钮的视图 - 查看完整的Ast

来自谷歌查询搜索的插件链接" eclipse插件ast视图" P.s。:不是森林,而是树#34;

再见

相关问题