LoginSignup
26
19

More than 5 years have passed since last update.

babylonでコード変換する超基礎的なまとめ

Posted at

社内勉強会資料。

最近、babylonでJavaScriptのコードを変換するツールを作っていて、まだ出来てませんが、現状調べたことのまとめです。

ASTの基礎

JavaScript ASTを始める最初の一歩 | Web Scratch

上記記事がよいです。ざっくりまとめると、

  • AST => コードをパースした抽象構文木のこと
    • JavaScriptの場合はJavaScriptオブジェクト(JSON)として表現
  • ツールの分類
    • Parser ... ソースコードをASTに変換する
    • Traverser ... ASTの木構造を探索。ノードを差し替えたり、削除したりする
    • Generator ... ASTからソースコードを生成する
  • Parserは大きく2系統(Esprima, Acorn)
    • babylonはAcornベースで、JSXなどESTreeから拡張してる
  • ParserによってASTのフォーマットが若干(ではないかも)異なるので、Generatorは同じ系統のものを使う
    • Esprima -> escodegen, babylon -> babel-generatorみたいな感じ

Esprimaで試して、何か足りないならAcorn -> Babylonという感じでやるのが良いと思います。

上記記事に気付かず始めてしまったのでbabel系のツールを使っていますが、EsprimaかAcornの方が安定している&ドキュメントが充実しているようです。

babel系のツール群

コードの変換

ASTを使ったソースコード変換の流れ

JSer.infoの記事にも書いておりますが、下記のような流れです。

  1. JavaScriptのソースコードをASTに変換する(Parser)
  2. ASTを探索して、任意のノードを入れ替えたり、削除したりする(Travarser)
  3. 2で出来たASTからJavaScriptのソースコードを生成する(Generator)

babel-parserでソースコードをASTに変換して、babel-traveseでASTを探索して、babel-typesで作ったASTと入れ替えたりしつつ、出来上がったASTをbabel-generatorでソースコードに変換するという感じです。

小さなサンプル

パッケージをインストールします。

$ npm install -S babylon babel-traverse babel-generator babel-types

hogefugaに変換するコードを書いてみました。(babelで書いてしまったので、その辺りのパッケージも入れてください)

// hoge.js
import {parse} from 'babylon';
import generate from 'babel-generator';
import traverse from 'babel-traverse';
import * as t from 'babel-types';

// hogeをfugaに変更する関数
const replaceHogeToFuga = code => {
  // 1. JavaScriptのソースコードをASTに変換する
  const ast = parse(code);

  // 2. ASTを探索して、任意のノードを入れ替えたり、削除したりする
  traverse(ast, {
    // ノードがIdentifierの場合に呼び出される
    // pathはNodePathのインスタンス、ast-typesと似た感じのインタフェース
    Identifier: path => {
      if (path.node.name === 'hoge') {
        // ast-typesと同じかと思われたが, replaceはreplaceWithだった
        path.replaceWith(t.identifier('fuga'));
      }
    }
  });

  // 3. 2で出来たASTからJavaScriptのソースコードを生成する
  const output = generate(ast, {}, code);
  return output.code;
};

console.log(replaceHogeToFuga("hoge('Hello');"));

babel-nodeで実行してみます。

$ babel-node hoge.js
fuga('Hello');

いえーい

おわり

  • babel-traverseのドキュメントがなく、調べるのに時間がかかってしまい、本当に基礎の基礎の話になってしまった。
  • そもそもbabylonを選んでしまったのが間違いだったかもしれない。
  • 次はもうちょっと濃いノウハウを
26
19
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
26
19