2012-08-28 37 views
1

鑑於詞法ANTLR 3 RewriteEmptyStreamException上ID/NAME區別

fragment 
FRAGID : ('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')* ; 
ID : FRAGID; 
NAME: FRAGID ('.' FRAGID)*; 

鑑於語法

var_def: type=ID vname=ID ASSIGN expr  
    -> ^(VARDEF $type $vname expr) 
    ; 

帶有選項

options 
{ 
    language=CSharp3; 
    output=AST; 
} 

和給出的代碼

int i = 0 

一切工作正常。

然而,當我想允許轉讓使用戶名(指到另一個對象)

var_def 
    : type=(NAME|ID) vname=ID ASSIGN expr 
    -> ^(VARDEF $type $vname expr) 
    ; 

我會在運行時RewriteEmptyStreamException

Antlr.Runtime.Tree.RewriteEmptyStreamException :令牌類型

at Antlr.Runtime.Tree.RewriteRuleElementStream.NextCore()in c:\ dev \ stringtemplate_main \ antlr \ antlr3-main \ runtime \ CSharp3 \ Sources \ Antlr3.Runtime \ Tree \ RewriteRuleEl ementStream.cs:line 200

at Antlr.Runtime.Tree.RewriteRuleTokenStream.NextNode()in c:\ dev \ stringtemplate_main \ antlr \ antlr3-main \ runtime \ CSharp3 \ Sources \ Antlr3.Runtime \ Tree \ RewriteRuleTokenStream。 CS:行62

做一些更investiagion,與語法

var_def 
    : type=NAME vname=ID ASSIGN expr 
    -> ^(VARDEF $type $vname expr) 
    ; 

我得到一個

Antlr.Runtime.Tree.RewriteEarlyExitException:類型Antlr.Runtime.Tree.RewriteEarlyExitException「的異常被拋出。

回答

1

'i'在:

int i = 0 

將永遠成爲一個ID令牌。因爲IDNAME匹配單個FRAGID,並且由於IDNAME之前定義,因此永遠不會有NAME令牌(在單個FRAGID的情況下)。它將永遠成爲一個ID令牌。

這就是爲什麼這是行不通的:

var_def 
    : type=NAME vname=ID ASSIGN expr 
    -> ^(VARDEF $type $vname expr) 
    ; 

你必須認識到,詞法分析器不取決於什麼記號解析器嘗試匹配在特定的時間創建令牌。詞法分析器獨立於解析器工作。

嘗試避免將標籤分配給帶圓括號的標記/規則組。相反的:

var_def 
    : type=(NAME|ID) vname=ID ASSIGN expr -> ^(VARDEF $type $vname expr) 
    ; 

做到這一點:

var_def 
: type ID ASSIGN expr -> ^(VARDEF type ID expr) 
; 

type 
: NAME 
| ID 
; 
+0

聽起來與避免標籤的標記/規則一個括號組有趣。你能否詳細說明或給出一個URL,以便我更好地理解爲什麼這是一個問題。 –

+1

@ CarloV.Dango,我沒有給你參考。根本不可能做'label =(A | B | C)'。可能是因爲在括號內部,你可能有多個解析器或詞法分析器規則,使得標籤的分配變得毫無意義。你*可以*做到這一點:'(type = NAME | type = ID)... - > ^(VARDEF $ type ...)',但我覺得它很雜亂。 –