2013-05-05 142 views
4

如何在ANLTR4詞法分析器中實現Perl正則表達式^和$?即。匹配一行的開始和一行的結尾而不消耗任何字符。ANTLR4詞彙匹配開始行尾

我想使用ANTLR4詞法分析器來匹配行的開始處的#字符,但不是在行的中間例如,要隔離和拋出所有C++預處理器指令,而不管它是哪個指令而忽略字符串文字中的#。 (通常我們可以標記C++字符串文字以消除#出現在行中,但假設我們沒有這樣做)。這意味着我只想指定#。*?而不會打擾#if #ifndef #pragma等。

此外,C++標準允許在#例如#之前和之後的空格和多行註釋。

/* helo 
world*/ # /* hel 
l 
o 
*/ /*world */ifdef ..... 

被認爲是出現在一行上的有效的預處理指令。 (在ML評論裏面CRLFs拋給)

這是我在做什麼目前:

PPLINE: '\r'? '\n' (ML_COMMENT | '\t' | '\f' |' ')* '#' (ML_COMMENT | ~[\r\n])+ -> channel(PPDIR); 

但問題是我必須依靠#前CRLF的存在,折騰的是CRLF與指令完全一致。我需要將CRLF替換爲該指令行的CRLF,所以我必須確保該指令由CRLF終止。

但是,這意味着我的語法不能處理出現在文件開頭的指令(即沒有在CRLF之前),或者在EOF之前沒有終止CRLF。

如果Perl風格的正則表達式^ $語法可用,我可以匹配SOL/EOL而不是顯式匹配和消費CRLF。

回答

4

您可以使用條件的語義謂詞。

PPLINE 
    : {getCharPositionInLine() == 0}? 
     (ML_COMMENT | '\t' | '\f' |' ')* '#' (ML_COMMENT | ~[\r\n])+ 
     {_input.LA(1) == '\r' || _input.LA(1) == '\n'}? 
     -> channel(PPDIR) 
    ; 
+0

在Terrance Parr的着作中,語義謂詞被認爲出現在詞法分析規則的右邊緣。我們應該如何解釋你的例子左邊出現語義謂詞? – JavaMan 2013-05-06 08:03:26

+0

在ANTLR 4中,語義謂詞可以出現在* lexer *規則中的任何地方,並且它們將在它們出現的地方進行評估。解析器規則有一些限制性 - 謂詞只能出現在決策的左邊。 – 2013-05-06 13:06:04

1

你可以嘗試有與門語義(Different lexer rules in different state)或模式(pushMode - >http://www.antlr.org/wiki/display/ANTLR4/Lexer+Rules)多個規則,具有對文件的開頭改變規則,然後切換到核心規則時,指令結束,但它可能是一項長期工作。首先,也許我會嘗試,如果在不改變任何東西的情況下解析#pragma/preprocessor指令時確實存在問題,例如,如果找到#的問題可能出現在字符串和註釋中,那麼只需通過訂購規則你應該能夠把它引導到正確的案例(但這可能是一個語言問題,你可以在指令中加註釋)。