一個星期前我開始了以下項目:識別Java代碼後綴的語法。ANTLR:如何解釋識別Java代碼後綴的語法行爲?
我使用Java的官方ANTLR
語法(Java.g4
)作爲基準,並開始添加一些規則。但是,這些新規則還引入了我也必須處理的左遞歸。
經過幾天的工作,我得到了following code。當我開始測試時,我發現了一些我仍然無法解釋的異常。當給定輸入{ }
時,解析器告訴我no viable alternative at input '<EOF>'
,但是當我切換規則s2
右手側的終端順序時,特別是如果我們將右手側從v2_1 | v2_2 | v2_3 ...
更改爲v2_36 | v2_1 | v2_2 ...
(將終端v2_36
移動到第一個位置),序列{ }
被接受。
我的第一個想法是認爲Antlr
不走回頭路,因爲我注意到,與輸入{ }
解析器的第一個版本開始遵循規則v2_3
和公正的報道,沒有被發現,不會嘗試考慮其他的選擇(這是我認爲但可能不是這樣),如v2_36
這給出了肯定的答案。
但是,經過一番研究,我發現ANTLR
實際上會回溯,但只有在其他一切都失敗的情況下。至少在v3.3中這是正確的(在官方的ANTLR
論文中可以看到它),但我想這也適用於v4
。現在我有點困惑。在這個項目上花了這麼多小時之後,如果我沒有成功,我會覺得非常糟糕。有人可以提供某種小費或什麼?非常感謝,謝謝。
編輯
管理隔離問題
grammar Java;
@parser::members {String ruleName; }
start : compilationUnitSuf EOF;
compilationUnitSuf
: {ruleName = "typeDeclarationSuf"; } s2
;
s2: '{' '}' v2_81 | '{' '}';
v2_81 : {ruleName.equals("enumBodyDeclarationsSuf")}? t173 | t173 '}';
t173: '}' | '{'*;
LBRACKET: '{';
RBRACKET: '}';
WS : [ \t\r\n\u000C]+ -> skip
;
那麼,爲什麼預測算法建議我跟着s2 -> v'{' '}' v2_81 -> ...
,而不是s2 -> '{' '}'
?
我不知道你的意思是_「後綴的Java代碼」_。 –
如果我們有給定Java代碼的標記序列'a [1..n]',我們將後綴定義爲序列'a [j],a [j + 1],...,a [對於某些'1 <= j <= n'(對於代碼'class A {int a;}'''可能的後綴是'A {int a;}','{int a;}','int a ;}'等),但我認爲這與問題無關 – svs
您有使用ANTLR的原因嗎?對於後綴解析,一個GLR解析器會容易得多,並且它會後綴解析LR(1)語法的大致線性時間,iirc。關於Grune&Jacobs中的後綴解析有一整章(解析技巧:實用指南)。 – rici