2012-05-08 46 views
1

我使用Antlr 3.2,並且在編寫語法以忽略註釋行時遇到困難。具體而言,如果註釋行是輸入的最後一行,並且後面沒有換行符,則會出現錯誤。ANTLR解析 - 忽略輸入最後一行的註釋

我的輸入實際上是彙編語言,其中註釋從分號開始的任何地方用分號開始,然後到行尾。其他一切都被解析爲命令。

我的語法表現出對問題的縮減版本,是:

grammar Test; 

options { 
    language = Java; 
    output = AST; 
    ASTLabelType = CommonTree; 
} 

@header { 
    package test; 
} 

@lexer::header { 
    package test; 
} 

rule 
    : instruction+ EOF! 
    ; 

instruction 
    : 'SET' NEWLINE!* 
    ; 

COMMENT 
    : ';' .* NEWLINE+ { $channel=HIDDEN; } 
    ; 

NEWLINE 
    : '\r'? '\n' 
    ; 

WS 
    : (' ' | '\r' | '\n' | '\t' | '\f')+ { $channel = HIDDEN; } 
    ; 

如果我使用像輸入:

; comment line 1 with blank line after it 

SET ; comment after command 
; comment line again 

解析這句話line 4:11 required (...)+ loop did not match anything at character '<EOF>'時,我得到一個錯誤。

如果我將一個換行符添加到輸入的最後一行,它會正常工作,因爲換行符與註釋剝離匹配,並且EOF匹配規則末尾。

我該如何更好地編寫它,以便忽略最後一行中的註釋,但不會給出錯誤?我不想追加任何東西到原始輸入來破解它,有沒有更清晰的方式來閱讀評論行?我試過NEWLINE | EOF的各種組合,但沒有任何東西可以擺脫錯誤。

回答

2

像這樣的東西應該這樣做:

COMMENT 
    : ';' ~('\r' | '\n')* { $channel=HIDDEN; } 
    ; 

如果你想有一個COMMENT潛在在結尾處換行,這樣做:

COMMENT 
    : ';' ~('\r' | '\n')* NEWLINE? { $channel=HIDDEN; } 
    ; 

然而,這兩個規則NEWLINEWS

NEWLINE 
    : '\r'? '\n' 
    ; 

WS 
    : (' ' | '\r' | '\n' | '\t' | '\f')+ { $channel = HIDDEN; } 
    ; 

是危險的:ANTLR wor像這樣的ks:它儘可能地匹配,所以匹配最「勝利」的規則。如果兩個(或更多)規則匹配相同數量的字符,則首先定義的那個「勝利」。

換句話說,如果詞法分析器看到類似"\n"的輸入,則會創建一個NEWLINE。但是,如果詞法分析器看到" \n"(空格後跟"\n"),則會創建一個WS令牌(並放在HIDDEN通道上)。

我不知道如果換行真的顯著您的語言(他們不是在彙編語言,據我所知的任何香精),所以簡單地去掉NEWLINE規則。如果重要,請從WS規則中刪除字符\r\n

+0

這很好,擺脫了錯誤,但我有一個後續問題。如果隱藏換行符的WS規則的確如此,爲什麼我需要''指令'來終止該規則?如果我把你的改變放入,然後從'instruction'中刪除NEWLINE *,它會在註釋結束時以'行3:27無關輸入'\ n'預期EOF'失敗。這讓我很困惑,爲什麼在第3行的評論結尾沒有被WS WSE詞法分析器規則所吞噬。 –

+0

不,對不起,我錯過了'NEWLINE'規則,只看到'WS'規則。 –

+0

感謝您的更新答案。我從你最初的答案拼湊起來,然後回到這裏評論,發現你已經更新了!你必須刪除NEWLINE規則。他們在我的情況下並不重要。 –