Blog

Regexp::Trie を java に移植した

https://github.com/tokuhirom/regexp-trie

Regexp::Assemble っぽいことをするには graph-expression に入ってるやつを使えばいい、という話は昨日書いた のですが、生成コードがあまり綺麗ではないし、まあ今どき google-collections に依存しているところからも分かる通り、メンテナンスはされていないようです。

というわけで、@dankogai の Regexp::Trie を java に移植してみました。

使い方は以下の様になります。Perl5 とほぼ同じ感じで使えていますね(例は例によって groovy)。

@GrabResolver(name='tokuhirom', root='https://tokuhirom.github.io/maven/releases/')
@Grab('me.geso:regexp-trie:0.0.1')

import me.geso.regexp_trie.RegexpTrie;

def trie = new RegexpTrie();
["foobar", "fooxar", "foozap", "fooza"].forEach {
    trie.add(it);
}
println(trie.regexp()) // → (?:foo(?:bar|xar|zap?))

依存もないし、シンプルなコードなので使いやすいと思います。

必要な JDK バージョンは 7 です。


コードは Perl 版に比べて長くなっているが、読みやすくなっていると思います。 長くなってる感じがするのは、元のコードが dan さんのコードなので、めっちゃ詰めて書いてあるからというのもでかい。

今回、唯一詰まったのは、

TreeMap<String, TreeMap<String, TreeMap<String, ...>

みたいな再帰的な型をどうやって定義しようかな、というところだったのですが、これは

class CharTrie extends TreeMap<String, CharTrie> { }

とすればよいのでした。

あと、当初は Character 型を Trie のキーにしていたのだが、null は TreeMap の key に使えないということに気づいたので、String 型に変更し、terminator は "" で表現することに変更しました。 (本当は Terminator オブジェクトとツリーオブジェクトを定義する方が Java らしいのかもしれないけど、めんどくさいし今動いてるのでいいということにします。もっと Java らしくてかっこいい設計が思いつく人がいたら教えてほしいです。)