public interface Lexer {
/*** Consume the next token.*/
void nextToken();
/*** Return current token.*/
Token token();
/*** Return token with given lookahead.*/
Token token(int lookahead);
/*** Return the last character position of the previous token.*/
Token prevToken();
/*** Splits the current token in two and return the first (splitted) token.* For instance {@literal '<<
Token split();
/*** Return the position where a lexical error occurred;*/
int errPos();
/*** Set the position where a lexical error occurred;*/
void errPos(int pos);
/*** Build a map for translating between line numbers and* positions in the input.** @return a LineMap*/
LineMap getLineMap();
}词法分析与语法分析类
解析一个Java文件由JavacParser.parseCompilationUnit()开始,一个合法的java文件同由下面的主要元素组成的:
简单说明一下“[]”里面的内容表示这个内容可以出现0次或是1次;"{}"里面的内容可以出现0次或是多次。所以下面的内容慢慢体会、理解一下就知道什么样是合法的.java文件了。
[{"@" Annotation} package packagename ";"]
{Import}
{ClassType} //这个是广类
所以总体流程是这样的:解析.java文件的主要流程。
这些实现除了“读取各种广类”复杂点之外,这个是我们接下来要讲的重点,其它的都是很直接简单的。
再讲“读取各种广类”这个流程之前,我们先来看看一些基本的类JCTree$JCCompilationUnit:
public static class JCCompilationUnit extends JCTree implements CompilationUnitTree {
/** All definitions in this file (ClassDef, Import, and Skip) */
public List defs;
/** The source file name. */
public JavaFileObject sourcefile;
/** The module to which this compilation unit belongs. */
public ModuleSymbol modle;
/** The location in which this compilation unit was found. */
public Location locn;
/** The package to which this compilation unit belongs. */
public PackageSymbol packge;
/** A scope containing top level classes. */
public WriteableScope toplevelScope;
/** A scope for all named imports. */
public NamedImportScope namedImportScope;
/** A scope for all import-on-demands. */
public StarImportScope starImportScope;
/** Line starting positions, defined only if option -g is set. */
public Position.LineMap lineMap = null;
/** A table that stores all documentation comments indexed by the tree* nodes they refer to. defined only if option -s is set. */
public DocCommentTable docComments = null;
/* An object encapsulating ending positions of source ranges indexed by* the tree nodes they belong to. Defined only if option -Xjcov is set. */
public EndPosTable endPositions = null;
}
这个类里面的字段defs是存放这个文件解析出来的顶级对象有以下几种:
JCTree$JCPackageDecl // 包申明
JCTree$JCImport // import,一条一个,所以有多个。
JCTree$JCClassDecl // 广类申明,可以有多个,但是最多只能有一个是public的。
好了,“读取各种广类”其实就是解析各种类(类,接口,枚举,注解,记录),函数入口在JavacParser.typeDeclaration,然后都是调用JavacParser类里面的函数。流程图如下(点击查看大图):
只画了类的解析,接口、枚举、记录也相似,我倒是建议大概了解一下就行了。这部分又复杂又没有技术含量。目前如果不是性能要求太强或是自己初步写一般都用框架生成。JavaCC或是Antlr都能很好地生成Java语言的解释器。
JavaCC有Java13的解释器描述文件,在这里能找到。
Antlr只找到最新是Java9的,在这里查看。
这个流程走完了,每个文件会生成一个