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

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

のシリーズを、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


やはり面白い。

コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)