JRuby で AST を作る

JRuby で AST 作ってみた。
だって AST が好きだから。
JRuby のバージョンは 1.3.1。


hello.jruby.RubyASTViewer

package hello.jruby;

import java.io.ByteArrayInputStream;

import org.jruby.Ruby;
import org.jruby.ast.Node;

/**
 * Ruby AST Viewer
 * @author mallowlabs
 */
public class RubyASTViewer {

	private String src = "";
	private Node ast = null;

	/**
	 * Constructor.
	 * @param src ruby source code
	 */
	public RubyASTViewer(String src) {
		super();
		this.src = src;
	}

	/**
	 * Show AST.
	 */
	public void view() {
		parse();
		traverse(ast, 0);
	}

	/**
	 * Traverse AST.
	 * @param node
	 * @param indent
	 */
	protected void traverse(Node node, int indent) {
		for (int i = 0; i < indent; i++)
			System.out.print(" ");
		System.out.println(node.getClass().toString() + " "
				+ node.getPosition().toString());
		for (Node child : node.childNodes()) {
			traverse(child, indent + 2);
		}
	}

	/**
	 * Parse ruby source code.
	 */
	protected void parse() {
		ast = Ruby.newInstance().parseInline(
				new ByteArrayInputStream(src.getBytes()), "-", null);
	}

	/**
	 * Entry point.
	 * @param args
	 */
	public static void main(String[] args) {
		final String src = "puts \"Hello world \"\nputs 1+1";
		new RubyASTViewer(src).view();
	}

}

実行結果

class org.jruby.ast.RootNode -:0
  class org.jruby.ast.BlockNode -:0
    class org.jruby.ast.NewlineNode -:0
      class org.jruby.ast.FCallOneArgNode -:0
        class org.jruby.ast.ArrayNode -:0
          class org.jruby.ast.StrNode -:0
    class org.jruby.ast.NewlineNode -:1
      class org.jruby.ast.FCallOneArgNode -:1
        class org.jruby.ast.ArrayNode -:1
          class org.jruby.ast.CallOneArgNode -:1
            class org.jruby.ast.FixnumNode -:1
            class org.jruby.ast.ArrayNode -:1
              class org.jruby.ast.FixnumNode -:1


感想

  • 簡単
  • AST のノードはそれぞれコード上の行番号を保持してて Java っぽい
  • NewLineNode というのがなんだか新鮮
  • AST 萌え