StreamTokenizer は、当然だけど細かい仕様変更に耐えない。例えば、""中に改行を許すとかね。それ以外は、簡単に書けてよろしい。
Scanner は、Delimiter を食っちゃう。食われたものに関する情報を取る方法がない。nextByte() で取って来ることはできるんだろうけど、それじゃぁ、うれしくないです。Delimiter を""とか"."に指定することもできないらしい。"[\\s]"で良いだろうとか思うけど、そうすると、 f() とかが分離できない。かと言って"[()]"をdelimiterにすると、() が食われちゃう。
自分で書いた Matcher を使う奴は、ほとんどScannerと同じ実装になっていて、おそらく、当時(2007年)同じ問題にぶつかって、Scannerを読んだんじゃなかろうかと思います。Scanner を継承して変更と言う手もあるんだが、JDK依存経験的に避けた方が良いので、別に書いたのだと思う。まぁ、今見ると「そうじゃないだろ」ってところはあるんだけど、まぁ、動いているから良いか。
protected String next(Pattern pattern) {
String s = null;
while(true) {
Boolean match = scan.usePattern(pattern).lookingAt();
if (scan.hitEnd()) {
if (extendInput()) {
scan.reset();
continue;
}
}
if (match) {
s = scan.group(1);
cb.position(cb.position()+scan.end());
}
if (scan.hitEnd()) {
extendInput();scan.hitEnd();
}
return s;
パターンに()を置いて、group(1)を使うのは変。このlookingAt() を見つけるのに時間がかかった記憶がある。
CharBuffer を一つ一つ見る方法は、割と簡単に書けました。でも、Matcher より遅い感じがする。計ってないけど。
while(true) {
if (!hasRemaining()) return nextToken;
while(Character.isSpaceChar(ch)) {
if (!hasRemaining()) return nextToken;
ch = nextChar();
}
CharBuffer w = CharBuffer.allocate(BufferSize);
if (Character.isJavaIdentifierStart(ch)) {
とかやるんだが、Character.isSpaceChar(ch)が見るからに遅そう〜 ch==' ' とかすれば早いのかも :-p
ただ、これだと、数値のパターンとか結構複雑なので、そのあたりに苦労しそうです。
Tokenizerの実装を三種類試すのに、interface切って、共有部分を super class に抜き出して。最近は別classのが流行りかな。 この手のRefactoringは、Eclipseで楽勝。楽しいので、はなうた歌いながらやってたら、伯母に画面をのぞきこまれて「画面は全然楽しくない」と言われた。いや、楽しいんですが。
No comments:
Post a Comment