/* Hello, This code compiles to recognize dotlists, ie "a", "a.b", etc. I want to report on incomplete list errors of the following kind a. a.# The par ser now detects such errors by failing to parse them completely. Instead I want to expect an id after a '.'. In dotlist_grammar() I wanted to replace this expression start %= (id % '.') ; with this one start %= (id >> (*('.' > id))) ; // XXX but it won't compile. Neither will this start %= (id >> (*('.' >> id))) ; // XXX What's wrong? Is there a difference between the synthesized attributes of the two alternative list expressions? Or is it a different bug? P.S. Both expressions seem to work for int_ instead of id. Thanks. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace ecgp { using namespace std; namespace qi = boost::spirit::qi; namespace ascii = boost::spirit::ascii; namespace fusion = boost::fusion; namespace phoenix = boost::phoenix; typedef ascii::space_type space; // structures, etc. struct structure { vector dotlist; int filler; // fusion requires >1 members?! void print(ostream& o) const { int i=0; BOOST_FOREACH(string s, dotlist) { if(++i > 1) o << '.'; o << s; } } }; ostream& operator<<(ostream& o, structure const & c) { c.print(o); return o; }; } BOOST_FUSION_ADAPT_STRUCT( ecgp::structure, (std::vector, dotlist) (int, filler) // fusion requires >1 members?! ) namespace ecgp { // actions void print_str(string const & v) { cout << "str: "; cout << v << endl; } void print_dotlist(vector const & v) { cout << "dotlist: "; int i=0; BOOST_FOREACH(string s, v) { if(++i > 1) cout << '.'; cout << s; } cout << endl; } void print_structure(structure const & v) { cout << "structure: "; print_dotlist(v.dotlist); cout << endl; } // grammars template // recognize an identifier struct id_grammar : qi::grammar { id_grammar() : id_grammar::base_type(start) { using ascii::alpha; using qi::lexeme; start %= lexeme[ +alpha ] [ &print_str ] ; } qi::rule start; }; template // recognize a dotlist, ie (string % '.') struct dotlist_grammar : qi::grammar(), space> { dotlist_grammar() : dotlist_grammar::base_type(start) { using qi::int_; using qi::lexeme; start %= // (id >> (*('.' > id))) // XXX (id % '.') [ &print_dotlist ] ; } id_grammar id; qi::rule(), space> start; }; template struct structure_grammar : qi::grammar { structure_grammar() : structure_grammar::base_type(start) { using qi::eps; using qi::int_; start %= ( dotlist >> (int_ | eps) // filler ) [ &print_structure ] ; } dotlist_grammar dotlist; qi::rule start; }; } int 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); structure list_container; structure_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; }