5

私の(1つの)コンパイラコースから何年も経っているので、この質問が間違っていたら許してください。私はANTLRとJavaではなくCのコーダーも初めてです。私がやりたいことは、私の問題を説明してから、採用する最善の手法についてアドバイスを求めることです.

ASN.1 プロダクションを ML に変換しようとしています。例えば、

Foo ::= ENUMERATED {
  bar  (0),    -- some comment 0
  baz  (1)     -- some comment 1
}

の中へ

<Enumerated name="Foo">
  <NamedValues>
    <Unsigned name="bar" value="0" comment="some comment 0"/>
    <Unsigned name="baz" value="1" comment="some comment 1"/>
  </NamedValues>
</Enumerated>

私の(簡略化された)ASN1文法は次のとおりです。

assignment : IDENTIFIER typeAssignment ;
typeAssignment : '::=' type ;
type : builtinType ;
builtinType : enumeratedType ;
enumeratedType : 'ENUMERATED' '{' enumerations '}' ;
...

「The Definitive ANTLR4 Reference」のいくつかの例は、BaseListener でいくつかの enterNode または exitNode メソッドをオーバーライドする方法を示しており、必要なものはすべてノードのコンテキストにあります。enterTypeAssignment私の問題は、 andをオーバーライドしたいということですexitTypeAssignmentが、必要な情報の一部は、解析ツリーの上位ノード (代入など) または下位ノード (列挙など) にあります。

ビジター パターンとリスナー パターンのどちらを使用する必要があるかを尋ねるのに十分な説明はありますか? どの本の例に焦点を当てるかについてのアドバイスは大歓迎です。

ブルートフォースアプローチで運が良かった:

import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.misc.Interval;

public class MylListener extends ASN1BaseListener {
  ASN1Parser parser;
  String id = "";
  String assignedType =  "";

  public MyListener(ASN1Parser parser) {this.parser = parser;}

  @Override
  public void enterAssignment(ASN1Parser.AssignmentContext ctx) {
    id = ctx.IDENTIFIER().getText();
  }

  /** Listen to matches of typeAssignment **/
  @Override
  public void enterTypeAssignment(ASN1Parser.TypeAssignmentContext ctx) {
    if ( ctx.type() != null ) {
      if ( ctx.type().builtinType() != null ) {
        if ( ctx.type().builtinType().enumeratedType() != null ) {
          assignedType =  "Enumerated";
          System.out.println("");
          System.out.println("<Enumerated name=\""+id+"\">");
          ...
        }
      }
    }
  }

  @Override
  public void exitTypeAssignment(ASN1Parser.TypeAssignmentContext ctx) {
    if (assignedType.length() > 0) {
      System.out.println("</"+assignedType+">");
      assignedType =  "";
    }
  }
}

しかし、おそらくもっとエレガントな解決策があります...


更新: ツリーを下る途中で TerminalNodes をグローバル変数に保存し、これらの変数にアクセスして、ツリーのさらに下にあるリスナーのメソッドをオーバーライドすることで、必要な結果を得ています。特定のノードから親または祖父母のコンテキストにアクセスするより良い方法はありますか?

4

1 に答える 1