libpcreのSML#バインディングを公開しました
pcre は Perl Compatible Regular Expressions の略で、Perl互換の正規表現ライブラリです。
SML#からこのライブラリを使うラッパーを書いたので公開しました > https://github.com/eldesh/pcre_sharp
基本的なマッチの機能と、subpatternにマッチした部分文字列の取り出し(後述)が出来ます。
バインディングには微妙に手間取りました(pcre_execがメンドイ)。あとはSML側で提供するインターフェースが悩みどころです。
ライブラリの機能としては 最適化用追加情報の取得、jit や utf8/16/32 対応がありそうですが、まぁ多分手数の問題なのでimportだけでもボチボチやって行く予定。
使い方
cloneしたディレクトリでmakeすればライブラリ(単なるオブジェクトファイル)とサンプルプログラム(./test) がビルド出来ます。
ユーザが使うのにとりあえず必要な関数は Pcre.match (Pcre.Open.=~) です。
# Pcre.Open.=~; val it = fn : string * string -> string option list option
普通にマッチするとSOME []が返ります。第二引数が正規表現のパターン。
# Pcre.match "fooooo" "fo*" = SOME[]; val it = true : bool
返ってくるリストは subpattern にマッチした部分文字列のリストです。
# fun println s = print (s^"\n"); val println = fn : string -> unit # fun test x = app (fn x=> println (getOpt (x,"not match"))) x; val test = fn : string option list -> unit # test(valOf(Pcre.match "192.168.foo.bar" "(\\d{1,3})\\.(\\d{1,3})\\.(\\w+)\\.(\\w+)")); 192 168 foo bar val it = () : unit
()で括った個所にマッチした文字列を取り出すことが出来ます。
で、個々の文字列がなぜoptionなのかというと、正規表現のパターンによっては、全体がマッチしているのに subpattern にはマッチしないということが起き得るからです。
# test(valOf(Pcre.match "ab" "(a|(b))")); a not match val it = () : unit
この例ではパターン全体にマッチしているのに "(b)" にはマッチしていないため、"not match" と表示されています。全体の値は
SOME [SOME "a", NONE]
となります。
検討事項
やはりsubpatternにマッチした文字列を取り出すのがめんどくさいので op=~ を使う場合にはNONEをフィルタしちゃってもいいかなという気がしてきました。(そうすれば string list option が結果になる)