
I recently tried to combine an arbitrary number of rules as alternatives in Boost.Spirit.Qi. Since rules are implemented as objects it seemed feasible to me. My motivation was to make certain parts of my grammar easily extensible. Unfortunately, I ran into some problems, so I wrote a simple program (see attachment for the complete code) demonstrating the unexpected behavior. Here's the key part:
// "Dynamic" version - Does not compile! :( /* std::vector<rule_t> rules;
rules.push_back(qi::char_('a')[qi::_r1 = px::val(0)]); rules.push_back(qi::char_('b')[qi::_r1 = px::val(1)]); rules.push_back(qi::char_('c')[qi::_r1 = px::val(2)]);
std::vector<rule_t>::iterator i(rules.begin()), last(rules.end());
rule_t grammar;
grammar = (*i)(qi::_r1); //[no_op]
for(++i; i!=last; ++i) { grammar = grammar.copy() | (*i)(qi::_r1); //[no_op] } */
// "Dynamic" version - Kind of works! :-/
std::vector<rule_t> rules;
rules.push_back(qi::char_('a')[qi::_r1 = px::val(0)]); rules.push_back(qi::char_('b')[qi::_r1 = px::val(1)]); rules.push_back(qi::char_('c')[qi::_r1 = px::val(2)]);
std::vector<rule_t>::iterator i(rules.begin()), last(rules.end());
qi::rule<iterator_t, int()> temp;
temp = (*i)(qi::_val); //[no_op]
for(++i; i!=last; ++i) { temp = temp.copy() | (*i)(qi::_val); //[no_op] }
rule_t grammar;
grammar = temp[qi::_r1 = qi::_1];
Now, I suppose that the first version (commented out) doesn't compile, because I'm not passing the inherited attribute down to grammar.copy(). I would love to know if there's a better way of doing this than the workaround that is the second version.
The second version actually compiles and it seems to do the right thing. However, once I attach a simple semantic action as indicated in the code using comments (see "[no_op]"), the behavior becomes really weird. Rather than printing 0,1,2 as before, the program prints 0,0,2. So I'm wondering, is what I'm trying to accomplish resulting in undefined behavior? Is this a bug? Or, quite possibly, am I just using something (e.g. semantic actions?) the wrong way?
Just as a heads up: I saw your question on stackoverflow and I'm currently trying to find a solution for you. Regards Hartmut --------------- http://boost-spirit.com