摘要:請下載一份源代碼,這里有個(gè)對應(yīng)的源碼包元素的組合需要遵守基本的語法規(guī)則不是全部。名字也是表達(dá)式的一種,是指變量名類名包名等元素,它們在中都屬于抽象類,分為和兩種具體類。
另載于 http://www.qingjingjie.com/blogs/3
上篇博客末尾提到了一棵抽象語法樹長什么樣子。JDT提供了一套DOM API來讓我們順利地控制這樣一棵樹。
讀完本篇后請繼續(xù)完成上篇的延伸閱讀:http://help.eclipse.org/ 點(diǎn)擊JDT Plug-in User Guide -> Programmer"s Guide -> JDT Core -> Manipulating Java Code。
各種語法元素用不同的結(jié)點(diǎn)類來表示,一些主要的類有:
CompilationUnit: 編譯單元,相當(dāng)于一個(gè).java文件
AbstractTypeDeclaration: 各種類型的聲明及定義,如類、接口、枚舉、注解。以下幾個(gè)類都繼承自該類
TypeDeclaration: 類或接口
EnumDeclaration: 枚舉類
AnnotationInterfaceDeclaration: 注解,即@interface Xxx {...}
MethodDeclaration: 方法
FieldDeclaration: 域 (成員變量)
Modifier: 修飾符,如public, static, volatile等,也包括注解,如@Override
Block: 代碼塊,也就是花括號(hào){...}所包裹的一段代碼
Statement: 語句,是代碼塊的一部分,也就是以;或}結(jié)尾的一段代碼
Expression: 表達(dá)式,是語句或聲明的一部分, 例如a+b, "seg", a.call(b), ((Number) this)等
其中一些是抽象類,它們會(huì)有一些具體的子類,列舉在抽象類的javadoc中。
結(jié)點(diǎn)之間通過對象引用來連接,舉個(gè)例子,MethodDeclaration主要有這么幾個(gè)屬性:
SimpleName name; //方法名 Listparameters; //方法參數(shù) List modifiers; List typeParameters; //泛型參數(shù) Type returnType; Block body; //方法體 Javadoc javadoc;
為了掌握J(rèn)DT的使用方法,我們需要觀看其javadoc和源代碼,因?yàn)槲臋n太缺乏。這部分源代碼還是挺容易懂的。
請下載一份源代碼,這里有個(gè)Eclipse 4.3.1對應(yīng)的JDT源碼包 http://grepcode.com/snapshot/repository.grepcode.com/java/eclipse.org/4.3.1/org.eclipse.jdt/core/3.9.1
元素的組合需要遵守基本的語法規(guī)則(不是全部)。當(dāng)我們用上篇博客的方式讀入并解析Java代碼時(shí),JDT只會(huì)做詞法分析和語法分析,而不會(huì)做語義分析,因此只能發(fā)現(xiàn)符號(hào)不合法、語句不完整、括號(hào)不匹配之類的簡單錯(cuò)誤,至于變量未聲明、類型不匹配、缺少import、方法未實(shí)現(xiàn)之類的錯(cuò)誤,則不會(huì)發(fā)現(xiàn)。語義分析需要Eclipse workspace的支持,因此需要實(shí)現(xiàn)一個(gè)Eclipse插件,本系列博客不研究這件事;如果費(fèi)點(diǎn)工夫,也是可以自行實(shí)現(xiàn)一定程度的語義分析的,如果有空可以分享一下。
為了更好地理解語法樹結(jié)構(gòu),請讀者運(yùn)行上篇的代碼,解析一個(gè)真實(shí)的.java文件,在debug模式下逐級(jí)展開觀察CompilationUnit的內(nèi)部結(jié)構(gòu)。
然后我們來介紹一些語法概念,方便進(jìn)一步理解:
字面量是表達(dá)式的一種,int, boolean, String的常量(以及null, X.class)在語法上都是字面量(literal)。
名字也是表達(dá)式的一種,是指變量名、類名、包名等元素,它們在JDT中都屬于Name抽象類,分為SimpleName和QualifiedName兩種具體類。SimpleName是不帶"."的標(biāo)識(shí)符,如變量名foo;QualifiedName則是帶有"."的合成名字,如包名java.util.List。QualifiedName是由SimpleName組成的。
根據(jù)Java語法,標(biāo)識(shí)符只能包含字母、數(shù)字、下劃線“_”、美元符號(hào)“$”,且不得以數(shù)字開頭。
從上篇最后的代碼開始,從CompilationUnit出發(fā)跟著對象引用一路走下去,就能分析代碼結(jié)構(gòu)了。但是到了代碼塊一級(jí)就要開始面對數(shù)不清的甚至有嵌套的語句和表達(dá)式了,不得了啊。其實(shí)我們可以使用ASTVisitor來遍歷所有結(jié)點(diǎn),不用自己硬著頭皮一層層去訪問。
像下面的代碼,就自定義了一個(gè)visitor,來遍歷所有的方法調(diào)用,我們把它應(yīng)用到CompilationUnit這棵樹上(也可以應(yīng)用到任意一棵子樹上):
ASTVisitor visitor = new ASTVisitor() { @Override public boolean visit(MethodInvocation mi) { System.out.println(mi); return true; } } compilationUnit.accept(visitor); //應(yīng)用到樹上
這樣它就在這棵樹上走了一圈,碰到合適的結(jié)點(diǎn)就干活。"return true"的作用是告訴visitor繼續(xù)前進(jìn),如果return false,visitor就會(huì)停止前進(jìn)。
再來溜一段復(fù)雜點(diǎn)的代碼,我們把visitor的visit方法改一改:
ASTVisitor visitor = new ASTVisitor() { @Override public boolean visit(MethodInvocation mi) { if (mi.getExpression() instanceof ThisExpression) { mi.setExpression(null); } return true; } } compilationUnit.accept(visitor); System.out.println(compilationUnit.toString());
如果代碼中含有this.doThing()這樣的調(diào)用,處理后重新輸出的代碼會(huì)變成doThing(),this被去掉了。
[本篇待續(xù)]文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/64142.html
摘要:另載于這是一個(gè)關(guān)于抽象語法樹的故事。抽象語法樹是對程序代碼的結(jié)構(gòu)化表示,是對代碼進(jìn)行詞法分析語法分析后得到的產(chǎn)物。 另載于 http://www.qingjingjie.com/blogs/2 這是一個(gè)關(guān)于抽象語法樹(Abstract Syntax Tree, AST)的故事。 抽象語法樹是對程序代碼的結(jié)構(gòu)化表示,是對代碼進(jìn)行詞法分析、語法分析后得到的產(chǎn)物。編譯器要用到它,很多生產(chǎn)力工...
摘要:本文總結(jié)了前端老司機(jī)經(jīng)常問題的一些問題并結(jié)合個(gè)人總結(jié)給出了比較詳盡的答案。網(wǎng)易阿里騰訊校招社招必備知識(shí)點(diǎn)。此外還有網(wǎng)絡(luò)線程,定時(shí)器任務(wù)線程,文件系統(tǒng)處理線程等等。線程核心是引擎。主線程和工作線程之間的通知機(jī)制叫做事件循環(huán)。 showImg(https://segmentfault.com/img/bVbu4aB?w=300&h=208); 本文總結(jié)了前端老司機(jī)經(jīng)常問題的一些問題并結(jié)合個(gè)...
摘要:本文總結(jié)了前端老司機(jī)經(jīng)常問題的一些問題并結(jié)合個(gè)人總結(jié)給出了比較詳盡的答案。網(wǎng)易阿里騰訊校招社招必備知識(shí)點(diǎn)。此外還有網(wǎng)絡(luò)線程,定時(shí)器任務(wù)線程,文件系統(tǒng)處理線程等等。線程核心是引擎。主線程和工作線程之間的通知機(jī)制叫做事件循環(huán)。 showImg(https://segmentfault.com/img/bVbu4aB?w=300&h=208); 本文總結(jié)了前端老司機(jī)經(jīng)常問題的一些問題并結(jié)合個(gè)...
摘要:本文總結(jié)了前端老司機(jī)經(jīng)常問題的一些問題并結(jié)合個(gè)人總結(jié)給出了比較詳盡的答案。網(wǎng)易阿里騰訊校招社招必備知識(shí)點(diǎn)。此外還有網(wǎng)絡(luò)線程,定時(shí)器任務(wù)線程,文件系統(tǒng)處理線程等等。線程核心是引擎。主線程和工作線程之間的通知機(jī)制叫做事件循環(huán)。 showImg(https://segmentfault.com/img/bVbu4aB?w=300&h=208); 本文總結(jié)了前端老司機(jī)經(jīng)常問題的一些問題并結(jié)合個(gè)...
閱讀 2436·2019-08-30 15:52
閱讀 2237·2019-08-30 12:51
閱讀 2833·2019-08-29 18:41
閱讀 2812·2019-08-29 17:04
閱讀 814·2019-08-29 15:11
閱讀 1720·2019-08-28 18:02
閱讀 3603·2019-08-26 10:22
閱讀 2510·2019-08-26 10:12