10.2 Javac编译器 10.2.2 解析与填充符号表

10.2.2 解析与填充符号表

解析过程由图10-5中的parseFiles()方法(图10-5中的过程1.1)来完成,解析过程包括了经典程序编译原理中的词法分析和语法分析两个步骤。

1.词法、语法分析

词法分析是将源代码的字符流转变为标记(Token)集合的过程,单个字符是程序编写时的最小元素,但标记才是编译时的最小元素。关键字、变量名、字面量、运算符都可以作为标记,如“int a=b+2”这句代码中就包含了6个标记,分别是int、a、=、b、+、2,虽然关键字int由3个字符构成,但是它只是一个独立的标记,不可以再拆分。在Javac的源码中,词法分析过程由com.sun.tools.javac.parser.Scanner类来实现。

语法分析是根据标记序列构造抽象语法树的过程,抽象语法树(Abstract Syntax Tree,AST)是一种用来描述程序代码语法结构的树形表示方式,抽象语法树的每一个节点都代表着程序代码中的一个语法结构(SyntaxConstruct),例如包、类型、修饰符、运算符、接口、返回值甚至连代码注释等都可以是一种特定的语法结构。

图10-6是Eclipse AST View插件分析出来的某段代码的抽象语法树视图,读者可以通过这个插件工具生成的可视化界面对抽象语法树有一个直观的认识。在Javac的源码中,语法分析过程由com.sun.tools.javac.parser.Parser类实现,这个阶段产出的抽象语法树是以com.sun.tools.javac.tree.JCTree 类表示的。

经过词法和语法分析生成语法树以后,编译器就不会再对源码字符流进行操作了,后续的操作都建立在抽象语法树之上。

image-20211125203608681

图10-6 抽象语法树结构视图

2.填充符号表

完成了语法分析和词法分析之后,下一个阶段是对符号表进行填充的过程,也就是图10-5中enterTrees()方法(图10-5中注释的过程1.2)要做的事情。符号表(Symbol Table)是由一组符号地址和符号信息构成的数据结构,读者可以把它类比想象成哈希表中键值对的存储形式(实际上符号表不一定是哈希表实现,可以是有序符号表、树状符号表、栈结构符号表等各种形式)。符号表中所登记的信息在编译的不同阶段都要被用到。譬如在语义分析的过程中,符号表所登记的内容将用于语义检查 (如检查一个名字的使用和原先的声明是否一致)和产生中间代码,在目标代码生成阶段,当对符号名进行地址分配时,符号表是地址分配的直接依据。

在Javac源代码中,填充符号表的过程由com.sun.tools.javac.comp.Enter类实现,该过程的产出物是一个待处理列表,其中包含了每一个编译单元的抽象语法树的顶级节点,以及package-info.java(如果存在的话)的顶级节点。