2015-04-02 32 views
1

在ANTLR4中,Java中生成的词法分析器包含每个标记的公共字段,其中字段的类型是简单的'int'。是否有原因为什么ANTLR4不使用枚举,或者是否有使用枚举的选项?有没有办法让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] 

更可读的版本将有一个<代替>

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

它已经经历过了讨论:http://www.antlr3.org/pipermail/antlr-interest/2008- May/028432.html – 2015-04-02 20:00:52

+0

根据这个讨论,对于生成的词法分析器类来说,它可能是最简单的,它包含将令牌的整数值映射到字符串名称的数组,例如已经为modeNames和ruleNames完成的数组。有一个tokenNames数组,但它包含一个看似随机的字符集。也许这只是一个错误。 – jonr 2015-04-02 23:35:10

回答

1

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

lexer.setTokenFactory(new MyTokenFactory()); 

提供TokenFactory到XLexer我重写我的令牌类的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()内的交换机中处理。

1

之所以ANTLR4使用int s,而不是enums简单性能

为了调试的目的,你可以修改令牌的字符串表示如下:

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

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

  • 设置令牌工厂for lexerfor parser

参见:


编辑,解决你已经mentio问题在你的答案中。

为了避免保持标记名称同步与手动.g4,您可以建立从XLexerdynamically using reflection的映射。

+0

您可以多说一些简单性和性能,以及枚举如何不满足这些属性? – jonr 2015-04-02 19:56:01

+0

由于XLexer类中有多种类型的字段被声明为“public static final int”,所以反射将无法正常工作。只有这些的一个子集是令牌类型。例如,词法分析器模式变成int字段并且其值与token值重叠。假设上面命名为ZZ的g4语法中有一个额外的词法分析器模式。 XLexer类会有'int A = 1; int ZZ = 1;' – jonr 2015-04-02 21:44:04

+0

@jonr,据我所知,您正在广泛使用ANTLR并定义复杂的语法。您是否尝试[ANTLRWorks2](http://tunnelvisionlabs.com/products/demo/antlrworks)进行调试? – 2015-04-03 09:41:00

4

要将INT令牌类型转换为它的象征性价值,只是用

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

这可行,但只适用于版本4.5(最新版本)。 – jonr 2015-04-06 17:52:46

相关问题