Boost.Spirit.Qiで引数を取るようなrule・・・でいいのかな?
typedef qi::rule<Iterator, unsigned int(), ascii::space_type> rule_t; rule_t XXX_; rule_t YYY_; rule_t ZZZ_; XXX_ %= qi::omit[qi::no_case[ascii::string("XXX")] >> *qi::blank >> "=" >> *qi::blank] >> qi::uint_; YYY_ %= qi::omit[qi::no_case[ascii::string("YYY")] >> *qi::blank >> "=" >> *qi::blank] >> qi::uint_; ZZZ_ %= qi::omit[qi::no_case[ascii::string("ZZZ")] >> *qi::blank >> "=" >> *qi::blank] >> qi::uint_; // | | //↓ +------------------------この部分をまとめたい---------------------------------| // XXX_ %= omitted("XXX") >> qi::uint_; YYY_ %= omitted("YYY") >> qi::uint_; ZZZ_ %= omitted("ZZZ") >> qi::uint_;
↑こんな風にしたかった。
つまり、文字列を引数に取るqi::ruleが欲しかったわけで。
Twitterで聞いたら[twitter:@kikairoya]さんからqi::_rNを使う方法を教えてもらった。
_r1, _r2... , _rN
http://www.boost.org/doc/libs/1_47_0/libs/spirit/doc/html/spirit/qi/quick_reference/phoenix.html
The enclosing rule's Nth inherited attribute.
typedef qi::rule<iterator, void(std::string), ascii::space_type> subrule_type; //(1) typedef qi::rule<iterator, unsigned(), ascii::space_type> rule_type; int main() { subrule_type omitted; omitted %= qi::omit[qi::no_case[ascii::string(qi::_r1)] >> *qi::blank >> "=" >> *qi::blank]; //(2) rule_type x, y; x %= omitted(std::string("XXX")) >> qi::uint_; y %= omitted(std::string("YYY")) >> qi::uint_; const std::string s = "XXX=3"; iterator ite = s.begin(); unsigned res = 0; qi::phrase_parse(ite, s.end(), x, ascii::space, res); std::cout << res << std::endl; }
※)頂いたコードを一部改変
(1)subrule_typeのtypedefのところでvoid(std::string)という風にして、
(2)そのruleを定義するときにqi::_r1で受け取ればいいらしい。
さらに、omitted(std::string("XXX"))のstd::stringが冗長だと思って、どうにかしようとしたらこんな風に。
omitted %=
qi::omit[
qi::no_case[
ascii::string(
phoenix::construct<std::string>(
qi::_r1))] >> *qi::blank >> "=" >> *qi::blank];
phoenixを使って、引数に文字列が渡されたら、それからstd::stringを構築する。
ただし、残念なことに
XXX_ %= omitted_("XXX") >> qi::uint_;
とかやっても
C:\boost\boost_1_46_1\boost/fusion/container/vector/detail/vector_n.hpp(50) : error C2536: 'boost::fusion::vector_data1
::boost::fusion::vector_data1 ::m0' : クラス、構造体、共用体のメンバは、初期化できません。
with
[
T0=const char [4]
]
C:\boost\boost_1_46_1\boost/fusion/container/vector/detail/vector_n.hpp(71) : 'boost::fusion::vector_data1::m0' の宣言を確認してください。
with
[
T0=const char [4]
]
C:\boost\boost_1_46_1\boost/fusion/container/vector/detail/vector_n.hpp(50): クラス テンプレート のメンバ関数 'boost::fusion::vector_data1::vector_data1(const boost::fusion::vector_data1 &)' のコンパイル中
with
[
T0=const char [4]
]
C:\boost\boost_1_46_1\boost/fusion/container/vector/detail/vector_n.hpp(77) : コンパイルされたクラスの テンプレート のインスタンス化 'boost::fusion::vector_data1' の参照を確認してください
with
......
とか怒られちゃう(const charの配列が渡されてるのがよくない?)ので強制的にchar const *に変換すれば・・・いいのかしら・・・
XXX_ %= omitted_(&*"XXX") >> qi::uint_;