esprimaのパーサを試してみる

2つ前の記事で紹介したJavaScript Source Transformation: Non-Destructive vs Regenerativeのコメント欄にて、esprimaというパーサがあることを知った。
さっそくnpm installして試そう・・・と思ったのだが、なんと公式サイト上で試せてしまった。
http://esprima.org/demo/parse.html

結果をみると大変分かりやすく、コメントをいれるのがうざいくらいなので、今回は貼るだけ。
この結果では、行番号などの実行時に不要な情報は抜け落ちているが、オプションをつけて色々出来るようだ。

パースする文

var g = function(x) {
  return 3 * x;
};

結果(構文解析木)

{
    type: 'Program',
    body: [
        {
            type: 'VariableDeclaration',
            kind: 'var',
            declarations: [
                {
                    type: 'VariableDeclarator',
                    id: {
                        type: 'Identifier',
                        name: 'g'
                    },
                    init: {
                        type: 'FunctionExpression',
                        id: null,
                        params: [
                            {
                                type: 'Identifier',
                                name: 'x'
                            }
                        ],
                        defaults: [],
                        body: {
                            type: 'BlockStatement',
                            body: [
                                {
                                    type: 'ReturnStatement',
                                    argument: {
                                        type: 'BinaryExpression',
                                        operator: '*',
                                        left: {
                                            type: 'Literal',
                                            value: 3,
                                            raw: '3'
                                        },
                                        right: {
                                            type: 'Identifier',
                                            name: 'x'
                                        }
                                    }
                                }
                            ]
                        },
                        rest: null,
                        generator: false,
                        expression: false
                    }
                }
            ]
        }
    ]
}

速さとかは計測してみなければ分からないけれども、趣味で使う分にはこっちだろうなー。

ところで、UglifyJSもEsprimaもJSで書かれている。これはつまり、例えばとあるコードをEsprimaでパースしようとして、それをNode.js上で動かしたとすると、EsprimaのコードはV8エンジンがパースするわけで、2度パースすることになる。(なおV8エンジンのパーサはC++で書かれている模様。)

目的が新しいコードを得ることではなく、実行時にコードを一部変更してそのまま実行させる、というような場合だったら、

V8がEsprimaのソースをパース → V8上で動いてるEsprimaがあるコードをパース → コードの構文解析木を変更 → 一旦JSの文字列として書き出す → V8がそれをパースして実行

となるわけで、なんかちょっと無駄感ある。

なのでV8のパーサを直接利用して・・・的なことは出来ないのかな?と思ったところ、
それはできないらしい。
https://groups.google.com/forum/#!topic/v8-users/_WracRX9BTQ
V8のパーサはV8の内部実装に密接に関係してるし、しょっちゅう実装変わるし、とにかく外から呼ばれるように作ってない、とのことです。