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に詳しい方は何かアドバイスありましたらお願いします。