|
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