// a test case for combining semantic actions with synthesized attributes in the same rule #include #include #include #include #include #include void action_func(std::string const& a, std::string const& b) { std::cout << "a=" << a << ", b=" << b << std::endl; } int main() { typedef std::string::iterator Iterator; namespace qi = boost::spirit::qi; using boost::spirit::_1; using boost::spirit::_2; using boost::spirit::_3; using boost::spirit::_val; using boost::phoenix::bind; using boost::phoenix::push_back; typedef std::vector result_t; boost::spirit::qi::rule testrule; // Goal: // Simultaneously store the synthesized attributes (a vector of three size 1 strings) // and call the semantic action function on the last two values // Actual Result: // I can either store the attribute, or call the function, but not both (compile error) // things that compile successfully: // testrule = qi::string("A") >> qi::string("B") >> qi::string("C") ; // does not call action // does not store the synthesized attribute: // testrule = (qi::string("A") >> qi::string("B") >> qi::string("C"))[bind(action_func, _1, _2)] ; // my desired syntax (does not compile): testrule %= (qi::string("A") >> qi::string("B") >> qi::string("C"))[bind(action_func, _1, _2)] ; // this is a workaround but is not as concise /* testrule = (qi::string("A") >> qi::string("B") >> qi::string("C"))[bind(action_func, _1, _2), push_back(_val, _1), push_back(_val, _2), push_back(_val, _3)]; */ std::string testdata("ABC"); result_t result; Iterator beg = testdata.begin(); if (!qi::parse(beg, testdata.end(), testrule, result)) { std::cerr << "parse failed" << std::endl; return 1; } if (beg != testdata.end()) { std::cerr << "not all input consumed! Remaining: "; std::copy(beg, testdata.end(), std::ostream_iterator(std::cerr, "")); std::cerr << std::endl; return 2; } std::cout << "parsed vector result:" << std::endl; std::copy(result.begin(), result.end(), std::ostream_iterator(std::cout, "\n")); return 0; }