接下來,讓我們膜拜下大師的代碼。
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()。所有語法解析的核心邏輯就在這幾個方法中