1 /*=============================================================================
2 Copyright (c) 2001-2015 Joel de Guzman
3 Copyright (c) 2001-2011 Hartmut Kaiser
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 #include <boost/detail/lightweight_test.hpp>
9 #include <boost/spirit/home/x3.hpp>
10 #include <boost/fusion/include/std_pair.hpp>
11
12 #include <iostream>
13 #include <map>
14 #include <unordered_map>
15 #include <boost/unordered_map.hpp>
16 #include <vector>
17 #include <list>
18 #include <deque>
19 #include <set>
20 #include <unordered_set>
21 #include <boost/unordered_set.hpp>
22 #include <string>
23 #include "test.hpp"
24
25 namespace x3 = boost::spirit::x3;
26
27
28 // check if we did not break user defined specializations
29 namespace check_substitute {
30 template <typename T> struct foo {};
31 template <typename T> struct bar { using type = T; };
32 template <typename T> struct is_bar : std::false_type {};
33 template <typename T> struct is_bar<bar<T>> : std::true_type {};
34 }
35
36 namespace boost { namespace spirit { namespace x3 { namespace traits {
37 using namespace check_substitute;
38
39 template <typename T, typename U>
40 struct is_substitute<foo<T>, foo<U>> : is_substitute<T, U> {};
41
42 template <typename T, typename U>
43 struct is_substitute<T, U, std::enable_if_t<is_bar<T>::value && is_bar<U>::value>>
44 : is_substitute<typename T::type, typename U::type> {};
45 }}}}
46
47 namespace check_substitute {
48 using x3::traits::is_substitute;
49 static_assert(is_substitute<foo<int>, foo<int>>::value, "is_substitute problem");
50 static_assert(!is_substitute<foo<int>, foo<long>>::value, "is_substitute problem");
51 static_assert(is_substitute<bar<int>, bar<int>>::value, "is_substitute problem");
52 static_assert(!is_substitute<bar<int>, bar<long>>::value, "is_substitute problem");
53 }
54
55
56 x3::rule<class pair_rule, std::pair<std::string,std::string>> const pair_rule("pair");
57 x3::rule<class string_rule, std::string> const string_rule("string");
58
59 auto const pair_rule_def = string_rule > x3::lit('=') > string_rule;
60 auto const string_rule_def = x3::lexeme[*x3::alnum];
61
BOOST_SPIRIT_DEFINE(pair_rule,string_rule)62 BOOST_SPIRIT_DEFINE(pair_rule, string_rule)
63
64 template <typename Container>
65 void test_map_support()
66 {
67 using spirit_test::test_attr;
68
69 Container container;
70 Container const compare {{"k1", "v1"}, {"k2", "v2"}};
71 auto const rule = pair_rule % x3::lit(',');
72
73 BOOST_TEST(test_attr("k1=v1,k2=v2,k2=v3", rule, container));
74 BOOST_TEST(container.size() == 2);
75 BOOST_TEST(container == compare);
76
77 // test sequences parsing into containers
78 auto const seq_rule = pair_rule >> ',' >> pair_rule >> ',' >> pair_rule;
79 container.clear();
80 BOOST_TEST(test_attr("k1=v1,k2=v2,k2=v3", seq_rule, container));
81
82 // test parsing container into container
83 auto const cic_rule = pair_rule >> +(',' >> pair_rule);
84 container.clear();
85 BOOST_TEST(test_attr("k1=v1,k2=v2,k2=v3", cic_rule, container));
86 }
87
88 template <typename Container>
test_multimap_support()89 void test_multimap_support()
90 {
91 using spirit_test::test_attr;
92
93 Container container;
94 Container const compare {{"k1", "v1"}, {"k2", "v2"}, {"k2", "v3"}};
95 auto const rule = pair_rule % x3::lit(',');
96
97 BOOST_TEST(test_attr("k1=v1,k2=v2,k2=v3", rule, container));
98 BOOST_TEST(container.size() == 3);
99 BOOST_TEST(container == compare);
100
101 // test sequences parsing into containers
102 auto const seq_rule = pair_rule >> ',' >> pair_rule >> ',' >> pair_rule;
103 container.clear();
104 BOOST_TEST(test_attr("k1=v1,k2=v2,k2=v3", seq_rule, container));
105
106 // test parsing container into container
107 auto const cic_rule = pair_rule >> +(',' >> pair_rule);
108 container.clear();
109 BOOST_TEST(test_attr("k1=v1,k2=v2,k2=v3", cic_rule, container));
110 }
111
112 template <typename Container>
test_sequence_support()113 void test_sequence_support()
114 {
115 using spirit_test::test_attr;
116
117 Container container;
118 Container const compare {"e1", "e2", "e2"};
119 auto const rule = string_rule % x3::lit(',');
120
121 BOOST_TEST(test_attr("e1,e2,e2", rule, container));
122 BOOST_TEST(container.size() == 3);
123 BOOST_TEST(container == compare);
124
125 // test sequences parsing into containers
126 auto const seq_rule = string_rule >> ',' >> string_rule >> ',' >> string_rule;
127 container.clear();
128 BOOST_TEST(test_attr("e1,e2,e2", seq_rule, container));
129
130 // test parsing container into container
131 auto const cic_rule = string_rule >> +(',' >> string_rule);
132 container.clear();
133 BOOST_TEST(test_attr("e1,e2,e2", cic_rule, container));
134 }
135
136 template <typename Container>
test_set_support()137 void test_set_support()
138 {
139 using spirit_test::test_attr;
140
141 Container container;
142 Container const compare {"e1", "e2"};
143 auto const rule = string_rule % x3::lit(',');
144
145 BOOST_TEST(test_attr("e1,e2,e2", rule, container));
146 BOOST_TEST(container.size() == 2);
147 BOOST_TEST(container == compare);
148
149 // test sequences parsing into containers
150 auto const seq_rule = string_rule >> ',' >> string_rule >> ',' >> string_rule;
151 container.clear();
152 BOOST_TEST(test_attr("e1,e2,e2", seq_rule, container));
153
154 // test parsing container into container
155 auto const cic_rule = string_rule >> +(',' >> string_rule);
156 container.clear();
157 BOOST_TEST(test_attr("e1,e2,e2", cic_rule, container));
158 }
159
160 template <typename Container>
test_multiset_support()161 void test_multiset_support()
162 {
163 using spirit_test::test_attr;
164
165 Container container;
166 Container const compare {"e1", "e2", "e2"};
167 auto const rule = string_rule % x3::lit(',');
168
169 BOOST_TEST(test_attr("e1,e2,e2", rule, container));
170 BOOST_TEST(container.size() == 3);
171 BOOST_TEST(container == compare);
172
173 // test sequences parsing into containers
174 auto const seq_rule = string_rule >> ',' >> string_rule >> ',' >> string_rule;
175 container.clear();
176 BOOST_TEST(test_attr("e1,e2,e2", seq_rule, container));
177
178 // test parsing container into container
179 auto const cic_rule = string_rule >> +(',' >> string_rule);
180 container.clear();
181 BOOST_TEST(test_attr("e1,e2,e2", cic_rule, container));
182 }
183
184 template <typename Container>
test_string_support()185 void test_string_support()
186 {
187 using spirit_test::test_attr;
188
189 Container container;
190 Container const compare {"e1e2e2"};
191 auto const rule = string_rule % x3::lit(',');
192
193 BOOST_TEST(test_attr("e1,e2,e2", rule, container));
194 BOOST_TEST(container.size() == 6);
195 BOOST_TEST(container == compare);
196
197 // test sequences parsing into containers
198 auto const seq_rule = string_rule >> ',' >> string_rule >> ',' >> string_rule;
199 container.clear();
200 BOOST_TEST(test_attr("e1,e2,e2", seq_rule, container));
201
202 // test parsing container into container
203 auto const cic_rule = string_rule >> +(',' >> string_rule);
204 container.clear();
205 BOOST_TEST(test_attr("e1,e2,e2", cic_rule, container));
206 }
207
208 int
main()209 main()
210 {
211 using x3::traits::is_associative;
212
213 // ------------------------------------------------------------------
214
215 static_assert(is_associative<std::set<int>>::value, "is_associative problem");
216 static_assert(is_associative<std::unordered_set<int>>::value, "is_associative problem");
217 static_assert(is_associative<boost::unordered_set<int>>::value, "is_associative problem");
218 static_assert(is_associative<std::multiset<int>>::value, "is_associative problem");
219 static_assert(is_associative<std::unordered_multiset<int>>::value, "is_associative problem");
220 static_assert(is_associative<boost::unordered_multiset<int>>::value, "is_associative problem");
221 static_assert(is_associative<std::map<int,int>>::value, "is_associative problem");
222 static_assert(is_associative<std::unordered_map<int,int>>::value, "is_associative problem");
223 static_assert(is_associative<boost::unordered_map<int,int>>::value, "is_associative problem");
224 static_assert(is_associative<std::multimap<int,int>>::value, "is_associative problem");
225 static_assert(is_associative<std::unordered_multimap<int,int>>::value, "is_associative problem");
226 static_assert(is_associative<boost::unordered_multimap<int,int>>::value, "is_associative problem");
227
228 static_assert(!is_associative<std::vector<int>>::value, "is_associative problem");
229 static_assert(!is_associative<std::string>::value, "is_associative problem");
230 static_assert(!is_associative<std::deque<int>>::value, "is_associative problem");
231 static_assert(!is_associative<std::list<int>>::value, "is_associative problem");
232
233 // ------------------------------------------------------------------
234
235 test_string_support<std::string>();
236
237 test_sequence_support<std::vector<std::string>>();
238 test_sequence_support<std::list<std::string>>();
239 test_sequence_support<std::deque<std::string>>();
240
241 test_set_support<std::set<std::string>>();
242 test_set_support<std::unordered_set<std::string>>();
243 test_set_support<boost::unordered_set<std::string>>();
244
245 test_multiset_support<std::multiset<std::string>>();
246 test_multiset_support<std::unordered_multiset<std::string>>();
247 test_multiset_support<boost::unordered_multiset<std::string>>();
248
249 test_map_support<std::map<std::string,std::string>>();
250 test_map_support<std::unordered_map<std::string,std::string>>();
251 test_map_support<boost::unordered_map<std::string,std::string>>();
252
253 test_multimap_support<std::multimap<std::string,std::string>>();
254 test_multimap_support<std::unordered_multimap<std::string,std::string>>();
255 test_multimap_support<boost::unordered_multimap<std::string,std::string>>();
256
257 return boost::report_errors();
258 }
259