java编译器_深入理解Java语言编译器之词法分析与语法分析

编译器都是由词法分析器(lexical analysis)也叫扫描器(Scanner)开始的,OpenJDK中的词法分析器是由接口com.sun.tools.javac.parser.Lexer和其实现类com.sun.tools.javac.parser.Scanner来组成其功能。然后Scanner的主要功能由com.sun.tools.javac.parser.JavaTokenizer来实现。

public 

其实这部分没有什么好讲的,都是根据Java语言规范(The Java Language Specification, Java SE 14 Edition)把源代码扫描解析成com.sun.tools.javac.parser.Tokens$Token,目前一共有112种类型的Token,都在com.sun.tools.javac.parser.Tokens$TokenKind里定义。

Lexer类把源码分解成Token之后,由com.sun.tools.javac.parser.Parser接口的实现类com.sun.tools.javac.parser.JavacParser把Token封装成com.sun.tools.javac.tree.JCTree的子类。这些类的关系如下图所示,中间省略了各种工厂,因为他们对理解程序没有帮助。

37658a006b8c0dd3b2aef824a33d646a.png
词法分析与语法分析类

解析一个Java文件由JavacParser.parseCompilationUnit()开始,一个合法的java文件同由下面的主要元素组成的:

简单说明一下“[]”里面的内容表示这个内容可以出现0次或是1次;"{}"里面的内容可以出现0次或是多次。所以下面的内容慢慢体会、理解一下就知道什么样是合法的.java文件了。

[{"@" Annotation} package packagename ";"] 
{Import}
{ClassType} //这个是广类

所以总体流程是这样的:

71bc27508ac4905ab02404bb9551f7d4.png
解析.java文件的主要流程。

这些实现除了“读取各种广类”复杂点之外,这个是我们接下来要讲的重点,其它的都是很直接简单的。

再讲“读取各种广类”这个流程之前,我们先来看看一些基本的类JCTree$JCCompilationUnit:

public 

这个类里面的字段defs是存放这个文件解析出来的顶级对象有以下几种:

JCTree$JCPackageDecl // 包申明

JCTree$JCImport // import,一条一个,所以有多个。

JCTree$JCClassDecl // 广类申明,可以有多个,但是最多只能有一个是public的。

好了,“读取各种广类”其实就是解析各种类(类,接口,枚举,注解,记录),函数入口在JavacParser.typeDeclaration,然后都是调用JavacParser类里面的函数。流程图如下(点击查看大图):

b7a662337d3d577151be4856224e4897.png

只画了类的解析,接口、枚举、记录也相似,我倒是建议大概了解一下就行了。这部分又复杂又没有技术含量。目前如果不是性能要求太强或是自己初步写一般都用框架生成。JavaCC或是Antlr都能很好地生成Java语言的解释器。

JavaCC有Java13的解释器描述文件,在这里能找到。

Antlr只找到最新是Java9的,在这里查看。

这个流程走完了,每个文件会生成一个

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值