EN JP CN

例 5:AST ツリーをトラバースする

例 5:AST ツリーをトラバースする
このトピックの内容:

セマンティック情報を確認したので、今度はカスタム関数が AST ノードのツリーをどのようにトラバースするかを確認します。KAST 式によりこのトラバースは非常に簡単になりますが、カスタム関数内でトラバースを実行することが必要な場合があります。これは、ktc_proceed() API で実行できます。

簡単な KAST 式

簡単な KAST 式から始めます。次に例を示します。

// FuncDef / FuncBody / Stmt::CompoundStmt / Stmts[*]::ExprStmt

この式は、コンテンツにバインドする複合ステートメントを通して関数の定義からその本体にナビゲートし、その複合語で最初の最上位の expression ステートメントを取り上げます。

 void foo(int someParams)
 {
   int someVariables;
  
     for( ... ) { }
     someVariables = 32;                // This ExprStmt will be our result
 }


この演習では、通常の FuncDef ノードで呼び出されるカスタム関数は、関数のさまざまなステートメントをトラバースし、expression ステートメントを使用して何かを行う必要があります。ktc_proceed() 関数はこの目的で使用できます。

ktc_proceed() function

ktc_proceed() 関数は、チェッカーが進む必要がある開始ノードおよびエッジ指定子を受け取ります。Checker Studio の FuncDef ノードを調べる場合、一般に子エッジがあることを確認します。

FuncDef
        DeclSpecs[] :: DeclSpec
        Declarator :: MaybeDeclarator
        KRParams[] :: DeclOrStmt
        FuncBody :: AnyFuncBody

Checker Studio の AST の表現では、FuncDef ノードから、4 種類の子エッジ (DeclSpecs、Declarator、KRParams、および FuncBody) を通じて進むことができ、それぞれには特定の特殊化 (DeclSpec、MaybeDeclarator、DeclOrStmt、および AnyFuncBody) があることを示しています。エッジの特殊化を確認するには、目的のノードを展開します。次のように表示されます。

FuncDef
        DeclSpecs[] :: DeclSpec
                BuiltinType
        Declarator :: MaybeDeclarator
                Declarator
        KRParams[] :: DeclOrStmt
        FuncBody :: AnyFuncBody
                FuncBody

たとえば、KAST のすべての void 関数をチェッカーに検出させる場合、FuncDef を次のように特殊化できます。

 // FuncDef / DeclSpecs[*]::BuiltinType [ @Spec = KTC_BUILTINTYPE_VOID ]


ktc API を使用してこの目的を達成するには、次の関数シーケンスを使用します。

 // Assume we start with 'node' referencing the FuncDef node, as usual
 int isVoid(ktc_tree_t node)
 {
   return
     ( (node = ktc_proceed(node, cid_DeclSpecs)) != 0 ) &&
     ( ktc_isTreeType(node, tid_BuiltinType) ) &&
     ( ktc_getBuiltinType(node) == KTC_BUILTINTYPE_VOID ) ? 1 : 0;
 }
   
 HOOKS_SET_START
   ...
   XPath_register_int_hook("isVoid", isVoid);
 HOOKS_SET_END

これで、同じ KAST ステートメントを次のように簡素化することができます。

 // FuncDef [ isVoid() ]

実際には、ktc_sema_getFunctionType() を使用したセマンティック情報で関数型を調べるでしょう。しかし、ktc_proceed() の方がこの例に適しています。