雑多なメモ。大まかな方針とか。まあ、細かく書くと変更時にドキュメントに反映させるの面倒だし。
BNFねー。ruby使ってracc+strscanで書くってぐらいかねー。
んで、構文木をrubyのデータ構造に落とし込みます。messageとかenumとかの定義はネストできるので、そのへんをツリー構造にしておきます。
括弧とかセミコロンとかの不要な情報は持たず、名前とかそういう一つのノードに一つだけみたいな情報は、枝にはしない感じで。そのへんの基準は曖昧。
あと、名前は出てきた名前そのまま保持しておく感じ。
で、名前→型定義のハッシュを作ります。この段階で名前を絶対パス(?)にしておきます。
message Msg1 { optional int32 field1 = 1; message Msg2 { optional int32 field1 = 1; optional Msgx field1 = 2; }; optional Msg2 field2 = 2; }
みたいな感じでネストされた定義は、以下のような状態にします。(あくまでイメージです)
message Msg1 { optional int32 field1 = 1; optional Msg2 field2 = 2; } message Msg1.Msg2 { optional int32 field1 = 1; optional Msgx field1 = 2; };
それで「Msg1」と「Msg1.Msg2」をキーにしてそれぞれの定義をハッシュに放り込んでおきます。
んで、例えば、上記の「Msg2」で参照してる「Msgx」型を探すときは、「Msg1.Msg2.Msgx」→「Msg1.Msgx」→「Msgx」って順にハッシュに問い合わせてヒットしたらそこでそれを返す感じで。
これで、同じ名前がある場合、スコープが近い方にヒットするようになるはず。
そしてCコード生成。
Protocol Buffersでは定義がネストできるんですけど、JavaとかC++とかならクラス定義をネストできるから、それで解決してる模様。
んで、Cのソースの場合、名前付けのルールでオブジェクト指向を表現することになるんですけど、それだと定義がネストするときにどーしたものかと。
まあ、結局、名前付けのルールで実現するしかなさそうですが。多分、名前がずらずら並んでいく感じで。