
/* Hello,
This code (second copy attached) compiles to recognize dotlists, ie "a", "a.b", etc. I want to report on incomplete list errors of the following kind
a. a.#
The parser 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
'>>' has difference operator precedence than '>', which means that Spirit is not able to flatten the whole expression leading to the attribute type mismatch you're seeing.
but it won't compile. Neither will this
start %= (id >> (*('.' >> id))) ; // XXX
Attribute-wise this will work. The problem is that the function signature
you're attaching doesn't match the attribute type exposed by the expression
it is attached to. It now exposes a fusion::vector
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.
HTH Regards Hartmut --------------- Meet me at BoostCon www.boostcon.com
Thanks.
*/ #include
#include #include #include #include #include #include #include #include #include #include #include #include
#include <iostream>
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<string> 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::vectorstd::string, 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<string> 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 <typename Iterator> // 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 <typename Iterator> // recognize a dotlist, ie (string % '.') struct dotlist_grammar : qi::grammar
{ dotlist_grammar() : dotlist_grammar::base_type(start) { using qi::int_; using qi::lexeme; start %= // (id >> (*('.' > id))) // XXX (id % '.') [ &print_dotlist ] ; } id_grammar<Iterator> id; qi::rule
start; }; template <typename Iterator> 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<Iterator> 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; }