4

私はANTLRのツリー文法でリストをきれいに消費する方法を見つけようとしてたくさん読んだことがあります。これが私が試したものとその結果です(私は本当に些細なことを見逃していることを願っています)...

+=構文の使用

program returns [someInterface result]
  : m+=method* EOF {result = new SomeClass(m);};

method returns [SomeMethod result] : <definition here>

これは失敗します...

ルール'+='リストラベルは出力オプションなしでは許可されていません

出力を「AST」または「template」(唯一のオプション)に設定すると、生成されたクラスのメソッドシグネチャが変更されます。つまりm、SomeMethod(s)のリストではなく、それぞれノードまたはテンプレートのリストになります。この方法を機能させる方法があれば、私は提案を受け入れます。

ルールスコープの使用

program returns [CompilesToJavaByteCode result]
    scope {
      List<SomeMethod> methods;
    }
    @init {
      $program::methods = new ArrayList<SomeMethod>();
    }
    : (m=method {$program::methods.add(m);})*
      EOF {result = new SomeClass($program::methods);};

これは機能しているようですが、ネストされた/再帰的なケースではまだテストしていないことを認めます。

最終目標

コンパイルされたコードを生成する前に静的分析と最適化を実行できるように、自分の言語(Class、Method、Variable、Statementなど)を表すクラスのセットを作成したいと思います。そのためには、リストを利用できるようにする必要があります。+ =構文が「正しく機能する」と期待していましたが、何かが足りない可能性があります。2番目の方法は機能しますが、過度に冗長でエレガントではないように見えます。

質問

ANTLRのツリー文法で、具体的なクラスに渡すためにリストを使用する適切な理由は何ですか?

4

1 に答える 1

6

例からスコープを切り取って、すべてローカル変数で行うことができます。

program returns [CompilesToJavaByteCode result]
    @init {
      List<SomeMethod> methods = new ArrayList<SomeMethod>();
    }
    : (m=method { methods.add($m.result); })* EOF 
      { $result = new SomeClass(methods); };

これは、職場でこのケースに対して行うことです。もう 1 つのオプションは、メソッド ルールに処理させることです。

program returns [CompilesToJavaByteCode result]
    @init {
      List<SomeMethod> methods = new ArrayList<SomeMethod>();
    }
    : method[methods]* EOF { $result = new SomeClass(methods); };

method [List<SomeMethod> methods]
    : ...
      { methods.add(new SomeMethod(...); };

メソッド ルールはおそらく、そのような結果で何が行われているかを気にするべきではないので、2 番目のオプションはあまり好きではありません。ClassBeingCompiledしかし、トップ ルールが を作成し、コードの残りの部分が段階的に を埋めていく構造を想像することができます.addMethod()

于 2011-04-03T05:54:59.997 に答える