/* This code (second copy attached) compiles to recognize dotlists, ie (string % '.'), with the added expectation that an id will follow a '.'. The solution is unsatisfactory because it requires a structure to contain a dotlist, and because it uses explicit semantic actions. Do you have any suggestions about how to obviate the semantic actions? The following pseudo-code illustrates something I don't know how to do, although I am pretty sure the solution is obvious to Spirit/Fusion users. If that's true, I think it will solve the problem of the extraneous structure. This pseudo-grammar exposes attribute vector instead of some structure. What I want is to push a recognized string onto that vector, rather than onto a part of a structure. That is what I mean below by "_val.push_back(_1)" If you can show me the expression which does what I need, I thank you. template struct slotchain_grammar : qi::grammar(), space> { slotchain_grammar() : slotchain_grammar::base_type(start) { using namespace qi::labels; using phoenix::at_c; using phoenix::push_back; start = id [ "_val.push_back(_1)" ] >> *('.' > id [ "_val.push_back(_1)" ]) ; } id_grammar id; qi::rule(), space> start; }; */ #include #include #include #include #include #include #include #include #include #include #include namespace ecgp { using namespace std; namespace fusion = boost::fusion; namespace phoenix = boost::phoenix; namespace qi = boost::spirit::qi; namespace ascii = boost::spirit::ascii; typedef ascii::space_type space; // structures struct slotchain { vector dotlist; int filler; // fusion requires >1 members?! }; } BOOST_FUSION_ADAPT_STRUCT( ecgp::slotchain, (std::vector, dotlist) (int, filler) ) namespace ecgp { // grammars template struct id_grammar : qi::grammar { id_grammar() : id_grammar::base_type(start) { using qi::lexeme; using ascii::alnum; start %= lexeme[+alnum]; } qi::rule start; }; template struct slotchain_grammar : qi::grammar { slotchain_grammar() : slotchain_grammar::base_type(start) { using namespace qi::labels; using phoenix::at_c; using phoenix::push_back; start = id [push_back(at_c<0>(_val), _1)] >> *('.' > id [push_back(at_c<0>(_val), _1)]) ; } id_grammar id; qi::rule start; }; } main() { using namespace std; using namespace ecgp; using namespace boost; typedef string::const_iterator string_iterator; string s; cout << "enter a dotlist:\n"; while (getline(cin, s)) { trim(s); string_iterator iter = s.begin(); string_iterator end = s.end(); string target(iter, end); slotchain list_container; slotchain_grammar g; bool r = phrase_parse(iter, end, g, boost::spirit::ascii::space, list_container); if (r && iter == end) { cout << "OK: " << target; cout << endl << endl; } else { cout << "FAIL"; if(! r) cout << "(p)"; if(iter != end) cout << "(e)"; cout << ": " << target; cout << endl << endl; } cout << "enter a dotlist:\n"; } return 0; }