java编译器源码解析-语法分析(1)
接下来,让我们膜拜下大师的代码。
JavacParser.parseCompilationUnit()是java语法分析的入口方法。
parseCompilationUnit()的返回结果是一个JCTree.JCCompilationUnit,说的更直白一点就是一颗抽象语法树AST。
一、抽象语法树
借用一张图来说明JCTree以及子类的构成。
注意:每个Tree节点都有一个对应的sym属性
当然这还不是全部,但已经可以初步看出AST的基本构成。
它的子类包括我们耳熟能详的类声明、变量声明和其他if/while/for语句一样继承于JCStatement类。
方法声明节点、标识符声明节点、表达式节点都直接继承JCTree。
一元表达式、二元表达式等继承于表达式节点JCExpression类。
下面是JCTree及其主要子类的类图
既然是一棵树,那么肯定要进行变量,JCTree中专门实现了一个内部抽象类Visitor来支持对各个节点的访问。这就用到了访问者模式。
Visitor支持的方法如下:
二、语法分析
继续parseCompilationUnit()的分析,代码很多,但核心的方法是typeDeclaration(),顾名思义是做类型定义的解析。
进入新的方法,发现类型可以分为三种classOrInterfaceOrEnumDeclaration():
类解析、接口解析和枚举类解析。
分别对应三个方法,返回值都是JCClassDecl:
JCClassDecl classDeclaration()
JCClassDecl interfaceDeclaration()
JCClassDecl enumDeclaration()
相对而言,接口和枚举类要比类更简单,因此我们直接去查看类定义解析的内容。
类解析从解析类的泛型参数开始,具体内容在typeParametersOpt()中。
如果有extend或者implement就会去解析父类和接口。这里的逻辑不复杂,我们就不展开了。
类的body是比较复杂的,源码中专门写了一个方法classOrInterfaceBody()实现它。
classOrInterfaceBody具体实现classOrInterfaceBodyDeclaration方法中。
类的定义中可以继续定义类,所以
1.首先判断是不是内部类
2.然后如果是一个“{”,那就进行block的解析
3.最后就是变量的声明variableDeclaratorsRest()和方法的声明methodDeclaratorRest()
三、变量声明
变量声明的解析又分普通变量的声明和array的声明,是区分对待的。
不可避免的,变量声明的右边是一个表达式parseExpression()
四、方法定义
methodDeclaratorRest()
方法定义首先解析方法的参数params,之后今日block()方法。
block()由一系列blockStatements()组成。进而调用blockStatement(),blockStatement()有多种语句,比如:
parseStatement()解析一般的Statement
variableDeclarators()解析变量声明
再加上解析表达式的parseExpression()。所有语法解析的核心逻辑就在这几个方法中