Boost logo

Boost Users :

Subject: [Boost-users] [Boost.Spirit] Synthesised attributes and sub-rules
From: Vitaly Budovski (vbudovski+news_at_[hidden])
Date: 2010-10-13 23:46:27


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 <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)]
            )
        ;
    }

    qi::rule<Iterator> a_rule;
    qi::rule<Iterator> b_rule;
    qi::rule<Iterator> 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;
}


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