2012-03-25 38 views
2

我有一個問題,建立一個語法,它能夠解析Python 3的AST轉儲格式,並將其轉換爲AST格式,我更容易玩弄。我決定編寫一個ANTLR語法來完成這項工作,但我在處理關鍵字塊(但由於某些原因只能使用關鍵字塊)時遇到問題。餘中分離出來的關鍵字語法,如下所示:解決可能的ANTLR語法歧義(和一般改進技巧)

grammar kwds; 
options {output=AST;} 

keywords: 'keywords=['((', '?)keyword)*']' -> keyword* 
    ; 

keyword : 'keyword(arg='STRING', value='str')' 
    ; 
str : 'Str(s='STRING')' -> STRING 
    ; 

STRING 
    : '\'' (ESC_SEQ | ~('\\'|'\''))* '\'' 
    ; 

fragment 
ESC_SEQ 
    : '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\') 
    | UNICODE_ESC 
    | OCTAL_ESC 
    ; 

EMPTYBRACKETS 
    : '[]'; 

fragment 
OCTAL_ESC 
    : '\\' ('0'..'3') ('0'..'7') ('0'..'7') 
    | '\\' ('0'..'7') ('0'..'7') 
    | '\\' ('0'..'7') 
    ; 

fragment 
UNICODE_ESC 
    : '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT 
    ; 

fragment 
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ; 

這被設計爲接受的關鍵字(0或更多逗號分隔符)的列表,其中在關鍵字規則所示的格式。

如果給上面的語法以下的(有效的)輸入,

關鍵字= [關鍵字(ARG = '名稱',值= STR(S = 'UGA')),關鍵字(ARG = 'rank',value = Str(s ='2'))]

語法會識別它,因爲它應該。

然而,使用「完全」蟒3 AST格式我寫語法(在http://pastebin.com/ETrSVXvf爲節省空間的目的發現,分別在線路106和109中發現,兩個以上規則),其使用幾乎完全相同的語法規則,令牌流似乎是幾個字符關閉解析從上面示出的樣本的第一關鍵字匹配,來確定這些關鍵字規則解析時產生以下輸出後:

sample3.txt line 1:52 mismatched character 'e' expecting 'w' 
sample3.txt line 1:53 no viable alternative at character 'y' 
sample3.txt line 1:54 no viable alternative at character 'w' 
sample3.txt line 1:55 no viable alternative at character 'o' 
sample3.txt line 1:56 no viable alternative at character 'r' 
sample3.txt line 1:57 no viable alternative at character 'd' 
sample3.txt line 1:58 no viable alternative at character '(' 
sample3.txt line 1:59 missing ENDBR at 'arg=' 

我只能想到的出現這種情況的一種可能性:由於語法中的模糊性,某物正在被不正確地標記,因爲我用來檢測多個關鍵字語句的模式適用於其他的t報表的類型。然而,我完全停留在語法中實際存在歧義的地方。

另外,任何一般的改進提示,以我如何能改善我的語法一般將不勝感激!

回答

1

如果添加了規則:

parse 
: (t=. {System.out.printf("type=\%-20s text='\%s'\n", tokenNames[$t.type], $t.text);})* EOF 
; 

它只是匹配零個或多個標記,並打印出的類型和這些記號的文字,你會看到詞法分析器無法與輸入, keyword從你的榜樣應對:

keywords=[keyword(arg='name', value=Str(s='UGA')), keyword(arg='rank', value=Str(s='2'))] 
               ^^^^^^^^^ 

所以在你的語法規則一個沒有問題,但事情出差錯在詞彙層面。

我建議您從解析器中刪除所有文字標記併爲它們創建詞法分析規則。然後添加一個parse規則,就像我上面發佈的那樣,您可以測試詞法分析器以查看是否創建了適當的令牌。一旦創建了適當的令牌,編寫解析器規則。

我敢肯定,這裏的問題是,你沒有一個', keyword'令牌,以及一旦詞法分析器「看到」 ', k',它試圖創建一個', kwargs'令牌,該令牌失敗,當然。所以我也建議你做而不是在你的代幣中包含逗號和空格,但讓它們成爲它們自己的代幣。

而且,你不希望有一個重寫規則是這樣的:

stmtlist:  ((', '?) stmt)* -> stmt* 
     ; 

這有可能匹配什麼。如果發生這種情況,ANTLR將在創建AST時拋出異常。總是讓重寫規則產生東西

... 

tokens { 
    ... 
    STMTLST; 
    ... 
} 

... 

stmtlist:  ((', '?) stmt)* -> ^(STMTLST stmt*) 
     ; 
+0

啊哈,我明白了。這很有道理,詞法分析師會混淆',k',這也會解釋一些角色是如何被消費的,而另一些則不是。另外,感謝關​​於重寫規則的提示! – wibarr 2012-03-25 14:17:23

+0

@ Webs961,不客氣。 – 2012-03-25 14:21:59