[Boost.Spirit] Synthesised attributes and sub-rules

Hi,
Please have a look at the code below. I would like to be able to split
up the start rule into several sub-rules (currently commented out).
The problem is, I'm not sure how to reference the synthesised
attribute from the grammar in these sub-rules? Is it possible? I would
like to do this so that the grammar is more readable, as the actual
rules have a bit more complexity than in this simple example.
Thank you,
Vitaly
----------------
#include

Please have a look at the code below. I would like to be able to split up the start rule into several sub-rules (currently commented out). The problem is, I'm not sure how to reference the synthesised attribute from the grammar in these sub-rules? Is it possible? I would like to do this so that the grammar is more readable, as the actual rules have a bit more complexity than in this simple example.
That should be easy, see below.
#include
#include #include #include #include #include <algorithm> #include <iterator> #include <string> #include <vector> using namespace boost::spirit; using namespace boost::spirit::qi;
struct a_: qi::symbols
{ a_() { add ("A", 0) ("B", 1) ("C", 2) ; } } a;
struct b_: qi::symbols
> { b_() { add ("x", boost::make_tuple(3, 2)) ("y", boost::make_tuple(4, 0)) ("z", boost::make_tuple(5, 1)) ; } } b;
struct c_: qi::symbols
{ c_() { add ("E", 6) ("D", 7) ("J", 8) ; } } c;
void insert_a(const int &value, const boost::optional<unsigned int> &count, std::vector<int> &result) { unsigned int c = 1; if(count) { c += *count; }
for(unsigned int i = 0; i < c; ++i) { result.push_back(value); } } void insert_b(const boost::tuple
&value, const boost::optional<unsigned int> &count, std::vector<int> &result) { unsigned int c = 1; if(count) { c += *count; } for(unsigned int i = 0; i < c; ++i) { result.push_back(value.get<0>()); result.push_back(value.get<1>()); } } void insert_c(const int &value, const boost::optional<unsigned int> &count, std::vector<int> &result) { unsigned int c = 1; if(count) { c += *count; }
for(unsigned int i = 0; i < c; ++i) { result.push_back(value); } }
template<typename Iterator> struct test_grammar: qi::grammar
{ test_grammar(): test_grammar::base_type(start) { using boost::phoenix::bind; /*a_rule = ( +(a >> -uint_)[bind(insert_a, _1, _2, _val)] ) ;
b_rule = ( +(b >> -uint_)[bind(insert_b, _1, _2, _val)] ) ;
c_rule = ( +(c >> -uint_)[bind(insert_c, _1, _2, _val)] ) ;*/
start = ( +(a >> -uint_)[bind(insert_a, _1, _2, _val)] | +(b >> -uint_)[bind(insert_b, _1, _2, _val)] | +(c >> -uint_)[bind(insert_c, _1, _2, _val)] ) ;
a_rule = +(a >> -uint_)[bind(insert_a, _1, _2, _val)]; b_rule = +(b >> -uint_)[bind(insert_b, _1, _2, _val)]; c_rule = +(c >> -uint_)[bind(insert_c, _1, _2, _val)]; start = a_rule | b_rule | c_rule;
}
qi::rule<Iterator> a_rule; qi::rule<Iterator> b_rule; qi::rule<Iterator> c_rule;
qi::rule
qi::rule
start; }; int main() { std::string s("A3BAC6");
typedef std::string::iterator string_iterator; string_iterator first = s.begin(); string_iterator last = s.end(); typedef test_grammar
test_grammar; test_grammar test_parser; std::vector<int> v; bool result = parse(first, last, test_parser, v); if(result && first == last) { std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << std::endl; } else { std::cerr << "Failed to parse expression\n"; v.clear(); }
std::string s2("xy2z3"); string_iterator first2 = s2.begin(); string_iterator last2 = s2.end(); bool result2 = parse(first2, last2, test_parser, v); if(result2 && first2 == last2) { std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << std::endl; } else { std::cerr << "Failed to parse expression\n"; v.clear(); }
std::string s3("EDJ"); string_iterator first3 = s3.begin(); string_iterator last3 = s3.end(); bool result3 = parse(first3, last3, test_parser, v); if(result3 && first3 == last3) { std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << std::endl; } else { std::cerr << "Failed to parse expression\n"; v.clear(); }
return 0; }
HTH Regards Hartmut --------------- http://boost-spirit.com

On 14 October 2010 22:36, Hartmut Kaiser
That should be easy, see below.
start = a_rule | b_rule | c_rule;
qi::rule
a_rule; qi::rule b_rule; qi::rule c_rule; HTH Regards Hartmut --------------- http://boost-spirit.com
I think I tried something like that, but it didn't work. Unless I'm
mistaken, each of those rules will create their own std::vector<int>
instance, so the values will not end up inserted into the vector
specified in the grammar parameter.
I was able to eventually achieve my goal by specifying each of the
rules like so:
qi::rule

On 14 October 2010 22:36, Hartmut Kaiser
That should be easy, see below.
start = a_rule | b_rule | c_rule;
<snip>
qi::rule
a_rule; qi::rule b_rule; qi::rule c_rule; qi::rule
start;
Hi Hartmut,
Thanks for your help. I've upgraded my version of Spirit to the one
from Boost 1.44, so things work better now. However, I'm still unable
to compile when I change my rule to something like: start = a_rule |
*b_rule. The * and + operators cause the compiler to generate the
following error: boost/spirit/home/qi/detail/assign_to.hpp:109: error:
invalid static_cast from type ‘const std::vector
participants (2)
-
Hartmut Kaiser
-
Vitaly Budovski