如何让自动生成的解析器类在ANTLR4中实现接口?

时间:2016-01-08 15:13:40

标签: java parsing antlr4

我正在使用ANTLR 4创建一个解析器,我已经完成了我的语法。我需要在ANTLR为我自动生成的结果解析器文件中注入一些Java代码。

如果我想在结果解析器中包含一个方法,我可以将它添加到ANTLR语法中:

@parser::members
{
  @Override
  public CGrammarParser.CSnippetContext call()
  {
    return cSnippet();
  }
}

如果我想包含一些import语句,我可以将它添加到语法中:

@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> 
{
  ...
}

2 个答案:

答案 0 :(得分:2)

不,不像你描述的那样(通过界面)。但是,您可以定义解析器应该扩展的超类。当然,这个超类应该扩展ANTLR的Parser类。在您自己的(抽象)解析器类中,然后定义要实现的接口。

以下是如何运作的:

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
 : .
 ;

答案 1 :(得分:0)

此答案归功于 Lucas Trzesniewski

要让您的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();
    }
}

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);