3

ANTLR パーサーは、次の生成コードを生成します。

protected TreeAdaptor adaptor = new CommonTreeAdaptor();

私は独自の TreeAdaptor を実装しましたが、パーサーが常に私のものを使用し、CommonTreeAdaptor() を使用しないようにしたいと考えています。私が見つけた唯一の方法は、新しいパーサーを作成するたびに呼び出しコード内に設定することです。

Parser parser = new MyParser();
parser.setTreeAdaptor(new MyAdaptor());

デフォルトの TreeAdaptor を設定したり、生成されたコンストラクターに初期化コードを追加したりする方法はありますか?

4

2 に答える 2

2

デフォルトの TreeAdaptor を設定したり、生成されたコンストラクターに初期化コードを追加したりする方法はありますか?

これを行う 1 つの方法は、カスタム ツリー アダプターを設定する静的メソッドを追加することです。

grammar T;

options {
  output=AST;
  ASTLabelType=CommonTree;
}

@parser::members {

  public static TParser newTParser(TreeNodeStream input) {
    TParser parser = new TParser(input);
    parser.setTreeAdaptor(new MyAdaptor());
    return parser;
  }
}

parse
 : Any* EOF
 ;

Any
 : .
 ;

そして、次のものを置き換えることができます:

TParser parser = new TParser(input);

TParser parser = TParser.newTParser(input);
于 2012-06-25T17:46:57.593 に答える
0

Bart の名前付きコンストラクター メソッドよりも優れた解決策を見つけたと思います。

生成されたコンストラクターを直接変更することはできません (それを非公開にすることを含め、名前付きコンストラクターのソリューションが嫌いな理由です)。ただし、初期化ブロックを導入できます。

grammar T;

options {
  output=AST;
  ASTLabelType=CommonTree;
}

@parser::members {
    {
        this.adaptor = new MyAdaptor();
    }
}

Java のドキュメントによると、「Java コンパイラはイニシャライザ ブロックをすべてのコンストラクタにコピーします。したがって、このアプローチを使用して、複数のコンストラクタ間でコードのブロックを共有できます。」

そのため、this.adaptor最初にnew CommonTreeAdaptor()生成されたコードによって に設定されますが、その後new MyAdaptor()、初期化ブロックによって に設定されます。テストにより、これが実際に起こることが確認されています。

このソリューションの利点は、パーサーの呼び出し元が、カスタム TreeAdaptor を使用していることや通常とは異なることを行っていることを認識する必要がないことです (私のアダプターは CommonTreeAdaptor のサブクラスであるため、それに依存するコードは問題ありません)。

于 2012-07-11T16:10:31.503 に答える