構文解析では解析の途中結果を置いておくスタック等をグローバルに持っておくのが普通だが,
漏れはそれが嫌なのでそれらのparseに必要な情報をクラスにカプセル化することにした.
でspiritではsemantic actionを,関数ポインタあるいはfunctorを通じてcall backさせることにより実現しているが,
クラスのメンバ関数はspiritのcall backにできないことに気が付く.
(クラスメンバ関数のポインタ渡してもmessageをdispatchするオブジェクトを指定できない)
なので,しばらく考えた結果pimplイディオム(個人的にはピンプル♪と呼んでいるw)をグローバルなfunctorに適用する方法を思いつく.
#include#include using namespace std; using namespace boost::spirit; class SemanticAction { public: void doAction{cout << "do action" << endl;} }; class OnTrigger { public: OnTrigger(SemanticAction & action) : r_impl(action){} template void operator()(IteratorT first, IteratorT last) const { r_impl.doAction(); } private: SemanticAction & r_impl; }; class MyGrammar : public grammar { public: MyGrammar(SemanticAction & action) : act(action), onTrigger(action){} template struct definition { rule r; definition(MyGrammar const& self) { r = (*anychar_p)[self.onTrigger]; } rule const& start() const { return r; } }; private: SemanticAction & act; OnTrigger onTrigger; }; int main(int argc, char *argv[]) { SemanticAction act; MyGrammar g(act); parse_info<> info; info = parse("abc", g); return 0; }
definitionのコンストラクタの引数のselfってこういうときのためのものだったのねん.
あ,ピンプル♪じゃなくてリンプル♪じゃねーか!なんてツッコミはなしの方向でw