Ticket #8556: actiontest.cpp

File actiontest.cpp, 2.5 KB (added by Jeff Trull (@…, 9 years ago)

standalone test case

Line 
1// a test case for combining semantic actions with synthesized attributes in the same rule
2
3#include <iostream>
4#include <vector>
5#include <string>
6#include <iterator>
7
8#include <boost/spirit/include/qi.hpp>
9#include <boost/spirit/include/phoenix.hpp>
10
11void action_func(std::string const& a, std::string const& b)
12{
13 std::cout << "a=" << a << ", b=" << b << std::endl;
14}
15
16int main()
17{
18 typedef std::string::iterator Iterator;
19
20 namespace qi = boost::spirit::qi;
21 using boost::spirit::_1;
22 using boost::spirit::_2;
23 using boost::spirit::_3;
24 using boost::spirit::_val;
25 using boost::phoenix::bind;
26 using boost::phoenix::push_back;
27
28 typedef std::vector<std::string> result_t;
29 boost::spirit::qi::rule<Iterator, result_t()> testrule;
30
31 // Goal:
32 // Simultaneously store the synthesized attributes (a vector of three size 1 strings)
33 // and call the semantic action function on the last two values
34
35 // Actual Result:
36 // I can either store the attribute, or call the function, but not both (compile error)
37
38 // things that compile successfully:
39
40 // testrule = qi::string("A") >> qi::string("B") >> qi::string("C") ; // does not call action
41
42 // does not store the synthesized attribute:
43 // testrule = (qi::string("A") >> qi::string("B") >> qi::string("C"))[bind(action_func, _1, _2)] ;
44
45 // my desired syntax (does not compile):
46 testrule %= (qi::string("A") >> qi::string("B") >> qi::string("C"))[bind(action_func, _1, _2)] ;
47
48
49 // this is a workaround but is not as concise
50/*
51 testrule = (qi::string("A") >> qi::string("B") >> qi::string("C"))[bind(action_func, _1, _2),
52 push_back(_val, _1),
53 push_back(_val, _2),
54 push_back(_val, _3)];
55*/
56
57 std::string testdata("ABC");
58 result_t result;
59 Iterator beg = testdata.begin();
60 if (!qi::parse(beg, testdata.end(), testrule, result))
61 {
62 std::cerr << "parse failed" << std::endl;
63 return 1;
64 }
65 if (beg != testdata.end())
66 {
67 std::cerr << "not all input consumed! Remaining: ";
68 std::copy(beg, testdata.end(), std::ostream_iterator<char>(std::cerr, ""));
69 std::cerr << std::endl;
70 return 2;
71 }
72
73 std::cout << "parsed vector result:" << std::endl;
74 std::copy(result.begin(), result.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
75
76 return 0;
77}