我对如何创建javacc解释器非常困惑,特别是如何从之前生成的AST树构建符号表。
这样的东西,从这个AST:
> Program
> Id
> Id
> Id
> VarDecl
> Type
> Id
> Stl
> Id
> NewInt
> IntLit
> Sta
> Id
> IntLit
> ParseArgs
> Id
> IntLit
> Sta
> Id
> IntLit
> ParseArgs
> Id
> IntLit
(…)
到此表
=== Symbol table ===
Name Type Init Values
---- ---- ---- ------
args args[] true 2 12 8
x int[] true 2 4 0
以此输入为例
class gcd {
public static void main(String[] args) {
int[] x;
x = new int[2];
x[0] = Integer.parseInt(args[0]);
x[1] = Integer.parseInt(args[1]);
if (x[0] == 0)
System.out.println(x[1]);
else
while (x[1] > 0) {
if (x[0] > x[1])
x[0] = x[0] - x[1];
else
x[1] = x[1] - x[0];
}
System.out.println(x[0]);
}
}
我现在拥有的只是创造了AST。
我的主要问题是如何定义然后逐一比较树上的类型。
任何帮助都会很棒,包括理论。
感谢。
答案 0 :(得分:3)
简单的答案是“走树,建立符号表”。
当您递归 down 树时,您将遇到范围构造;为遇到的每个这样的节点构建一个范围,并推送到范围堆栈的顶部。当您访问该节点的声明子节点时引入了一个作用域,在作用域堆栈顶部的作用域中插入声明的定义。当您从引入范围的节点返回时,弹出范围堆栈。 Voila:词汇范围语言的符号表。所有这些都独立于JavaCC,在编译器书籍中得到了很好的解释。建议你拿一个并仔细阅读。
使用命名空间的语言并不容易,但可以加入到这种结构中。有些语言在范围之间具有更复杂的关系,而这并不容易。
现在,要为Java做这个...类型系统的细节是复杂而神秘的,并且知道类型的语法意味着什么的复杂性非常复杂,尤其是。模板类型。没有编译器书可以帮助你;如果构建自己的符号表,则需要解释Java参考手册。期待这很困难;这是为了其他所有人。
当您遇到软件包引用时,您会发现其中一个“不那么容易嵌套”的范围问题;要解析包含包引用的模块的名称,首先必须找到引用包的源文件或类文件,并为 构建符号表。这实际上意味着在为一个文件构建符号表的过程中,您可能必须进入文件系统,解析文件[作为文本或类]并在继续之前构建符号表。
结论:对于符号表构建器,Java充满了不便之处。
(我构建了程序分析工具。我们花了几天时间才能将所有各种Java方言都解析为解析,部分原因是我们拥有非常好的解析机制;我们花了几个月的时间来构建一个通过Java 1.7编写适当的符号表,我们正在研究Java 1.8)。
如果您确实想要使用AST和符号表,那么获得/使用其他人的解析器/名称类型解析器要好得多。想到JDT AST机器。我公司也在这个领域提供工具。