Previous: Parser Up: 目次 Next: Generator Stage

Abstract Syntax Trees

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

See How-To - Write Documentation

パーサがprocess_*メソッドでの処理を終えると、抽象構文木が出来上がります。 この構文木は、パースされたコードの構文構造を抽象的に表現します。 各ノードがソースコード内の1つの構造を表しています。 このツリーは lib/compiler/ast/ ディレクトリ内で定義されているクラス群の インスタンスによって構成されています。 各クラスはRubinius::AST::Nodeクラスを継承しています。 このNodeクラスにはサブクラスから利用されるいくつかのメソッド (例えば、デバッグ用に行番号を記録する pos(g)、など) が定義されています。

ASTクラスには通常、少なくとも以下の3つのメソッドが定義されています:

作成されたASTを確認する一番簡単な方法は to_astメソッドをコードの文字列に対して呼ぶことです:

irb(main):002:0> "a = 1".to_ast
=> #<Rubinius::AST::LocalVariableAssignment:0xf70
   @value=#<Rubinius::AST::FixnumLiteral:0xf74 @value=1 @line=1>
   @name=:a @variable=nil @line=1>

もしくは、コードをコンパイルするときに -A オプションを指定します:

rbx compile -A -e "def hello;end"
Script
  @name: __script__
  @file: "(snippet)"
  @body: \
  Define
    @name: hello
    @line: 1
    @arguments: \
    FormalArguments
      @defaults: nil
      @names: \
      @block_arg: nil
      @optional: \
      @splat: nil
      @line: 1
      @required: \
    @body: \
    Block
      @line: 1
      @array: \
        NilLiteral
          @line: 1

同様に、to_sexpメソッドで構文木のS式の表現を得ることもできます:

irb(main):002:0> "a = 1".to_sexp
=> [:lasgn, :a, [:lit, 1]]

もしくはコンパイル時に -S オプションを使います:

rbx compile -S -e "def hello;end"
[:script, [:defn, :hello, [:args], [:scope, [:block, [:nil]]]]]

抽象構文木は、ノードが他のノードを持つ、ネストした構造です。 例えば、上の例にある hello メソッドの定義の場合、 その構文木はScriptノードで、@bodyDefineノードを持ちます。 このDefineノードの@argumentsにはFormalAgumentsノードが、 @bodyにはBlockノードが入っています。 そしてこの Blockノードの@arrayにはNilLiteralだけが入っています。 このNilLiteralノードは葉(リーフノード)で、他のノードを持ちません。

以下の if式と:

rbx compile -S -e ":foo if :bar"
[:script, [:if, [:lit, :bar], [:lit, :foo], nil]]

違う方式で書かれている同等のif式が:

rbx compile -S -e "if :bar then :foo; end"
[:script, [:if, [:lit, :bar], [:lit, :foo], nil]]

全く同じ構文木になることに注意して下さい。 実際のシンタックスの全てを正確に表現するわけではないので、 「抽象」構文木と呼ばれています。

参照されているファイル

カスタマイズする

コンパイル処理のこの段階をカスタマイズするには2つの方法があります。 一番簡単な方法はASTの生成を AST Transforms を使ってカスタマイズすることです。

Melbourneパーサのサブクラスを定義し、 process_メソッドを再定義することもできます。 しかし、この方法は上級者向けで、まだ十分に実証されていません。

Previous: Parser Up: 目次 Next: Generator Stage

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