懲りずにパーサジェネレーター

http://panathenaia.halfmoon.jp/alang/castling.html
とりあえず当初の目的としては使える程度にはなったと思う……。
実はfirst-set作るところがバグってたりしたので、もっとテストケースが必要なのでしょうけれども。
コード自体もいくらOCamlと言ってもちょっと酷いぐらいぐちゃぐちゃになってきたため、少し整理しないとですね。
あとエラーリカバリでもうひとつややこしいのが出て来ました。S ::= A * B D | A * C DでDが来たときはrecovery/recovery conflict*1でUnexpected Dにしてしまいます。これは正しいと思うのですが、例えばS ::= * A C ; A ::= * B CでCが来たときは、Expected BにしてA ::= B * Cに遷移させるのか、Expected AにしてS ::= A * Cに遷移させるのかで、やっぱりrecovery先が衝突していて、しかしこの場合はUnexpected Cにするのも充分とは思えないのです。具体的には電卓の例……だと左再帰でちょっと複雑なのですがとにかくこれをUnexpectedにすると先頭に中置演算子が来ても左辺を補えなくなります。どっちかに決めてしまわないといけないのですが、どっちがいいでしょうか。今は手抜きでルールのindexの小さい方採用してますがあんまりですのでどっちかに決めたいです。

*1:他に思いつかないので使い続けてますがこの用語どうよ……。