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

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

上一篇文章
講解了抽象語法樹的來源和獲取時機,接下來要分析一下抽象語法樹的內(nèi)部結(jié)構(gòu)。

抽象語法樹由JCTree的內(nèi)部類(如JCCompilationUnit,JCClassDecl,JCMethodDecl等)作為語法節(jié)點構(gòu)成。我們可以通過調(diào)用JCTree的accept()方法來訪問抽象語法樹的所有語法節(jié)點。

public abstract void accept(JCTree.Visitor var1);

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

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

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

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

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

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

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

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

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

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

        //訪問forEach循環(huán)
        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);
        }

        //訪問同步關(guān)鍵字
        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);
        }

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

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

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

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

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

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

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

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

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

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

        //訪問字面量,可以是數(shù)字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;//泛型參數(shù)列表
        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;//泛型參數(shù)列表
        public JCTree.JCVariableDecl recvparam;//null
        public List<JCTree.JCVariableDecl> params;//方法參數(shù)列表
        public List<JCTree.JCExpression> thrown;//異常拋出列表
        public JCTree.JCBlock body;//方法體
        public JCTree.JCExpression defaultValue;//注解類的方法需要的defaultValue
        public MethodSymbol sym;//方法名+ (參數(shù)類型),如: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;//變量名
}

-->創(chuàng)建變量: 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;

    ...
}

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

代碼塊

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

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

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

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

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

-->創(chuàng)建實例: 獲取變量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,                             // %
}

-->創(chuàng)建例子 : 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;//返回語句的結(jié)果字段
}

-->例子: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循環(huán)代碼塊;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

方法調(diào)用表達式

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

doWhile循環(huán) ; do(body)while(cond)

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

增強for循環(huán) ; 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;//代碼執(zhí)行語句
}
JCConditional

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

public static class JCConditional extends JCTree.JCPolyExpression implements ConditionalExpressionTree {
        public JCTree.JCExpression cond;//判斷條件
        public JCTree.JCExpression truepart;//判斷為真時執(zhí)行的表達式
        public JCTree.JCExpression falsepart;//判斷為假時執(zhí)行的表達式
}
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,跳過本次循環(huán), continue label

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

break,跳出循環(huán), break label

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

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容