Previous: Bytecode Compiler Up: 目次 Next: AST

Ruby Parser

This topic has missing or partial documentation. Please help us improve it.

See How-To - Write Documentation

コンパイル処理のパイプラインの最初のステージはRubyパーサです。 Rubyパーサはコードの文字列またはファイルを入力として受け取り、 ASTを次のステージであるジェネレータに渡します。

パーサ(Melbourne)にはCで書かれたパートとRubyで書かれたパートがあり、 前者は基本的にはMRIのパーサで、後者はRubyのASTの生成を担当しています。 Cのパーサはパースツリーの各ノードについてメソッドを呼ぶことで Rubyとコミュニケーションをとります。

各メソッドは処理対象となる部分木について、その特徴となる全ての情報を受け取ります。 例えば、対象のRubyコードにif文がある場合、 Cパーサは行番号、条件を表す値、if文の本体を表す値、もしあればelse節を表す値、 を引数として、process_ifを呼びます。

def process_if(line, cond, body, else_body)
  AST::If.new line, cond, body, else_body
end

Rubiniusのソースコード内のlib/melbourne/processor.rbを見ると、 全ての起こりうるprocess_呼び出しが確認できます。

多くの場合、パーサはprocess_メソッドに その一つ前に呼び出されたprocess_メソッドの結果を渡します。 例えば true if 1 というコードでは、パーサはまず process_lit(line,1)process_true(line) を実行します。 加えて、この場合元のパースツリーはelseの本体としてnilを持っているので、 process_nil(line)も実行されます。 その後、process_ifを、行番号、process_litの結果、process_trueの結果、 process_nilの結果を引数にして呼び出します。

このような処理が再帰的にツリー構造を構築し、 Rubiniusはそれを次の段階であるジェネレータステージに渡します。

参照されているファイル

カスタマイズする

コンパイル処理のこのステージをカスタマイズするには2つの方法があります。 ASTの生成をカスタマイズする一番簡単な方法は、 AST Transformsを使う方法です。

Melbourneのサブクラスを定義し、process_メソッドを好きなように定義する方法も あります。こちらは上級者向けのまだ十分に実証されていない方法です。

Previous: Bytecode Compiler Up: 目次 Next: AST

Tweet at @rubinius on Twitter or email community@rubini.us. Please report Rubinius issues to our issue tracker.