Xtal PEG

ちょこちょこと実装を進めています。

ローカルでは、文字列分割パーサが次のように書けるところまで出来ました。

make_split_parser: fun(patt){
 elem: peg::join( (peg::anych - patt)*0 );
 return elem >> (-patt >> elem)*0;
}

split_p: make_split_parser(peg::chset(":-"));
ret: [];
if(split_p.parse_string("a:bb-cc:d", ret)){
  ret.p; // [a,bb,cc,d]
}

これマニュアル書くの大変だ。

                                                                                    • -

マニュアルテスト

peg::Parser
 パーサクラス
 Parser::parse_string: method(source, result)
 文字列sourceをパースし、キャプチャーした値を配列resultに格納していく
 パースに成功したかどうかは戻り値で知らされる
                                                                                      • -
peg::anych
入力文字列を一つ読み取るパーサを返す。文字列が終わっていない限り、パースは成功する。
読み取った文字をキャプチャーする。
--コード例---------------------
ret: [];
if(peg::anych.parse_string("test", ret)){
  ret.p; //=> [t]
}
parser * number
parserを最低number回以上繰り返すパーサを返す。 elem*0 は PEGの elem* に相当し、 elem*1 はPEGの elem+ に相当する。
number回パースに成功したら、全体の結果も成功となる。

もしnumberの値がマイナスのとき、最高number回繰り返すパーサとなる。 elem*-1は PEGの elem? に相当する。
--コード例---------------------
ret: [];
if((peg::anych*1).parse_string("test", ret)){
  ret.p; //=> [t,e,s,t]
} 
"str"
入力文字列がstrと等しかったら成功するパーサを返す。
読み取った文字列をキャプチャーする。
--コード例---------------------
ret: [];
if(("test"*1).parse_string("testtest", ret)){
  ret.p; //=> [test, test]
}
left_parser >> right_parser
left_parserを呼び出し、left_parserがパースに成功したら続けてright_parserを呼び出すパーサを返す。
どちらのパースにも成功したら、全体の結果も成功となる。
--コード例---------------------
ret: [];
if((peg::anych >> peg::anych).parse_source("test", ret)){
  ret.p; //=> [t,e]
}
left_parser | right_parser
left_parserを呼び出し、left_parserがパースに失敗したら続けてright_parserを呼び出すパーサを返す。
どちらかのパースにも成功したら、全体の結果も成功となる。left_parserが成功したら、right_parserは呼び出されない。
--コード例---------------------
ret: [];
if((("foo" | "bar")*1).parse_source("foobar", ret)){
  ret.p; //=> [foo,bar]
}
peg::chset(str)
文字列strのどれかの文字と等しかったら成功するパーサを返す。
等しかった一つの文字をキャプチャーします。
--コード例---------------------
ret: [];
if((peg::chset("abcd")*0).parse_source("abdec", ret)){
  ret.p; //=> [a,b,d]
}
peg::join(parser)
parserがキャプチャーした値を連結するパーサを返す。
parserがパースに成功したら、このパーサも成功する。
--コード例---------------------
ret: [];
if(peg::join(peg::chset("abcd")*0).parse_source("abdec", ret)){
  ret.p; //=> [abd]
}
-parser
parserがキャプチャーした値を無視するパーサを返す。
parserがパースに成功したら、このパーサも成功する。
--コード例---------------------
ret: [];
if((peg::anych >> -peg::anych >> peg::anych).parse_source("test", ret)){
  ret.p; //=> [t,s]
}

他にも色々と用意してますが、大体こんな感じということで。
AND述語とNOT述語はどの演算子を使うか迷っています。Xtalでは前置&と前置!は演算子オーバーロード対象ではありませんから。

Xtalのpegのパーサ生成器は、値のキャプチャーをやりやすく、構文木を作りやすくする方向でデザインしています。
pegに詳しい方は何かアドバイスありましたらお願いします。