test_symbols.cpp 8.7 KB

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