我的(一)编译器课程已经很多年了,如果这样,请原谅我 问题是不适应的。我也是ANTLR和C的新手,而不是Java编码器。 我想做的是描述我的问题,然后寻求最好的建议 采用的技术。
我正在尝试将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 '}' ;
...
“最终ANTLR4参考”中的几个例子证明了这一点
覆盖BaseListener中的一些enterNode或exitNode方法
所需的一切都在Node的上下文中。我的问题是,我想
覆盖enterTypeAssignment
和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来获取我想要的结果,并且可以访问这些变量,以便在树中进一步覆盖监听器中的方法。有没有更好的方法从给定节点访问父或祖父母上下文?
答案 0 :(得分:1)
我先解析这个东西,然后使用访客。 使用Listener的优势在于您拥有所有可用的信息。
您还可以使用C#目标,它可能更容易使用C背景。