1 /*=============================================================================
2 Copyright (c) 2001-2011 Hartmut Kaiser
3 Copyright (c) 2001-2011 Joel de Guzman
4
5 Distributed under the Boost Software License, Version 1.0. (See accompanying
6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 =============================================================================*/
8
9 #include <boost/config/warning_disable.hpp>
10 #include <boost/detail/lightweight_test.hpp>
11
12 #include <boost/spirit/include/phoenix_limits.hpp>
13
14 #include <boost/fusion/include/struct.hpp>
15 #include <boost/fusion/include/nview.hpp>
16
17 #include <boost/spirit/include/qi_char.hpp>
18 #include <boost/spirit/include/qi_string.hpp>
19 #include <boost/spirit/include/qi_numeric.hpp>
20 #include <boost/spirit/include/qi_operator.hpp>
21 #include <boost/spirit/include/qi_nonterminal.hpp>
22 #include <boost/spirit/include/qi_auxiliary.hpp>
23
24 #include <iostream>
25 #include <vector>
26 #include <string>
27 #include "test.hpp"
28
29 ///////////////////////////////////////////////////////////////////////////////
30 struct test_data
31 {
32 std::string s1;
33 std::string s2;
34 int i1;
35 double d1;
36 std::string s3;
37 };
38
39 BOOST_FUSION_ADAPT_STRUCT(
40 test_data,
41 (int, i1)
42 (std::string, s1)
43 (std::string, s2)
44 (std::string, s3)
45 (double, d1)
46 )
47
48 ///////////////////////////////////////////////////////////////////////////////
49 struct test_int_data1
50 {
51 int i;
52 };
53
54 // we provide a custom attribute transformation taking copy of the actual
55 // attribute value, simulating more complex type transformations
56 namespace boost { namespace spirit { namespace traits
57 {
58 template <>
59 struct transform_attribute<test_int_data1, int, qi::domain>
60 {
61 typedef int type;
preboost::spirit::traits::transform_attribute62 static int pre(test_int_data1& d) { return d.i; }
postboost::spirit::traits::transform_attribute63 static void post(test_int_data1& d, int i) { d.i = i; }
failboost::spirit::traits::transform_attribute64 static void fail(test_int_data1&) {}
65 };
66 }}}
67
68 ///////////////////////////////////////////////////////////////////////////////
69 struct test_int_data2
70 {
71 int i;
72 };
73
74 // we provide a simple custom attribute transformation utilizing passing the
75 // actual attribute by reference
76 namespace boost { namespace spirit { namespace traits
77 {
78 template <>
79 struct transform_attribute<test_int_data2, int, qi::domain>
80 {
81 typedef int& type;
preboost::spirit::traits::transform_attribute82 static int& pre(test_int_data2& d) { return d.i; }
postboost::spirit::traits::transform_attribute83 static void post(test_int_data2&, int const&) {}
failboost::spirit::traits::transform_attribute84 static void fail(test_int_data2&) {}
85 };
86 }}}
87
88 ///////////////////////////////////////////////////////////////////////////////
89 int
main()90 main()
91 {
92 using spirit_test::test_attr;
93 namespace qi = boost::spirit::qi;
94 namespace fusion = boost::fusion;
95
96 {
97 std::vector<test_int_data1> v;
98 qi::rule<char const*, int()> r = qi::int_;
99
100 BOOST_TEST(test_attr("1,2", r % ',', v));
101 BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
102 }
103
104 {
105 std::vector<double> v;
106 qi::rule<char const*, int()> r = qi::int_;
107
108 BOOST_TEST(test_attr("1,2", r % ',', v));
109 BOOST_TEST(v.size() == 2 && v[0] == 1.0 && v[1] == 2.0);
110 }
111
112 {
113 std::vector<test_int_data1> v;
114
115 // this won't compile as there is no defined transformation for
116 // test_int_data1 and double
117 // BOOST_TEST(test_attr("1.0,2.2", qi::attr_cast(qi::double_) % ',', v));
118 // BOOST_TEST(test_attr("1.0,2.2"
119 // , qi::attr_cast<test_int_data1>(qi::double_) % ',', v));
120
121 BOOST_TEST(test_attr("1.0,2.2"
122 , qi::attr_cast<test_int_data1, int>(qi::double_) % ',', v));
123 BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
124
125 qi::rule<char const*, int()> r = qi::double_;
126
127 v.clear();
128 BOOST_TEST(test_attr("1.0,2.0", r % ',', v));
129 BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
130 }
131
132 // testing explicit transformation if attribute is taken by reference
133 {
134 test_int_data2 d = { 0 };
135 BOOST_TEST(test_attr("1", qi::attr_cast(qi::int_), d));
136 BOOST_TEST(d.i == 1);
137 BOOST_TEST(test_attr("2", qi::attr_cast<test_int_data2>(qi::int_), d));
138 BOOST_TEST(d.i == 2);
139 BOOST_TEST(test_attr("3", qi::attr_cast<test_int_data2, int>(qi::int_), d));
140 BOOST_TEST(d.i == 3);
141 }
142
143 {
144 std::vector<test_int_data2> v;
145
146 BOOST_TEST(test_attr("1,2", qi::attr_cast(qi::int_) % ',', v));
147 BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
148
149 v.clear();
150 BOOST_TEST(test_attr("1,2"
151 , qi::attr_cast<test_int_data2>(qi::int_) % ',', v));
152 BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
153
154 v.clear();
155 BOOST_TEST(test_attr("1,2"
156 , qi::attr_cast<test_int_data2, int>(qi::int_) % ',', v));
157 BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
158 }
159
160 {
161 std::vector<test_int_data2> v;
162 qi::rule<char const*, int()> r = qi::int_;
163
164 BOOST_TEST(test_attr("1,2", r % ',', v));
165 BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
166 }
167
168 {
169 std::vector<test_int_data2> v;
170
171 // this won't compile as there is no defined transformation for
172 // test_int_data2 and double
173 // BOOST_TEST(test_attr("1.0,2.2", qi::attr_cast(qi::double_) % ',', v));
174 // BOOST_TEST(test_attr("1.0,2.2"
175 // , qi::attr_cast<test_int_data2>(qi::double_) % ',', v));
176
177 BOOST_TEST(test_attr("1.0,2.2"
178 , qi::attr_cast<test_int_data2, int>(qi::double_) % ',', v));
179 BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
180
181 qi::rule<char const*, int()> r = qi::double_;
182
183 v.clear();
184 BOOST_TEST(test_attr("1.0,2.0", r % ',', v));
185 BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
186 }
187
188 return boost::report_errors();
189 }
190