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
20namespace xp = boost::xpressive;
21
22///////////////////////////////////////////////////////////////////////////////
23// test1
24// simple action which builds a *translated* string
25void 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
53void 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
83void 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.
122void 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
160void 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
209void 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
238void 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
262struct City
263{
264 std::wstring name;
265 char const* nickname;
266 int population;
267};
268
269BOOST_TYPEOF_REGISTER_TYPE(City)
270
271///////////////////////////////////////////////////////////////////////////////
272// test8
273// test wide strings with structure result
274void 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
306void test8()
307{
308 // This test is empty
309}
310#endif
311
312///////////////////////////////////////////////////////////////////////////////
313// test9
314// test "not before" using a map
315void 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
335using namespace boost::unit_test;
336
337///////////////////////////////////////////////////////////////////////////////
338// init_unit_test_suite
339//
340test_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

source code of boost/libs/xpressive/test/test_symbols.cpp