2012-09-03 82 views
3

我想分析可能含有像這樣的utf-8編碼的文本文件:Java - 解析文本文件 - 掃描儀,讀取器或其他東西?

int 1 
text " some text with \" and \\ " 
int list[-45,54, 435 ,-65] 
float list [ 4.0, 5.2,-5.2342e+4] 

在列表中的號碼之間用逗號隔開。在任何數字和任何符號(如逗號和括號)之間,空格都是允許的,但不是必需的。類似的文字和符號,就像list[

我已經通過強制掃描儀給我單個字符(將其分隔符設置爲空模式)來完成帶引號的字符串讀取,因爲我仍然認爲它會有用閱讀整數和浮點數,但我不知道了。

掃描儀總是接受一個完整的標記,然後嘗試匹配它。我所需要的是儘可能多(或儘可能少地)匹配,而忽略分隔符。

基本上此輸入

int list[-45,54, 435 ,-65] 

我希望能夠調用和得到這個

s.nextWord() // int 
s.nextWord() // list 
s.nextSymbol() // [ 
s.nextInt() // -45 
s.nextSymbol() // , 
s.nextInt() // 54 
s.nextSymbol() // , 
s.nextInt() // 435 
s.nextSymbol() // , 
s.nextInt() // -65 
s.nextSymbol() // ] 

等。或者,如果它本身不能解析雙打和其他類型,至少需要一個正則表達式的方法,返回匹配它的最大字符串(或錯誤),並將流的位置設置爲恰好在匹配它之後。

掃描儀可以以某種方式用於此?還是有另一種方法?我覺得這肯定是一件很平常的事情,但我似乎無法爲它找到合適的工具。

+0

我會使用正則表達式逐行解析該文件以提取令牌。這在語法檢查的同時會很有用。 – Dmitry

+1

我會用ANTLR編寫一個解析器。 – davidbuzatto

回答

1

我不是ANTLR專家,但這個ANTLR語法能夠解析代碼:

grammar Expressions; 

expressions 
    : expression+ EOF 
    ; 

expression 
    : intExpression 
    | intListExpression 
    | floatExpression 
    | floatListExpression 
    | textExpression 
    | textListExpression 
    ; 

intExpression  : intType INT; 
intListExpression : intType listType '[' (INT (',' INT)*)? ']'; 
floatExpression  : floatType FLOAT; 
floatListExpression : floatType listType '[' ((INT|FLOAT) (',' (INT|FLOAT))*)? ']'; 
textExpression  : textType STRING; 
textListExpression : textType listType '[' (STRING (',' STRING)*)? ']'; 

intType : 'int'; 
floatType : 'float'; 
textType : 'text'; 
listType : 'list'; 

INT : '0'..'9'+ 
    ; 

FLOAT 
    : ('0'..'9')+ '.' ('0'..'9')* EXPONENT? 
    | '.' ('0'..'9')+ EXPONENT? 
    | ('0'..'9')+ EXPONENT 
    ; 

STRING 
    : '"' (ESC_SEQ | ~('\\'|'"'))* '"' 
    ; 

fragment 
EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ; 

fragment 
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ; 

fragment 
ESC_SEQ 
    : '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\') 
    | UNICODE_ESC 
    | OCTAL_ESC 
    ; 

fragment 
OCTAL_ESC 
    : '\\' ('0'..'3') ('0'..'7') ('0'..'7') 
    | '\\' ('0'..'7') ('0'..'7') 
    | '\\' ('0'..'7') 
    ; 

fragment 
UNICODE_ESC 
    : '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT 
    ; 

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

當然,你將需要改進,但我認爲,這種結構容易插入代碼在解析器中做你想做的事(一種令牌流)。嘗試在ANTLRWorks調試以查看會發生什麼。

您的輸入,這是分析樹:

Parse Tree for OP input

編輯:我改變了它支持空列表。

+0

謝謝,這看起來很不錯。我從來沒有使用ANTLR,但我想我應該看看它。 – Neil

+0

不客氣!這是一本關於ANTLR的好書(作者是ANTLR的頭腦):http://www.amazon。COM /該-定形-的Antlr引用域特異性/ DP/0978739256/REF = sr_1_1?即= UTF8&QID = 1346709882&SR = 8-1&關鍵字= ANTLR – davidbuzatto

0

用類構造函數中的文件啓動掃描器。然後爲nextWord的方法,爲此,

public static nextWord(){ 
return(sc.findInLine("\\w+")); 
} 

可以導出用於使用上述例子與掃描器類的findInLine方法和改變正則表達式模式的其它方法的代碼。

+0

OP沒有問這個問題。 – davidbuzatto