読者です 読者をやめる 読者になる 読者になる

若き JavaScripter の悩み

何かをdisっているときは、たいていツンデレですので大目に見てやってください。愛です。

estraverseの仕様意訳

es**シリーズの仕様意訳第二回。前回はesprimaでした。今回はestraverse。

estraverse

estraverseはASTの巡回コードをお手軽に書けるようにするモジュール。 ASTは子ノードのプロパティ名がまちまちなので、巡回させるコードを書くのが結構手間なんで重宝する。

基本的にesprimaの吐いたASTをestraverse.traverseに喰わせるだけでOK。 ここらへんも本当によくできていて、esprimaとestraverseは疎結合を保っている(AST仕様のみで結びついているといってもよい)。

ではいってみよう。estraverseと、ASTを吐かせるためのesprimaをnpmからとってくる。

npm install esprima
npm install estraverse

以下のようにコードを作成。

var esprima = require('esprima');
var estraverse = require('estraverse');

var code = 'console.log("Hello, World!");';
var ast = esprima.parse(code);

estraverse.traverse(ast, {
  enter: function(currentNode, parentNode) {
    console.log(currentNode.type, parentNode && parentNode.type);
    // this.skip(); // スキップする。
    // this.break(); // 巡回を終わらせる。
  },
  leave: unction(currentNode, parentNode) {
    console.log(currentNode.type, parentNode && parentNode.type);
    // this.skip(); // スキップする。
    // this.break(); // 巡回を終わらせる。
  }
});

おわり。

/**
 * ASTを深さ優先探索で巡回する。
 * @param {AstNode} root ASTのルートノード。
 * @param {EstraverseVisitor} visitor 巡回オブジェクト(Visitorパターン)。
 */
estraverse.traverse;


/**
 * estraverse.traverseの第二引数。
 */
EstraverseVisitor = {
  /**
   * ノードに訪れたときに実行される。thisにestraverse.Controllerのインスタンスにアクセスできる。
   * @param {AstNode} currentNode 訪問したノード。
   * @param {AstNode} parentNode 訪問したノードの親ノード。
   * @this {estraverse.Controller}
   */
  enter: function(currentNode, parentNode) {},

  /**
   * ノードから去るときに実行される。thisにestraverse.Controllerのインスタンスにアクセスできる。
   * @param {AstNode} currentNode 去るノード。
   * @param {AstNode} parentNode 去るノードの親ノード。
   * @this {estraverse.Controller}
   */
  leave: function(currentNode, parentNode) {},
};

巡回の制御については、EstraverseVisitor.enter EstraverseVisitor.leavethis に割り当てられた estraverse.Controll インスタンスを通じておこなうか、戻り値に estraverse.VisitorOption.BREAKestraverse.VisitorOption.SKIP を指定することでおこなえる。また、訪問先のAstNodeの祖先ノード達は、 estraverse.Controll#parents の実行(要するにthis.parents();)で取得できる。

おわり。