2015-04-02 33 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

相關問題