有没有办法让ANTLR4使用生成令牌的枚举?

时间:2015-04-02 19:28:57

标签: java enums antlr4

在ANTLR4中,Java中生成的词法分析器包含每个标记的公共字段,其中字段的类型是简单的' int'。有没有理由为什么ANTLR4不使用枚举,或者是否有选项让它使用枚举?

这是我头脑中的一个简化示例

x.g4

A: 'a';
B: 'b';

XLexer.java

public class XLexer extends Lexer{
   public static final int A = 1, B = 2;
}

我希望XLexer包含

public class XLexer extends Lexer{
  public static enum Token{
    A(1), B(2)
  }
}

这在转储令牌时用于调试目的非常有用。现在不打印令牌名称,而只提供整数表示。

[@-1,0:0='a',<1>,1:0]

更易读的版本将具有&lt; A&gt;而不是&lt; 1&gt;

[@-1,0:0='a',<A>,1:0]

3 个答案:

答案 0 :(得分:4)

要将 int 标记类型转换为其符号值,只需使用

String tokenName = YourLexer.VOCABULARY.getSymbolicName(type);

答案 1 :(得分:1)

这是我目前的解决方法。我创建了一个自定义令牌,并通过

为XLexer提供TokenFactory
lexer.setTokenFactory(new MyTokenFactory());

我覆盖了令牌类中的toString()方法。

public class MyToken extends Token{
  @Override
  public String toString(){
    StringBuilder out = new StringBuilder();

    out.append("[");
    out.append("'").append(getText()).append("'");
    out.append(" type ").append(getName()); //getName() is implemented by this class

    int start = getCharPositionInLine();
    int end = start + getText().length();
    out.append(" at ").append(getLine()).append(":").append(start).append("-").append(end);
    out.append("]");

    return out.toString();
}

除了显示类型的整数之外,类使用getName()将整数转换为字符串。

// inside the token class
private String getName(){
   switch (getType()){
     case XLexer.A: return "A";
     case XLexer.B: return "B";
     default: throw new RuntimeException("unknown token " + getType());
  }
}

这会产生以下输出

['A' type A at 1:5-6]

这个解决方案有些脆弱,因为必须更新getName()以保持与g4文件定义的当前标记保持同步。无法强制执行此属性,因为编译器无法知道是否在getName()内的交换机中处理了所有令牌类型。

答案 2 :(得分:1)

ANTLR4使用int而不是enums的原因是简单性能

出于调试目的,您可以修改令牌的字符串表示形式,如下所示:

  • 创建自己的令牌实现,扩展CommonToken。根据需要定义toString()方法。

  • 创建TokenFactory实现,返回自定义类型的标记。

  • 设置令牌工厂for lexerfor parser

另见


编辑,解决您在答案中提到的问题。

为避免令牌名称与 .g4 保持同步,您可以构建XLexer dynamically using reflection的映射。