需要ANTLR4树行走线索

ker*_*lyn 5 antlr4

我的(一)编译器课程已经很多年了,如果这个问题不合适,请原谅我.我也是ANTLR和C的新手,而不是Java编码器.我想做的是描述我的问题,然后就最好的技术寻求建议.

我正在尝试将ASN.1制作翻译成ML.例如,

Foo ::= ENUMERATED {
  bar  (0),    -- some comment 0
  baz  (1)     -- some comment 1
}
Run Code Online (Sandbox Code Playgroud)

<Enumerated name="Foo">
  <NamedValues>
    <Unsigned name="bar" value="0" comment="some comment 0"/>
    <Unsigned name="baz" value="1" comment="some comment 1"/>
  </NamedValues>
</Enumerated>
Run Code Online (Sandbox Code Playgroud)

我的(简化)ASN1语法是:

assignment : IDENTIFIER typeAssignment ;
typeAssignment : '::=' type ;
type : builtinType ;
builtinType : enumeratedType ;
enumeratedType : 'ENUMERATED' '{' enumerations '}' ;
...
Run Code Online (Sandbox Code Playgroud)

"明确的ANTLR4参考"中的几个示例演示了覆盖BaseListener中的一些enterNode或exitNode方法,所需的一切都在Node的上下文中.我的问题是我想覆盖enterTypeAssignmentexitTypeAssignment,但我需要的一些信息是在解析树上的节点更高(例如赋值)或更低(例如枚举).

这里有足够的描述来询问我是否应该使用访客或听众模式?我们将非常感谢您关注哪些书籍示例的建议.

我对蛮力方法有点运气:

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 =  "";
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

但可能有更优雅的解决方案......


更新:我通过在树上的方式将全局变量中的TerminalNode保存到我想要的结果,并使这些变量可以在树中进一步覆盖监听器中的方法.是否有更好的方法从给定节点访问父或祖父母上下文?

Onu*_*nur 1

我首先解析该事物,然后使用访问者。与使用侦听器相比,优点是您可以获得所有可用信息。

您还可以使用 C# 目标,这在 C 背景下可能更容易使用。