如何让自动生成的解析器 class 在 ANTLR4 中实现一个接口?
How do I make the auto-generated parser class implement an interface in ANTLR4?
我正在使用 ANTLR 4 创建一个解析器,并且我已经完成了我的语法。我需要将一些 Java 代码注入到 ANTLR 自动为我生成的解析器文件中。
如果我想在生成的解析器中包含一个方法,我可以将其添加到 ANTLR 语法中:
@parser::members
{
@Override
public CGrammarParser.CSnippetContext call()
{
return cSnippet();
}
}
如果我想包含一些导入语句,我可以将其添加到语法中:
@header
{
import java.lang.Thread;
import java.lang.InterruptedException;
import java.util.concurrent.Callable;
}
如果我想修改 class 声明,使其 实现一个接口 ,我该怎么做?换句话说,这是 ANTLR 自动生成的:
public class CGrammarParser extends Parser
{
...
}
但这就是我想要它生成的:
public class CGrammarParser extends Parser implements Callable<CGrammarParser.CSnippetContext>
{
...
}
不,不像你描述的那样(通过界面)。但是,您可以定义一个超级 class 您的解析器应该从中扩展。这个超级 class 当然应该扩展 ANTLR 的 Parser
class。然后在您自己的(抽象)解析器 class 中定义要实现的接口。
工作原理如下:
CallableParser
import java.util.concurrent.Callable;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.TokenStream;
public abstract class CallableParser extends Parser implements Callable<CGrammarParser.CSnippetContext>
{
public CallableParser(TokenStream input)
{
super(input);
}
}
CGrammar.g4
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
: .
;
此答案归功于 Lucas Trzesniewski。
要让您的 ANTLR 解析器实现接口,语法文件 (.g4) 本身不需要 Java。只需执行以下操作:
1) 创建一个可调用的解析器 class 来扩展 ANTLR 解析器并实现相关接口,例如:
public class CallableParser extends CGrammarParser implements Callable<CGrammarParser.CSnippetContext>
{
public CallableParser(TokenStream input)
{
super(input);
}
@Override
public CGrammarParser.CSnippetContext call()
{
return cSnippet();
}
}
2) 不要调用您的 ANTLR 解析器,而是调用 CallableParser
,如下所示:
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);
我正在使用 ANTLR 4 创建一个解析器,并且我已经完成了我的语法。我需要将一些 Java 代码注入到 ANTLR 自动为我生成的解析器文件中。
如果我想在生成的解析器中包含一个方法,我可以将其添加到 ANTLR 语法中:
@parser::members
{
@Override
public CGrammarParser.CSnippetContext call()
{
return cSnippet();
}
}
如果我想包含一些导入语句,我可以将其添加到语法中:
@header
{
import java.lang.Thread;
import java.lang.InterruptedException;
import java.util.concurrent.Callable;
}
如果我想修改 class 声明,使其 实现一个接口 ,我该怎么做?换句话说,这是 ANTLR 自动生成的:
public class CGrammarParser extends Parser
{
...
}
但这就是我想要它生成的:
public class CGrammarParser extends Parser implements Callable<CGrammarParser.CSnippetContext>
{
...
}
不,不像你描述的那样(通过界面)。但是,您可以定义一个超级 class 您的解析器应该从中扩展。这个超级 class 当然应该扩展 ANTLR 的 Parser
class。然后在您自己的(抽象)解析器 class 中定义要实现的接口。
工作原理如下:
CallableParser
import java.util.concurrent.Callable;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.TokenStream;
public abstract class CallableParser extends Parser implements Callable<CGrammarParser.CSnippetContext>
{
public CallableParser(TokenStream input)
{
super(input);
}
}
CGrammar.g4
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
: .
;
此答案归功于 Lucas Trzesniewski。
要让您的 ANTLR 解析器实现接口,语法文件 (.g4) 本身不需要 Java。只需执行以下操作:
1) 创建一个可调用的解析器 class 来扩展 ANTLR 解析器并实现相关接口,例如:
public class CallableParser extends CGrammarParser implements Callable<CGrammarParser.CSnippetContext>
{
public CallableParser(TokenStream input)
{
super(input);
}
@Override
public CGrammarParser.CSnippetContext call()
{
return cSnippet();
}
}
2) 不要调用您的 ANTLR 解析器,而是调用 CallableParser
,如下所示:
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);