Java 如何使自动生成的解析器类在ANTLR4中实现接口?
我正在使用Antlr4创建一个解析器,我已经完成了语法。我需要将一些Java代码注入ANTLR自动生成的解析器文件中 如果我想在生成的解析器中包含一个方法,我可以将其添加到ANTLR语法中:Java 如何使自动生成的解析器类在ANTLR4中实现接口?,java,parsing,antlr4,Java,Parsing,Antlr4,我正在使用Antlr4创建一个解析器,我已经完成了语法。我需要将一些Java代码注入ANTLR自动生成的解析器文件中 如果我想在生成的解析器中包含一个方法,我可以将其添加到ANTLR语法中: @parser::members { @Override public CGrammarParser.CSnippetContext call() { return cSnippet(); } } 如果我想包含一些导入语句,我可以将其添加到语法中: @header { impo
@parser::members
{
@Override
public CGrammarParser.CSnippetContext call()
{
return cSnippet();
}
}
如果我想包含一些导入语句,我可以将其添加到语法中:
@header
{
import java.lang.Thread;
import java.lang.InterruptedException;
import java.util.concurrent.Callable;
}
如果我想修改类声明,使其实现接口,我该怎么做?换句话说,这是ANTLR自动生成的:
public class CGrammarParser extends Parser
{
...
}
但这就是我想要它产生的:
public class CGrammarParser extends Parser implements Callable<CGrammarParser.CSnippetContext>
{
...
}
公共类CGrammarParser扩展解析器实现可调用
{
...
}
不,不像您描述的那样(通过接口)。但是,您可以定义一个解析器应该从中扩展的超类。当然,这个超类应该扩展ANTLR的解析器
类。在自己的(抽象)解析器类中,定义要实现的接口
以下是如何做到这一点:
可调用解析器
这个答案归功于卢卡斯·特泽斯涅夫斯基 要让ANTLR解析器实现接口,语法文件(.g4)本身不需要Java。只需执行以下操作: 1) 创建一个可调用的解析器类,该类扩展ANTLR解析器并实现相关接口,如:
public class CallableParser extends CGrammarParser implements Callable<CGrammarParser.CSnippetContext>
{
public CallableParser(TokenStream input)
{
super(input);
}
@Override
public CGrammarParser.CSnippetContext call()
{
return cSnippet();
}
}
您也可以通过另一种方式来实现这一点:您可以从生成的解析器继承并在派生类中实现所需的内容(这比使用
@parser::members
构造IMO更简洁,因为语法和逻辑之间有更多的分离)。为了记录在案,对于C#解析器来说,这个问题的答案更简单:它们是部分类。它抛出一个异常InInitializeRerror
。如果我手动添加所需的扩展和实现(请参见我的问题),它可以正常工作。我觉得这个答案非常接近,但ANTLR对此并不满意。我试过你的答案,@Lucastrezesniewski,它奏效了!如果你想给这个问题添加一个答案,我会接受它作为正确答案。非常感谢。
grammar CGrammar;
options
{
superClass = CallableParser;
}
@header
{
import java.lang.Thread;
import java.lang.InterruptedException;
import java.util.concurrent.Callable;
}
@parser::members
{
@Override
public CGrammarParser.CSnippetContext call()
{
return cSnippet();
}
}
cSnippet
: ANY*? EOF
;
ANY
: .
;
public class CallableParser extends CGrammarParser implements Callable<CGrammarParser.CSnippetContext>
{
public CallableParser(TokenStream input)
{
super(input);
}
@Override
public CGrammarParser.CSnippetContext call()
{
return cSnippet();
}
}
CharStream in = new ANTLRInputStream(input);
CGrammarLexer lexer = new CGrammarLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
// Instead of doing this...
// CGrammarParser parser = new CGrammarParser(tokens);
// Do this...
CallableParser parser = new CallableParser(tokens);