在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]
答案 0 :(得分:4)
要将 int 标记类型转换为其符号值,只需使用
String tokenName = YourLexer.VOCABULARY.getSymbolicName(type);
答案 1 :(得分:1)
这是我目前的解决方法。我创建了一个自定义令牌,并通过
为XLexer提供TokenFactorylexer.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 lexer和for parser。
另见:
编辑,解决您在答案中提到的问题。
为避免令牌名称与 .g4 保持同步,您可以构建XLexer
dynamically using reflection的映射。