3

次のようなものを含む可能性のあるUTF8でエンコードされたテキストファイルを解析したいと思います。

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

リスト内の数字はコンマで区切られます。ここでは、空白は許可されていますが、数字とコンマや角かっこなどの記号の間にある必要はありません。同様に、単語や記号についても、list[

引用符で囲まれた文字列の読み取りは、Intとfloatの読み取りに役立つと思っていたので、Scannerに単一の文字を強制的に(区切り文字を空のパターンに設定して)実行しましたが、もうわかりません。

スキャナーは常に完全なトークンを取得し、それを照合しようとします。私が必要としているのは、区切り文字を無視して、できるだけ多く(またはできるだけ少なく)一致するようにすることです。

基本的にこの入力の場合

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() // ]

等々。

または、doubleや他の型自体を解析できなかった場合、少なくとも正規表現を取得するメソッドは、それに一致する最大の文字列(またはエラー)を返し、一致したものの直後にストリーム位置を設定します。

スキャナーはどういうわけかこれに使用できますか?それとも別のアプローチがありますか?これは非常に一般的なことだと思いますが、適切なツールを見つけることができないようです。

4

2 に答える 2

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デバッグで試して、何が起こるかを確認してください。

入力として、これは解析ツリーです。

OP 入力の解析ツリー

編集:空のリストをサポートするように変更しました。

于 2012-09-03T21:38:47.043 に答える
0

クラスコンストラクターのファイルを使用してスキャナーを開始します。次に、nextWordメソッドの場合、これを実行します。

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

上記の例でScannerクラスのfindInLineメソッドを使用し、正規表現パターンを変更して、他のメソッドのコードを導出できます。

于 2012-09-03T21:15:23.320 に答える