1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // test_symbols.cpp |
3 | // |
4 | // Copyright 2008 David Jenkins. |
5 | // Copyright 2008 Eric Niebler. |
6 | // |
7 | // Distributed under the Boost Software License, Version 1.0. (See |
8 | // accompanying file LICENSE_1_0.txt or copy at |
9 | // http://www.boost.org/LICENSE_1_0.txt) |
10 | |
11 | #include <string> |
12 | #include <map> |
13 | #include <boost/version.hpp> |
14 | #include <boost/xpressive/xpressive_static.hpp> |
15 | #include <boost/xpressive/regex_actions.hpp> |
16 | #include <boost/test/unit_test.hpp> |
17 | |
18 | #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() |
19 | |
20 | namespace xp = boost::xpressive; |
21 | |
22 | /////////////////////////////////////////////////////////////////////////////// |
23 | // test1 |
24 | // simple action which builds a *translated* string |
25 | void test1() |
26 | { |
27 | using namespace boost::xpressive; |
28 | |
29 | local<std::string> result; |
30 | std::string str("foo bar baz foo bar baz" ); |
31 | std::map<std::string,std::string> map1; |
32 | map1["foo" ] = "1" ; |
33 | map1["bar" ] = "2" ; |
34 | map1["baz" ] = "3" ; |
35 | |
36 | sregex rx = skip(skip: _s) (+(a1=map1) |
37 | [ result += if_else(a0: length(result) > 0, a1: "," , a2: "" ) + a1 ] |
38 | ); |
39 | |
40 | if(!regex_match(rng&: str, re: rx)) |
41 | { |
42 | BOOST_ERROR("oops" ); |
43 | } |
44 | else |
45 | { |
46 | BOOST_CHECK_EQUAL(result.get(), "1,2,3,1,2,3" ); |
47 | } |
48 | } |
49 | |
50 | /////////////////////////////////////////////////////////////////////////////// |
51 | // test2 |
52 | // find longest match in symbol table |
53 | void test2() |
54 | { |
55 | using namespace boost::xpressive; |
56 | |
57 | local<std::string> result; |
58 | std::string str("foobarbazfoobazbazfoobazbar" ); |
59 | std::map<std::string,std::string> map1; |
60 | map1["foo" ] = "1" ; |
61 | map1["bar" ] = "2" ; |
62 | map1["baz" ] = "3" ; |
63 | map1["foobaz" ] = "4" ; |
64 | map1["foobazbaz" ] = "5" ; |
65 | |
66 | sregex rx = skip(skip: _s) (+(a1=map1) |
67 | [ result += if_else(a0: length(result) > 0, a1: "," , a2: "" ) + a1 ] |
68 | ); |
69 | |
70 | if(!regex_match(rng&: str, re: rx)) |
71 | { |
72 | BOOST_ERROR("oops" ); |
73 | } |
74 | else |
75 | { |
76 | BOOST_CHECK_EQUAL(result.get(), "1,2,3,5,4,2" ); |
77 | } |
78 | } |
79 | |
80 | /////////////////////////////////////////////////////////////////////////////// |
81 | // test3 |
82 | // *map* string to int, push back into list, use alternate ->* syntax |
83 | void test3() |
84 | { |
85 | using namespace boost::xpressive; |
86 | |
87 | std::list<int> result; |
88 | std::string str("foo bar baz bop" ); |
89 | std::map<std::string,int> map1; |
90 | map1["foo" ] = 1; |
91 | map1["bar" ] = 23; |
92 | map1["baz" ] = 456; |
93 | map1["bop" ] = 7890; |
94 | |
95 | #if BOOST_VERSION >= 103500 |
96 | sregex rx = skip(skip: _s) (+(a1=map1) |
97 | [ xp::ref(t&: result)->*push_back( a1 ) ] |
98 | ); |
99 | #else |
100 | sregex rx = skip(_s) (+(a1=map1) |
101 | [ push_back(xp::ref(result), a1 ) ] |
102 | ); |
103 | #endif |
104 | |
105 | if(!regex_match(rng&: str, re: rx)) |
106 | { |
107 | BOOST_ERROR("oops" ); |
108 | } |
109 | else |
110 | { |
111 | BOOST_REQUIRE_EQUAL(result.size(), 4u); |
112 | BOOST_CHECK_EQUAL(*result.begin(), 1); |
113 | BOOST_CHECK_EQUAL(*++result.begin(), 23); |
114 | BOOST_CHECK_EQUAL(*++++result.begin(), 456); |
115 | BOOST_CHECK_EQUAL(*++++++result.begin(), 7890); |
116 | } |
117 | } |
118 | |
119 | /////////////////////////////////////////////////////////////////////////////// |
120 | // test4 |
121 | // use two input maps to build an output map, with a late-bound action argument. |
122 | void test4() |
123 | { |
124 | using namespace boost::xpressive; |
125 | placeholder< std::map<std::string, int> > const _map = {}; |
126 | |
127 | std::string str("aaa=>1 bbb=>2 ccc=>3" ); |
128 | std::map<std::string,std::string> map1; |
129 | map1["aaa" ] = "foo" ; |
130 | map1["bbb" ] = "bar" ; |
131 | map1["ccc" ] = "baz" ; |
132 | std::map<std::string,int> map2; |
133 | map2["1" ] = 1; |
134 | map2["2" ] = 23; |
135 | map2["3" ] = 456; |
136 | |
137 | sregex pair = ( (a1=map1) >> "=>" >> (a2= map2) )[ _map[a1] = a2 ]; |
138 | sregex rx = pair >> *(+_s >> pair); |
139 | |
140 | smatch what; |
141 | std::map<std::string, int> result; |
142 | what.let(arg: _map = result); // bind the argument! |
143 | |
144 | if(!regex_match(rng&: str, what, re: rx)) |
145 | { |
146 | BOOST_ERROR("oops" ); |
147 | } |
148 | else |
149 | { |
150 | BOOST_REQUIRE_EQUAL(result.size(), 3u); |
151 | BOOST_CHECK_EQUAL(result["foo" ], 1); |
152 | BOOST_CHECK_EQUAL(result["bar" ], 23); |
153 | BOOST_CHECK_EQUAL(result["baz" ], 456); |
154 | } |
155 | } |
156 | |
157 | /////////////////////////////////////////////////////////////////////////////// |
158 | // test5 |
159 | // test nine maps and attributes |
160 | void test5() |
161 | { |
162 | using namespace boost::xpressive; |
163 | |
164 | local<int> result(0); |
165 | std::string str("abcdefghi" ); |
166 | std::map<std::string,int> map1; |
167 | std::map<std::string,int> map2; |
168 | std::map<std::string,int> map3; |
169 | std::map<std::string,int> map4; |
170 | std::map<std::string,int> map5; |
171 | std::map<std::string,int> map6; |
172 | std::map<std::string,int> map7; |
173 | std::map<std::string,int> map8; |
174 | std::map<std::string,int> map9; |
175 | map1["a" ] = 1; |
176 | map2["b" ] = 2; |
177 | map3["c" ] = 3; |
178 | map4["d" ] = 4; |
179 | map5["e" ] = 5; |
180 | map6["f" ] = 6; |
181 | map7["g" ] = 7; |
182 | map8["h" ] = 8; |
183 | map9["i" ] = 9; |
184 | |
185 | sregex rx = |
186 | (a1=map1)[ result += a1 ] |
187 | >> (a2=map2)[ result += a2 ] |
188 | >> (a3=map3)[ result += a3 ] |
189 | >> (a4=map4)[ result += a4 ] |
190 | >> (a5=map5)[ result += a5 ] |
191 | >> (a6=map6)[ result += a6 ] |
192 | >> (a7=map7)[ result += a7 ] |
193 | >> (a8=map8)[ result += a8 ] |
194 | >> (a9=map9)[ result += a9 ]; |
195 | |
196 | if(!regex_match(rng&: str, re: rx)) |
197 | { |
198 | BOOST_ERROR("oops" ); |
199 | } |
200 | else |
201 | { |
202 | BOOST_CHECK_EQUAL(result.get(), 45); |
203 | } |
204 | } |
205 | |
206 | /////////////////////////////////////////////////////////////////////////////// |
207 | // test6 |
208 | // test case-sensitivity |
209 | void test6() |
210 | { |
211 | using namespace boost::xpressive; |
212 | |
213 | local<std::string> result; |
214 | std::map<std::string,std::string> map1; |
215 | map1["a" ] = "1" ; |
216 | map1["A" ] = "2" ; |
217 | map1["b" ] = "3" ; |
218 | map1["B" ] = "4" ; |
219 | std::string str("a A b B a A b B" ); |
220 | sregex rx = skip(skip: _s)( |
221 | icase(a1= map1) [ result = a1 ] |
222 | >> repeat<3>( expr2: (icase(a1= map1) [ result += ',' + a1 ]) ) |
223 | >> repeat<4>( expr2: ((a1= map1) [ result += ',' + a1 ]) ) |
224 | ); |
225 | if(!regex_match(rng&: str, re: rx)) |
226 | { |
227 | BOOST_ERROR("oops" ); |
228 | } |
229 | else |
230 | { |
231 | BOOST_CHECK_EQUAL(result.get(), "1,1,3,3,1,2,3,4" ); |
232 | } |
233 | } |
234 | |
235 | /////////////////////////////////////////////////////////////////////////////// |
236 | // test7 |
237 | // test multiple mutually-exclusive maps and default attribute value |
238 | void test7() |
239 | { |
240 | using namespace boost::xpressive; |
241 | |
242 | local<std::string> result; |
243 | std::map<std::string,std::string> map1; |
244 | map1["a" ] = "1" ; |
245 | map1["b" ] = "2" ; |
246 | std::map<std::string,std::string> map2; |
247 | map2["c" ] = "3" ; |
248 | map2["d" ] = "4" ; |
249 | std::string str("abcde" ); |
250 | sregex rx = *((a1= map1) | (a1= map2) | 'e') [ result += (a1 | "9" ) ]; |
251 | if(!regex_match(rng&: str, re: rx)) |
252 | { |
253 | BOOST_ERROR("oops" ); |
254 | } |
255 | else |
256 | { |
257 | BOOST_CHECK_EQUAL(result.get(), "12349" ); |
258 | } |
259 | } |
260 | |
261 | #ifndef BOOST_XPRESSIVE_NO_WREGEX |
262 | struct City |
263 | { |
264 | std::wstring name; |
265 | char const* nickname; |
266 | int population; |
267 | }; |
268 | |
269 | BOOST_TYPEOF_REGISTER_TYPE(City) |
270 | |
271 | /////////////////////////////////////////////////////////////////////////////// |
272 | // test8 |
273 | // test wide strings with structure result |
274 | void test8() |
275 | { |
276 | using namespace boost::xpressive; |
277 | |
278 | City cities[] = { |
279 | {.name: L"Chicago" , .nickname: "The Windy City" , .population: 945000}, |
280 | {.name: L"New York" , .nickname: "The Big Apple" , .population: 16626000}, |
281 | {.name: L"\u041c\u043E\u0441\u043A\u0432\u0430" , .nickname: "Moscow" , .population: 9299000} |
282 | }; |
283 | int const nbr_cities = sizeof(cities)/sizeof(*cities); |
284 | |
285 | std::map<std::wstring, City> map1; |
286 | for(int i=0; i<nbr_cities; ++i) |
287 | { |
288 | map1[cities[i].name] = cities[i]; |
289 | } |
290 | |
291 | std::wstring str(L"Chicago \u041c\u043E\u0441\u043A\u0432\u0430" ); |
292 | local<City> result1, result2; |
293 | wsregex rx = (a1= map1)[ result1 = a1 ] >> +_s |
294 | >> (a1= map1)[ result2 = a1 ]; |
295 | if(!regex_match(rng&: str, re: rx)) |
296 | { |
297 | BOOST_ERROR("oops" ); |
298 | } |
299 | else |
300 | { |
301 | BOOST_CHECK_EQUAL(result1.get().nickname, "The Windy City" ); |
302 | BOOST_CHECK_EQUAL(result2.get().nickname, "Moscow" ); |
303 | } |
304 | } |
305 | #else |
306 | void test8() |
307 | { |
308 | // This test is empty |
309 | } |
310 | #endif |
311 | |
312 | /////////////////////////////////////////////////////////////////////////////// |
313 | // test9 |
314 | // test "not before" using a map |
315 | void test9() |
316 | { |
317 | using namespace boost::xpressive; |
318 | |
319 | std::string result; |
320 | std::string str("foobar" ); |
321 | std::map<std::string,int> map1; |
322 | map1["foo" ] = 1; |
323 | sregex rx = ~before(expr: (a1=map1)[a1]) >> |
324 | (s1=*_w)[ xp::ref(t&: result) = s1 ]; |
325 | if(!regex_match(rng&: str, re: rx)) |
326 | { |
327 | BOOST_CHECK_EQUAL(result, "" ); |
328 | } |
329 | else |
330 | { |
331 | BOOST_ERROR("oops" ); |
332 | } |
333 | } |
334 | |
335 | using namespace boost::unit_test; |
336 | |
337 | /////////////////////////////////////////////////////////////////////////////// |
338 | // init_unit_test_suite |
339 | // |
340 | test_suite* init_unit_test_suite( int argc, char* argv[] ) |
341 | { |
342 | test_suite *test = BOOST_TEST_SUITE("test_symbols" ); |
343 | test->add(BOOST_TEST_CASE(&test1)); |
344 | test->add(BOOST_TEST_CASE(&test2)); |
345 | test->add(BOOST_TEST_CASE(&test3)); |
346 | test->add(BOOST_TEST_CASE(&test4)); |
347 | test->add(BOOST_TEST_CASE(&test5)); |
348 | test->add(BOOST_TEST_CASE(&test6)); |
349 | test->add(BOOST_TEST_CASE(&test7)); |
350 | test->add(BOOST_TEST_CASE(&test8)); |
351 | test->add(BOOST_TEST_CASE(&test9)); |
352 | return test; |
353 | } |
354 | |
355 | |