2012-08-30 41 views
4

我有以下的語法前瞻:ANTLR詞法分析器不能在所有

rule: 'aaa' | 'a' 'a'; 

它可以成功地解析字符串「AAA」,但它無法解析「AA」,出現以下錯誤:

line 1:2 mismatched character '<EOF>' expecting 'a' 

僅供參考,這是詞法分析器的問題而不是解析器的問題,因爲我甚至不會調用解析器。主要功能是這樣的:

@members { 
    public static void main(String[] args) throws Exception { 
    RecipeLexer lexer = new RecipeLexer(new ANTLRInputStream(System.in)); 
    for (Token t = lexer.nextToken(); t.getType() != EOF; t = lexer.nextToken()) 
     System.out.println(t.getType()); 
    } 
} 

結果是具有較爲明顯的版本是一樣的:

rule: AAA | A A; 
AAA: 'aaa'; 
A: 'a'; 

顯然ANTLR詞法分析器嘗試匹配與失敗規則AAA輸入「AA」。除了ANTLR是LL(*)解析器之外,詞法分析器應該與解析器分開工作,它應該能夠解決模糊性問題。語法與舊的lex(或flex)很好地工作,但它似乎與ANTLR不同。那麼這裏有什麼問題?

感謝您的幫助!

+0

在詞法分析器中如何定義令牌?在我看來,詞法分析器寧願匹配'a'而不是'aaa',只需要一個'a'作爲輸入。 – Dervall

+0

ANTLR是貪婪的。 –

+0

@Dervall令牌文件看起來像:'A = 4 AAA = 5'它傾向於'aaa'到'a'。它可以解析'aaa'和'a',但不能解析'aa'。 –

回答

6

ANTLR生成的解析器是(或可以)LL(*),而不是它的詞法分析器。

當詞法分析器看到輸入"aa"時,它會嘗試匹配令牌AAA。當它沒有這樣做時,它會嘗試匹配任何也與"aa"匹配的其他標記(詞法分析器不會匹配A!)。由於這是不可能的,所以會產生錯誤。

這通常不是問題,因爲在實踐中,經常會有某種標識符規則"aa"可以回退。那麼,你試圖解決什麼樣的實際問題,或者你只是對內部工作感到好奇?如果是第一個,請編輯您的問題並描述您的實際問題。

+0

感謝您的澄清,巴特。我想這更接近第二。我一直在使用lex/yacc,我試圖切換到ANTLR。 ANTLR解析器作爲LL解析器已經有其限制,但正如您所指出的,這是關於詞法分析器而不是解析器。說實話,如果ANTLR詞法分析器無法處理這種複雜性,那麼像'lex'這樣的其他詞法分析器就可以做到,我會有點失望。回溯成本不會很大,O(n^2)最差,如果巧妙處理,效果會更好。 –

+0

@KJ,當然有辦法解決這個問題。但不是解釋如何解決你的「稻草人」的例子,我寧願試圖提出解決手頭的「真實」問題(否則我最終會回答兩次......)。 –

+0

恐怕我不是在尋求解決特定問題的解決方法。正如我所說的那樣,它更接近好奇心,因爲我正在考慮使用ANTLR,因爲它不像yacc支持JAVA,但我越來越謹慎。我知道有一個解決這個問題的手動查找(我見過你的[上一篇文章](http://stackoverflow.com/a/8800722/456933)),但必須處理類似的問題,案件似乎不可靠..感謝您的答案,但! –

相關問題