• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
test1()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(_s) (+(a1=map1)
37         [ result += if_else(length(result) > 0, ",", "") + a1 ]
38     );
39 
40     if(!regex_match(str, 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
test2()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(_s) (+(a1=map1)
67         [ result += if_else(length(result) > 0, ",", "") + a1 ]
68     );
69 
70     if(!regex_match(str, 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
test3()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(_s) (+(a1=map1)
97         [ xp::ref(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(str, 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.
test4()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(_map = result); // bind the argument!
143 
144     if(!regex_match(str, what, 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
test5()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(str, 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
test6()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(_s)(
221         icase(a1= map1) [ result = a1 ]
222         >> repeat<3>( (icase(a1= map1) [ result += ',' + a1 ]) )
223         >> repeat<4>( ((a1= map1) [ result += ',' + a1 ]) )
224         );
225     if(!regex_match(str, 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
test7()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(str, 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 
BOOST_TYPEOF_REGISTER_TYPE(City)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         {L"Chicago", "The Windy City", 945000},
280         {L"New York", "The Big Apple", 16626000},
281         {L"\u041c\u043E\u0441\u043A\u0432\u0430", "Moscow", 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(str, 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
test8()306 void test8()
307 {
308     // This test is empty
309 }
310 #endif
311 
312 ///////////////////////////////////////////////////////////////////////////////
313 // test9
314 //  test "not before" using a map
test9()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((a1=map1)[a1]) >>
324         (s1=*_w)[ xp::ref(result) = s1 ];
325     if(!regex_match(str, 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 //
init_unit_test_suite(int argc,char * argv[])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