LoginSignup
0
0

More than 5 years have passed since last update.

RecursiveASTVisitorの使い方

Posted at

ClangでなにかやろうとしたときにはRecursiveASTVisitorを使うことが多いと思う。簡単な使い方の説明を書く。

RecursiveASTVisitorにはVisitFooTraverseFooが定義されている。他にWalkUpFromFooもあるけど、前二つに比べると利用頻度は下がるだろう。

サンプルプログラム。意味はない。

@interface Hello : NSObject
@end

@implementation Hello

- (NSString *)hello:(NSString *x) {
  if (x) {
    return x;
  } else {
    return @"";
  }
}

@end

僕はClang初心者なので、Clangの流儀としてこれで合っているのか良くわかりません。とりあえず意図通りに動いてはいる。

プログラム中のすべての要素を処理したい場合

これは簡単で、単純にVisitFooを実装すれば良い。

VisitExprを定義しておけば、ifの条件のxreturnx@""に対する処理が実装できる。

特定の要素に含まれる要素を処理したい場合

メソッド定義の中の式だけ処理したい場合がある。しかもその処理には式を含むメソッド名が必要だったりする。

この場合は、

  1. メソッド定義だけ取り出すVisitor
  2. 式を処理するVisitor

に分ける。1.のためにVisitを使うと、全部の部分式を処理してしまうので、ここでTraverseを使う。

class MethodBodyProcessor : public RecursiveASTVisitor<MethodBodyProcessor> {
  ...
};

class ProgramProcessor : public RecursiveASTVisitor<ProgramProcessor> {
public:
  bool TraverseObjCMethodDecl(ObjCMethodDecl *decl) {
    std::string name = decl->getNameAsString();
    MethodBodyProcessor bodyProcessor(name);
    return bodyProcessor.TraverseStmt(decl->getBody());
  }
};

RecursiveASTVisitorTraverseFooには、再帰的にvisitする処理が含まれているので、TraverseFooを自分で実装してしまうことで、部分式を処理しないようにすることができる。この場合、式の処理が必要なら、別のVisitorを作って委譲する。

式のクラスによって場合分けしつつ、結果をreturnしたい場合

多分RecursiveASTVisitorではなく、ExprVisitorとかを使って、手でrecursionするしか無いと思う。悲しい。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0