抽象語法樹AST的全面解析(二)

JCTree類(com.sun.tools.javac.tree.JCTree)的簡要分析

上一篇文章
講解了抽象語法樹的來源和獲取時機,接下來要分析一下抽象語法樹的內部結構。

抽象語法樹由JCTree的內部類(如JCCompilationUnit,JCClassDecl,JCMethodDecl等)作為語法節點構成。我們可以通過調用JCTree的accept()方法來訪問抽象語法樹的所有語法節點。

public abstract void accept(JCTree.Visitor var1);

accept()方法接收一個JCTree.Visitor的參數,通過執行這個方法,我們可以在Visitor類中獲取到抽象語法樹所有語法節點的數據。

Visitor
  • 抽象內部類,內部定義了訪問各種語法節點的方法,獲取到對應的語法節點后我們可以對語法節點增加刪除或者修改語句;
  • Visitor派生子類有TreeScanner(掃描所有的語法節點)和TreeTranslator(掃描節點且可以把語法節點轉換成另一種語法節點);
public abstract static class Visitor {

        //訪問類節點
        public void visitClassDef(JCTree.JCClassDecl var1) {
            this.visitTree(var1);
        }

        //訪問方法節點
        public void visitMethodDef(JCTree.JCMethodDecl var1) {
            this.visitTree(var1);
        }

        //訪問變量節點
        public void visitVarDef(JCTree.JCVariableDecl var1) {
            this.visitTree(var1);
        }

        //訪問skip節點
        public void visitSkip(JCTree.JCSkip var1) {
            this.visitTree(var1);
        }

        //訪問代碼塊節點
        public void visitBlock(JCTree.JCBlock var1) {
            this.visitTree(var1);
        }

        //訪問doWhild循環
        public void visitDoLoop(JCTree.JCDoWhileLoop var1) {
            this.visitTree(var1);
        }

        //訪問whild循環
        public void visitWhileLoop(JCTree.JCWhileLoop var1) {
            this.visitTree(var1);
        }

        //訪問for循環
        public void visitForLoop(JCTree.JCForLoop var1) {
            this.visitTree(var1);
        }

        //訪問forEach循環
        public void visitForeachLoop(JCTree.JCEnhancedForLoop var1) {
            this.visitTree(var1);
        }

        //訪問switch
        public void visitSwitch(JCTree.JCSwitch var1) {
            this.visitTree(var1);
        }

        //訪問case
        public void visitCase(JCTree.JCCase var1) {
            this.visitTree(var1);
        }

        //訪問同步關鍵字
        public void visitSynchronized(JCTree.JCSynchronized var1) {
            this.visitTree(var1);
        }

        //訪問try
        public void visitTry(JCTree.JCTry var1) {
            this.visitTree(var1);
        }

        //訪問catch
        public void visitCatch(JCTree.JCCatch var1) {
            this.visitTree(var1);
        }

        //訪問三目運算符表達式
        public void visitConditional(JCTree.JCConditional var1) {
            this.visitTree(var1);
        }

        //訪問if語句
        public void visitIf(JCTree.JCIf var1) {
            this.visitTree(var1);
        }

        //訪問break語句
        public void visitBreak(JCTree.JCBreak var1) {
            this.visitTree(var1);
        }

        //訪問continue語句
        public void visitContinue(JCTree.JCContinue var1) {
            this.visitTree(var1);
        }

        //訪問return語句
        public void visitReturn(JCTree.JCReturn var1) {
            this.visitTree(var1);
        }

        //訪問異常拋出表達式節點
        public void visitThrow(JCTree.JCThrow var1) {
            this.visitTree(var1);
        }

        //訪問方法調用節點
        public void visitApply(JCTree.JCMethodInvocation var1) {
            this.visitTree(var1);
        }

        //訪問new對象語句節點
        public void visitNewClass(JCTree.JCNewClass var1) {
            this.visitTree(var1);
        }

        //訪問new數組語句節點
        public void visitNewArray(JCTree.JCNewArray var1) {
            this.visitTree(var1);
        }

        //訪問賦值語句節點
        public void visitAssign(JCTree.JCAssign var1) {
            this.visitTree(var1);
        }

        //訪問賦值操作語句節點
        public void visitAssignop(JCTree.JCAssignOp var1) {
            this.visitTree(var1);
        }

        //訪問賦值操作語句節點
        public void visitUnary(JCTree.JCUnary var1) {
            this.visitTree(var1);
        }

        //訪問一元運算節點
        public void visitBinary(JCTree.JCBinary var1) {
            this.visitTree(var1);
        }

        //訪問對其他類的方法調用或者變量調用節點
        public void visitSelect(JCTree.JCFieldAccess var1) {
            this.visitTree(var1);
        }

        //訪問標識符
        public void visitIdent(JCTree.JCIdent var1) {
            this.visitTree(var1);
        }

        //訪問字面量,可以是數字1,字符串"x"
        public void visitLiteral(JCTree.JCLiteral var1) {
            this.visitTree(var1);
        }

        //獲取訪問修飾符
        public void visitModifiers(JCTree.JCModifiers var1) {
            this.visitTree(var1);
        }
    }
JCStatement

聲明語句,繼承JCStatement都是聲明語句,子類有:
JCBlock、JCReturn、JCClassDecl、JCVariableDecl、JCTry、JCThrow等;

JCExpression

表達式語句,繼承JCExpression都是表達式語句,子類有:
JCAssign,JCBinary,JCBreak,JCFieldAccess,JCIdent,JCLiteral等;

JCClassDecl

類定義

public static class JCClassDecl extends JCTree.JCStatement implements ClassTree {
        public JCTree.JCModifiers mods;//訪問修飾符 比如public, final
        public Name name;//類名
        public List<JCTree.JCTypeParameter> typarams;//泛型參數列表
        public JCTree.JCExpression extending;//父類
        public List<JCTree.JCExpression> implementing;//接口列表
        public List<JCTree> defs;//變量,方法定義列表
        public ClassSymbol sym;//包名+類名
}
JCMethodDecl

方法定義

public static class JCMethodDecl extends JCTree implements MethodTree {
        public JCTree.JCModifiers mods;//訪問修飾符 比如public, final,static
        public Name name;//方法名
        public JCTree.JCExpression restype;//返回類型
        public List<JCTree.JCTypeParameter> typarams;//泛型參數列表
        public JCTree.JCVariableDecl recvparam;//null
        public List<JCTree.JCVariableDecl> params;//方法參數列表
        public List<JCTree.JCExpression> thrown;//異常拋出列表
        public JCTree.JCBlock body;//方法體
        public JCTree.JCExpression defaultValue;//注解類的方法需要的defaultValue
        public MethodSymbol sym;//方法名+ (參數類型),如:setName(java.lang.String)
}
JCVariableDecl

變量定義

public static class JCVariableDecl extends JCTree.JCStatement implements VariableTree {
        public JCTree.JCModifiers mods;//訪問修飾符 比如public, final,static
        public Name name;//變量名
        public JCTree.JCExpression nameexpr;//null
        public JCTree.JCExpression vartype;//變量的類型
        public JCTree.JCExpression init;//初始化值
        public VarSymbol sym;//變量名
}

-->創建變量: private x = 1;
treeMaker.VarDef(treeMaker.Modifiers(Flags.PRIVATE), names.fromString"x", treeMaker.TypeIdent(TypeTag.INT),  treeMaker.Literal(1));
JCModifiers

訪問修飾符

public static class JCModifiers extends JCTree implements ModifiersTree {
        public long flags;//訪問標志,例如:public,private,static
        public List<JCTree.JCAnnotation> annotations;//注解列表
}

-->flag通常用Flags(com.sun.tools.javac.code.Flags)類的常量來表示
public class Flags {
    public static final int PUBLIC = 1;
    public static final int PRIVATE = 2;
    public static final int PROTECTED = 4;
    public static final int STATIC = 8;
    public static final int FINAL = 16;
    public static final int SYNCHRONIZED = 32;
    public static final int VOLATILE = 64;
    public static final int TRANSIENT = 128;
    public static final int NATIVE = 256;

    ...
}

-->創建例子:public
treeMaker.Modifiers(Flags.PUBLIC);
JCBlock

代碼塊

public static class JCBlock extends JCTree.JCStatement implements BlockTree {
        public long flags;//訪問修復符
        public List<JCTree.JCStatement> stats;//多行代碼列表
}

-->使用例子:
List<JCTree.JCStatement> jcStatementList = List.nil();
treeMaker.Block(0, jcStatementList);//構建代碼塊
JCIdent

標識符表達式,可以表示類、變量引用或者方法。

public static class JCIdent extends JCTree.JCExpression implements IdentifierTree {
        public Name name;//標識符的名字
        public Symbol sym;//代表類時為包名+類名,代表其他類型數據時為null

        protected JCIdent(Name var1, Symbol var2) {
            this.name = var1;
            this.sym = var2;
        }
}

-->創建實例: 獲取變量textView的引用
treeMaker.Ident(names.fromString("textView"))))
JCFieldAccess

其他類的變量、方法的訪問表達式

public static class JCFieldAccess extends JCTree.JCExpression implements MemberSelectTree {
        public JCTree.JCExpression selected;//類訪問表達式
        public Name name;//變量名或方法名
        public Symbol sym;
}
JCLiteral

字面量表達式

public static class JCLiteral extends JCTree.JCExpression implements LiteralTree {
        public TypeTag typetag;//常量的類型
        public Object value;//常量的值
}

-->
字面量類型的枚舉類
public enum TypeTag {
    BYTE(1, 125, true),
    CHAR(2, 122, true),
    SHORT(4, 124, true),
    LONG(16, 112, true),
    FLOAT(32, 96, true),
    INT(8, 120, true),
    DOUBLE(64, 64, true),
    BOOLEAN(0, 0, true),
    CLASS,

    ...
}

-->使用例子:閉括號字符串"}"
treeMaker.Literal("}")
JCBinary

二元操作符

    public static class JCBinary extends JCTree.JCExpression implements BinaryTree {
        private JCTree.Tag opcode;//操作符
        public JCTree.JCExpression lhs;//操作符左邊
        public JCTree.JCExpression rhs;//操作符右邊
        public Symbol operator;//null
}

-->二元運算符opcode可取值
public static enum Tag {
        OR,                              // ||
        AND,                             // &&
        BITOR,                           // |
        BITXOR,                          // ^
        BITAND,                          // &
        EQ,                              // ==
        NE,                              // !=
        LT,                              // <
        GT,                              // >
        LE,                              // <=
        GE,                              // >=
        SL,                              // <<
        SR,                              // >>
        USR,                             // >>>
        PLUS,                            // +
        MINUS,                           // -
        MUL,                             // *
        DIV,                             // /
        MOD,                             // %
}

-->創建例子 : 1 + 1
treeMaker.Binary(JCTree.Tag.PLUS, treeMaker.Literal(1), treeMaker.Literal(1));
JCReturn

return語句

public static class JCReturn extends JCTree.JCStatement implements ReturnTree {
        public JCTree.JCExpression expr;//返回語句的結果字段
}

-->例子:retrun this.xxx
treeMaker.Return(treeMaker.Select(treeMaker.Ident(names.fromString("this")),names.fromString("xxx")));
JCAssign

賦值語句

public static class JCAssign extends JCTree.JCExpression implements AssignmentTree {
        public JCTree.JCExpression lhs;//賦值語句左邊表達式
        public JCTree.JCExpression rhs;//賦值語句右邊表達式
}

-->例子:x = 1
treeMaker.Assign(treeMaker.Ident(names.fromString("x")))), treeMaker.Literal(1))
JCAssignOp

賦值語句

public static class JCAssignOp extends JCTree.JCExpression implements CompoundAssignmentTree {
        private JCTree.Tag opcode;
        public JCTree.JCExpression lhs;
        public JCTree.JCExpression rhs;
        public Symbol operator;
}

-->opcode可取值
public static enum Tag {
      BITOR_ASG(BITOR),                // |=
      BITXOR_ASG(BITXOR),              // ^=
      BITAND_ASG(BITAND),              // &=

      SL_ASG(SL),                      // <<=
      SR_ASG(SR),                      // >>=
      USR_ASG(USR),                    // >>>=
      PLUS_ASG(PLUS),                  // +=
      MINUS_ASG(MINUS),                // -=
      MUL_ASG(MUL),                    // *=
      DIV_ASG(DIV),                    // /=
      MOD_ASG(MOD),                    // %=
}

-->例子:x += 1
treeMaker.AssignOp(JCTree.Tag.PLUS_ASG, treeMaker.Ident(names.fromString("x")))), treeMaker.Literal(1))
JCIf

if代碼塊; if(condition) {thenpart} else {elsepart}

public static class JCIf extends JCTree.JCStatement implements IfTree {
        public JCTree.JCExpression cond;//條件語句
        public JCTree.JCStatement thenpart;//if的操作語句
        public JCTree.JCStatement elsepart;//else的操作語句
}
JCForLoop

for循環代碼塊;for (init; cond; step) {body}

public static class JCForLoop extends JCTree.JCStatement implements ForLoopTree {
        public List<JCTree.JCStatement> init;
        public JCTree.JCExpression cond;
        public List<JCTree.JCExpressionStatement> step;
        public JCTree.JCStatement body;
}
JCTry、JCCatch

try、catch和finally代碼塊;

public static class JCTry extends JCTree.JCStatement implements TryTree {
        public JCTree.JCBlock body;//try代碼塊
        public List<JCTree.JCCatch> catchers;//JCCatch
        public JCTree.JCBlock finalizer;//final代碼塊
        public List<JCTree> resources;//List.nil(),用不上的字段
        public boolean finallyCanCompleteNormally;//
}

-->JCCatch
public static class JCCatch extends JCTree implements CatchTree {
        public JCTree.JCVariableDecl param;//catch的異常類型
        public JCTree.JCBlock body;//catch代碼塊
}
JCMethodInvocation

方法調用表達式

public static class JCMethodInvocation extends JCTree.JCPolyExpression implements MethodInvocationTree {
        public List<JCTree.JCExpression> typeargs;//參數類型列表
        public JCTree.JCExpression meth;//方法的調用語句,比如Log.i,setContentView
        public List<JCTree.JCExpression> args;//參數列表
        public Type varargsElement;//null
}
JCDoWhileLoop

doWhile循環 ; do(body)while(cond)

public static class JCDoWhileLoop extends JCTree.JCStatement implements DoWhileLoopTree {
        public JCTree.JCStatement body;//do代碼塊
        public JCTree.JCExpression cond;//條件語句
}
JCEnhancedForLoop

增強for循環 ; for(var : expr){body}

public static class JCEnhancedForLoop extends JCTree.JCStatement implements EnhancedForLoopTree {
        public JCTree.JCVariableDecl var;
        public JCTree.JCExpression expr;
        public JCTree.JCStatement body;//代碼塊
}
JCThrow

異常拋出

public static class JCThrow extends JCTree.JCStatement implements ThrowTree {
        public JCTree.JCExpression expr;//異常表達式
}

-->例子:throw Exception
treeMaker.Throw(treeMaker.Ident(names.fromString("Exception")));
JCSwitch,JCCase

switch代碼塊;switch(selector) {case pat : stats}

public static class JCSwitch extends JCTree.JCStatement implements SwitchTree {
        public JCTree.JCExpression selector;//判斷條件
        public List<JCTree.JCCase> cases;//多個case
}

public static class JCCase extends JCTree.JCStatement implements CaseTree {
        public JCTree.JCExpression pat;//case邏輯表達式
        public List<JCTree.JCStatement> stats;//代碼執行語句
}
JCConditional

三目運算表達式,cond ? truepart : falsepart

public static class JCConditional extends JCTree.JCPolyExpression implements ConditionalExpressionTree {
        public JCTree.JCExpression cond;//判斷條件
        public JCTree.JCExpression truepart;//判斷為真時執行的表達式
        public JCTree.JCExpression falsepart;//判斷為假時執行的表達式
}
JCSkip

空操作,即一個無效的分號 ";"

JCUnary

一元運算表達式,

public static class JCUnary extends JCTree.JCExpression implements UnaryTree {
        private JCTree.Tag opcode;//操作運算符
        public JCTree.JCExpression arg;//
}

public static enum Tag {
  POS,                             // +
  NEG,                             // -
  NOT,                             // !
  COMPL,                           // ~
  PREINC,                          // ++ _;例子:++i
  PREDEC,                          // -- _; 例子:--i
  POSTINC,                         // _ ++; 例子:i++
  POSTDEC,                         // _ --; 例子:i--
}

-->例子:i++;
treeMaker.Unary(JCTree.Tag.POSTINC, treeMaker.Ident(names.fromString("i")));
JCContinue

continue,跳過本次循環, continue label

public static class JCContinue extends JCTree.JCStatement implements ContinueTree {
        public Name label;//label標簽
        public JCTree target;//null
}
JCBreak

break,跳出循環, break label

public static class JCBreak extends JCTree.JCStatement implements BreakTree {
        public Name label;//label標簽
        public JCTree target;//null
}

關于如何操作AST請看抽象語法樹AST的全面分析(三)

參考:
java AST JCTree簡要分析
java注解處理器——在編譯期修改語法樹

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,247評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,520評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,362評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,805評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,541評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,896評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,887評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,062評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,608評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,356評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,555評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,077評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,769評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,175評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,489評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,289評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,516評論 2 379