compiler-construction - JavaCC 解释器(AST 到符号表)

标签 compiler-construction abstract-syntax-tree javacc semantic-analysis symbol-table

我对如何创建 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。

我的大问题是如何定义然后一一比较树上的类型。

任何帮助都会很棒,包括理论。

谢谢。

最佳答案

简单的答案是“遍历树,构建符号表”。

当您沿着树向下递归时,您将遇到作用域构造;为遇到的每个此类节点构建一个作用域,并将其插入作用域堆栈的顶部。当您访问引入该作用域的节点的声明子级时,将声明的定义插入作用域堆栈顶部的作用域中。当您从引入作用域的节点返回时,弹出作用域堆栈。瞧:词法范围语言的符号表。所有这些都独立于 JavaCC,并且在编译器书籍中得到了很好的解释;建议你买一本并仔细阅读。

具有命名空间的语言并不那么容易,但可以硬塞到这个结构中。有些语言的作用域之间的关系更为复杂,而这并不那么容易。

现在,要为 Java 执行此操作...类型系统的细节既复杂又神秘,并且了解类型语法含义的复杂性出人意料地复杂,尤其是。与模板化类型。没有任何编译器书籍可以在这方面为您提供帮助;如果您构建自己的符号表,则需要解释 Java 引用手册。预计这会相当困难;这是为了其他人。

当您遇到包引用时,您会发现其中一个“不太容易嵌套”的范围问题;要解析包含包引用的模块的名称,您首先必须找到引用的包的源文件或类文件,并为其构建符号表。这实际上意味着在为一个文件构建符号表的过程中,您可能必须进入文件系统,解析文件[作为文本或类]并为其构建符号表,然后再继续。

底线:对于符号表构建者来说,Java 充满了令人不便的意外。

(我构建程序分析工具。我们只花了几天时间就可以解析所有各种 Java 方言,部分原因是我们拥有非常好的解析机制;我们花了几个月的时间来构建一个适当的符号表一直到 Java 1.7,我们正在开发 Java 1.8)。

如果您确实想使用 AST 和符号表,那么最好获取/使用其他人的解析器/名称类型解析器。我想到了 JDT AST 机械。我的公司也在这个领域提供了一个工具。

关于compiler-construction - JavaCC 解释器(AST 到符号表),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23857356/

相关文章:

C++结构重新定义编译器错误

c++ - Antlr4 在堆上分配 ParseTree

java - javacc有java1.8.jj吗?

java - 使用可为空/可选标记时进入下一个循环迭代

c - 是否有正则表达式为某种编程语言生成所有整数

c++ - C++中多重继承对象的内存布局

c++ - 链接器如何处理具有不同链接的变量?

ruby - 树顶语法无限循环

ANTLR 的 Java 树解析器输出

java - 如何根据 JavaCC 中的解析异常创建特定的错误消息