/* Spirit1.cpp Egtra 2008/04/06 NYSL http://www.kmonos.net/nysl/ で公開します。 */ #include #include #include #include #include #include #include #include #include #include #include #include #include typedef std::map map_ss_t; typedef std::pair pair_ss_t; //独自のデータをセマンティックアクションに渡すパーサ。 template struct parser_transfer_context : public Context { private: typedef Context my_base_t; public: typedef boost::spirit::parser_context_linker context_linker_t; // typedef parser_transfer_context context_linker_t; template parser_transfer_context(Parser2 const& p) : my_base_t(p) {} template void pre_parse(Parser2 const& p, Scanner const& s) { my_base_t::pre_parse(p, s); static_cast(p).pre_parse(s); } template Result& post_parse(Result& hit, Parser2 const& p, Scanner const& s) { Result& hit2 = my_base_t::post_parse(hit, p, s); return static_cast(p).post_parse(hit2, s); } }; template struct grammar_base { typedef boost::spirit::grammar< Grammar, parser_transfer_context< Grammar, boost::spirit::parser_context > > type; }; struct pair_grammar : grammar_base::type { template struct result { typedef typename boost::spirit::match_result::type type; }; BOOST_STATIC_ASSERT(( std::tr1::is_same< boost::spirit::parser_result< pair_grammar, boost::spirit::scanner >::parser_type, pair_grammar >::value)); template void pre_parse(Scanner const& s) const { boost::fusion::for_each(pair, std::tr1::mem_fn(&std::string::clear)); } template Result& post_parse(Result& hit, Scanner const& s) const { hit.value(pair); return hit; } template struct definition { private: typedef boost::spirit::rule rule_t; public: rule_t root; definition(pair_grammar const& self) { using namespace boost::spirit; root = (*(anychar_p - ','))[assign_a(self.pair.first)] >> ',' >> *space_p >> (*(anychar_p - '\n'))[assign_a(self.pair.second)]; } rule_t const& start() const { return root; } }; private: pair_ss_t mutable pair; //許して }; //-------------------------------- //ここからはspirit2.cppと同じ struct dictionary_grammar : boost::spirit::grammar { dictionary_grammar(map_ss_t& m) : map(m) {} template struct definition { private: typedef boost::spirit::rule rule_t; public: rule_t root; pair_grammar pair; definition(dictionary_grammar const& self) { using namespace std::tr1::placeholders; typedef dictionary_grammar d; //最終行にも改行が必要という手抜き定義 root = *( pair[std::tr1::bind(&d::insert_map, self, _1)] >> '\n' ); } rule_t const& start() const { return root; } }; private: //ほらほら、これがセマンティックアクションで呼ばれる。 void insert_map(pair_ss_t const& pair) const { map.insert(pair); } map_ss_t& map; }; int main() { char const* s = "red,赤\n" "yellow,黄\n" "green,緑\n" "blue,青\n"; map_ss_t m; boost::spirit::parse(s, dictionary_grammar(m)); BOOST_FOREACH(map_ss_t::value_type& pair, m) { std::cout << pair.first << ", " << pair.second << '\n'; } std::cout << std::flush; }