libpcreのSML#バインディングを公開しました

pcrePerl 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 が結果になる)