• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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