2011-12-23 62 views
3

我必須解析由兩部分組成的文件。在第一個中,必須跳過新行。在第二個中,它們很重要並用作分隔符。有選擇地根據上下文跳過換行

我想避免像http://www.antlr.org/wiki/pages/viewpage.action?pageId=1734這樣的解決方案,而是使用謂詞。

就目前而言,我有這樣的:

WS:  (' ' | '\t' | NEWLINE) {SKIP();}; 
fragment NEWLINE : '\r'|'\n'|'\r\n'; 

我嘗試添加動態範圍變量keepNewline被設置爲true,當「進入」文件的第二部分。

但是,我無法創建正確的謂詞來關閉換行符的「跳過」。

任何幫助將不勝感激。

此致敬禮。

回答

4

它比你想象的要容易:你甚至不需要謂詞。

假設您只想在<pre>內保留換行符... </pre>標籤。以下僞語法做到了這一點:

grammar Pre; 

@lexer::members { 
    private boolean keepNewLine = false; 
} 

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

Word 
: ('a'..'z' | 'A'..'Z')+ 
; 

OPr 
: '<pre>' {keepNewLine = true;} 
; 

CPr 
: '</pre>' {keepNewLine = false;} 
; 

NewLine 
: ('\r'? '\n' | '\r') {if(!keepNewLine) skip();} 
; 

Space 
: (' ' | '\t') {skip();} 
; 

,你可以用類測試:

import org.antlr.runtime.*; 

public class Main { 
    public static void main(String[] args) throws Exception { 
    PreLexer lexer = new PreLexer(new ANTLRFileStream("in.txt")); 
    PreParser parser = new PreParser(new CommonTokenStream(lexer)); 
    parser.parse(); 
    } 
} 

如果in.txt將包含:

foo bar 
<pre> 
a 

b 
</pre> 


baz 

運行Main類的輸出將是:

Word  'foo' 
Word  'bar' 
OPr  '<pre>' 
NewLine '\n' 
Word  'a' 
NewLine '\n' 
NewLine '\n' 
Word  'b' 
NewLine '\n' 
CPr  '</pre>' 
Word  'baz' 
+0

非常感謝!這確實比我一直試圖做的更容易...... ^^ – Korchkidu 2012-01-09 16:30:42