xpeg

xtalにxpegという名前でPEGが入ります。svn上では一応実装されています。


PEGとは
http://ja.wikipedia.org/wiki/%E8%A7%A3%E6%9E%90%E8%A1%A8%E7%8F%BE%E6%96%87%E6%B3%95

xtalで対応する演算子は次のようになります。

  • 並び: e1 >> e2
  • 選択: e1 | e2
  • ゼロ個以上の繰り返し: e*0
  • 1個以上の繰り返し: e*1
  • 1個以内の省略可能: e*-1

繰り返しは、一度マッチしたら離さない強欲な繰り返しです。
正規表現のように使いたい場合もあるでしょうから、正規表現の貪欲な繰り返し、非貪欲な繰り返しもサポートしています。

  • 1個以上の貪欲な繰り返し: e/1
  • 1個以上の非貪欲な繰り返し: e%1

これらは、*演算子と優先順位が等しいため選択されました。


とりあえず、使用例で雰囲気を。

String::splitにはxpegのパターンが渡せます。
,か:で区切りたい場合次のようにします。

str: "test,we:rwe,rr:rr,rr";

str.split("," | ":"){
  it.p;
}

//test
//we
//rwe
//rr
//rr
//rr

String::scanというメソッドも追加されました。

// lalphaとはaからzまでの範囲の文字にマッチするパターンである
lalpha: "a".."z";

// degitとは 0から9までの範囲の文字にマッチするパターンである
degit: "0".."9";

// many1_lalphaとは、1以上のlalphaにマッチするパターンである
many1_lalpha: lalpha*1;

// many0_degitとは、0以上のdegitにマッチするパターンである 
many0_degit: degit*0; 

// cap_many0_degitとは、many0_degitがマッチしたらkeyという名前でキャプチャするパターンである
cap_many0_degit: cap(key: many0_degit);

// patternとは、many1_alphaがマッチしたあと続けてcap_many0_degitがマッチするパターンである
pattern: many1_lalpha >> cap_many0_degit; 

str:"a65,b,cser4,eeeee44";

str.scan(pattern){
  it[""].p; // マッチした全体の文字列をp
  it["key"].p; // keyという名前でキャプチャした部分文字列をp
  "-----".p;
}
//a65
//65
//-----
//b
//
//-----
//cser4
//4
//-----
//eeeee44
//44
//-----


文字列だけでなく、イテレータに適用もできます。
たとえば、下のソースは、整数45の次の要素をキャプチャしてpする例です。

[0,32,45,53,23,23,1123,43,45,3].each.scan(pred(|x|x==45) >> cap(n: any)){
 it("n")[0].p;
}
      • -

なお、xpegはk.inabaさんのGreenPadのRSearchのソースをかなり参考にさせていただきました。
ありがとうございました。
http://www.kmonos.net/