LoginSignup
4
7

More than 5 years have passed since last update.

node.js + esprima + Graphviz で抽象構文木をグラフにしてみる

Posted at

のシリーズを、JavaScript(node.js) で。

JS の AST を得る方法はたくさんあるみたいなんだけど、 esprima というライブラリを選択した。

まずはソースコード。

node.js
var esprima = require('esprima');
var fs = require('fs');

function walk(parent, edge, node, proc) {
  if (node === null || "object" != typeof node) {
    return;
  }
  proc(parent, edge, node);
  for (var key in node) {
    walk(node, key, node[key], proc);
  }
}

function quoted(node) {
  var s = "";
  if ("type" in node) {
    s += node.type;
  }
  if ("name" in node) {
    s += "(" + node.name + ")";
  }
  if ("value" in node) {
    s += "[" + node.value + "]";
  }
  if ("operator" in node) {
    s += "(" + node.operator + ")";
  }
  if (Array.isArray(node)){
    s = "Array";
  }
  var j = JSON.stringify([s]);
  return j.substr(1, j.length - 2);
}

function codeToDot(src) {
  var ast = esprima.parse(src);
  var str = "";
  var id = 0;
  walk(null, null, ast, function (parent, edge, node) {
    node["dot_id"] = "n" + (id++);
    if ( parent!==null ){
      str += parent.dot_id + "->" + node.dot_id + "[taillabel=\"" + edge + "\"]\n";
    }
    var label = quoted(node);
    str += node.dot_id + "[ label=" + label + "]\n";
  });
  return str;
}
fs.readFile(process.argv[2], 'utf8', function (err, text) {
  dot = codeToDot(text);
  process.stdout.write("digraph{graph [dpi=288;]; node[ shape=box ];\n");
  process.stdout.write(dot);
  process.stdout.write("}\n");
});

関数 quoted が不十分かもしれない。

食べさせたコードはこんな感じ:

javascript

function hoge(foo, bar) {
  for (var ix in bar) {
    var val = bar[ix];
    if (val < ix) {
      console.log(val + (-10 + 100));
    }
  }
}

hoge("45", ["34", "56"]);

forif と関数定義、関数呼び出し、配列リテラル、あたりを入れてみた。

出来上がる絵はこんな感じ:

image.png

やはり面白い。

4
7
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
4
7