Boost logo

Boost Users :

Subject: Re: [Boost-users] [Boost.Spirit] Synthesised attributes and sub-rules
From: Hartmut Kaiser (hartmut.kaiser_at_[hidden])
Date: 2010-10-14 07:36:07


> 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 <boost/spirit/home/phoenix/bind/bind_function.hpp>
> #include <boost/spirit/include/phoenix_core.hpp>
> #include <boost/spirit/include/phoenix_operator.hpp>
> #include <boost/spirit/include/qi.hpp>
> #include <boost/tuple/tuple.hpp>
> #include <algorithm>
> #include <iterator>
> #include <string>
> #include <vector>
>
> using namespace boost::spirit;
> using namespace boost::spirit::qi;
>
> struct a_: qi::symbols<char, int>
> {
> a_()
> {
> add
> ("A", 0)
> ("B", 1)
> ("C", 2)
> ;
> }
>
> } a;
>
> struct b_: qi::symbols<char, boost::tuple<int, int> >
> {
> 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<char, int>
> {
> 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<int, 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.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<Iterator, std::vector<int>()>
> {
> 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<Iterator, std::vector<int>()> a_rule;
    qi::rule<Iterator, std::vector<int>()> b_rule;
    qi::rule<Iterator, std::vector<int>()> c_rule;

> qi::rule<Iterator, std::vector<int>()> 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<string_iterator> 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


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net