Antlr4 需要一个蚂蚁行走的线索吗

Antlr4 需要一个蚂蚁行走的线索吗,antlr4,Antlr4,我的(一个)编译器课程已经很多年了,所以请原谅我的错误 这个问题是不适定的。我对ANTLR和C(而不是Java)编码器也不熟悉。 我想做的是描述我的问题,然后寻求最好的建议 使用的技术 我正在尝试将ASN.1产品翻译成ML。例如 Foo ::= ENUMERATED { bar (0), -- some comment 0 baz (1) -- some comment 1 } 进入 “最终ANTLR4参考”中的几个示例演示了 重写BaseListener中的某些en

我的(一个)编译器课程已经很多年了,所以请原谅我的错误 这个问题是不适定的。我对ANTLR和C(而不是Java)编码器也不熟悉。 我想做的是描述我的问题,然后寻求最好的建议 使用的技术

我正在尝试将ASN.1产品翻译成ML。例如

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

“最终ANTLR4参考”中的几个示例演示了 重写BaseListener中的某些enterNode或exitNode方法,并 所需的一切都在节点的上下文中。我的问题是我想 覆盖
输入类型分配
退出类型分配
,但 我需要的信息位于较高的节点(例如分配)或较低的节点(例如枚举) 在解析树上

这里是否有足够的描述来询问我是否应该使用访客 还是听者模式?关于关注哪本书的示例的任何建议 非常感谢

我在蛮力方法方面有点运气:

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 =  "";
    }
  }
}
import org.antlr.v4.runtime.TokenStream;
导入org.antlr.v4.runtime.misc.Interval;
公共类MyListener扩展为ASN1BaseListener{
ASN1语法分析器;
字符串id=“”;
字符串assignedType=“”;
公共MyListener(ASN1Parser){this.parser=parser;}
@凌驾
公共无效enterAssignment(ASN1Parser.AssignmentContext ctx){
id=ctx.IDENTIFIER().getText();
}
/**听类型分配的匹配**/
@凌驾
public void entertypesignment(ASN1Parser.TypeAssignmentContext ctx){
如果(ctx.type()!=null){
if(ctx.type().builtinType()!=null){
if(ctx.type().builtinType().enumeratedType()!=null){
assignedType=“枚举”;
System.out.println(“”);
System.out.println(“”);
...
}
}
}
}
@凌驾
public void exitTypeAssignment(ASN1Parser.TypeAssignmentContext ctx){
如果(assignedType.length()>0){
System.out.println(“”);
assignedType=“”;
}
}
}
但可能有一个更优雅的解决方案



更新:我通过在树下保存全局变量中的TerminalNodes,并使这些变量可以访问,以覆盖树下侦听器中的方法,从而得到想要的结果。有没有更好的方法从给定的节点访问父或祖父母上下文?

我会首先解析该内容,然后使用访问者。 与使用侦听器相比,它的优点是您拥有所有可用信息


您也可以使用C#目标,这可能更容易用于C背景。

我不会给出这个答案,因为我没有使用ANTL4并测试过这个。我用ANTLR 3做了很多这件事。当您有一个节点时,它应该具有获取子节点或父节点的方法,如果没有,那么您需要将其强制转换为这样做的节点类型。请参阅:。希望这能让你走上正轨。:)
assignment : IDENTIFIER typeAssignment ;
typeAssignment : '::=' type ;
type : builtinType ;
builtinType : enumeratedType ;
enumeratedType : 'ENUMERATED' '{' enumerations '}' ;
...
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 =  "";
    }
  }
}