Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 有没有办法让ANTLR4对生成的令牌使用枚举?_Java_Enums_Antlr4 - Fatal编程技术网

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

Java 有没有办法让ANTLR4对生成的令牌使用枚举?,java,enums,antlr4,Java,Enums,Antlr4,在ANTLR4中,Java中生成的lexer包含每个令牌的公共字段,其中字段的类型为简单的“int”。ANTLR4不使用枚举是有原因的,还是有选项让它使用枚举 这是我脑海中一个简单的例子 x、 g4 XLexer.java public class XLexer extends Lexer{ public static final int A = 1, B = 2; } 我更希望XLexer包含 public class XLexer extends Lexer{ public st

在ANTLR4中,Java中生成的lexer包含每个令牌的公共字段,其中字段的类型为简单的“int”。ANTLR4不使用枚举是有原因的,还是有选项让它使用枚举

这是我脑海中一个简单的例子

x、 g4

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]
更具可读性的版本将取代


这是我目前的解决办法。我创建一个自定义令牌,并通过向XLexer提供一个令牌工厂

lexer.setTokenFactory(new MyTokenFactory());
我在token类中重写了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内的开关中处理。

以下是我当前的解决方法。我创建一个自定义令牌,并通过向XLexer提供一个令牌工厂

lexer.setTokenFactory(new MyTokenFactory());
我在token类中重写了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内的开关中处理。

ANTLR4使用ints而不是ENUM的原因是简单性和性能

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

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

创建一个TokenFactory实现,它返回自定义类型的令牌

设置令牌工厂和

另见:

关于堆栈溢出 关于GitHub 编辑,解决您在回答中提到的问题

为了避免手动将令牌名称与.g4保持同步,您可以从XLexer构建映射

ANTLR4使用整数而不是枚举的原因是简单性和性能

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

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

创建一个TokenFactory实现,它返回自定义类型的令牌

设置令牌工厂和

另见:

关于堆栈溢出 关于GitHub 编辑,解决您在回答中提到的问题

为了避免手动将令牌名称与.g4保持同步,您可以从XLexer构建映射

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

String tokenName = YourLexer.VOCABULARY.getSymbolicName(type);
要将int标记类型转换为其符号值,只需使用

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

您能否进一步介绍一下简单性和性能,以及枚举如何不满足这些属性?反射将不起作用,因为XLexer类中有多种类型的字段声明为“public static final int”。其中只有一个子集是令牌类型。例如,lexer模式变成int字段,其值与令牌值重叠。假设g4语法中有一个附加的lexer模式,名为ZZ。XLexer类将具有“int A=1”;int ZZ=1;'@据我所知,您正在广泛使用ANTLR并定义复杂语法。你试过调试吗?你能谈谈简单性和性能,以及枚举如何不满足这些属性吗?反射不会起作用,因为XLexer类中有多种类型的字段声明为“public static final int”。其中只有一个子集是令牌类型。例如,lexer模式变成int字段,其值与令牌值重叠。假设g4语法中有一个附加的lexer模式,名为ZZ。XLexer类将具有“int A=1”;int ZZ=1;'@据我所知,您正在广泛使用ANTLR并定义复杂语法。您尝试过调试吗?前面已经讨论过了:根据这一讨论,生成的lexer类可能最简单的方法是包含一个数组,该数组将令牌的整数值映射到字符串名,例如已经对modename和rulename进行了映射。有一个tokenNames数组,但它包含一组看似随机的字符。也许这只是一个bug,前面已经讨论过了:根据这个讨论,对于生成的lexer类来说,包含一个映射t的整数值的数组可能是最简单的 他对字符串名称进行标记,如modename和rulename已经完成的标记。有一个tokenNames数组,但它包含一组看似随机的字符。也许这只是一个bug。