keywords.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Copyright (c) 2011 Thomas Bernard
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. =============================================================================*/
  7. #define FUSION_MAX_VECTOR_SIZE 50
  8. #define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
  9. #define BOOST_MPL_LIMIT_LIST_SIZE 50
  10. #define BOOST_MPL_LIMIT_VECTOR_SIZE 50
  11. #include "../measure.hpp"
  12. #include <boost/config/warning_disable.hpp>
  13. #include <boost/spirit/include/qi.hpp>
  14. #include <boost/spirit/include/phoenix_core.hpp>
  15. #include <boost/spirit/include/phoenix_operator.hpp>
  16. #include <boost/spirit/include/phoenix_object.hpp>
  17. #include <boost/spirit/include/phoenix_fusion.hpp>
  18. #include <boost/spirit/include/phoenix_container.hpp>
  19. #include <boost/fusion/include/adapt_struct.hpp>
  20. #include <boost/fusion/include/io.hpp>
  21. #include <boost/spirit/include/qi_permutation.hpp>
  22. #include <boost/spirit/home/qi/string/tst_map.hpp>
  23. #include <boost/spirit/repository/include/qi_kwd.hpp>
  24. #include <boost/spirit/repository/include/qi_keywords.hpp>
  25. #include <boost/optional.hpp>
  26. #include <boost/spirit/home/phoenix/core/argument.hpp>
  27. #include <boost/spirit/home/phoenix/bind/bind_member_variable.hpp>
  28. #include <iostream>
  29. #include <string>
  30. #include <complex>
  31. #include <vector>
  32. #include <iterator>
  33. #include <stdexcept>
  34. #include <boost/preprocessor/control/if.hpp>
  35. #include <boost/preprocessor/seq/for_each_i.hpp>
  36. #include <boost/preprocessor/seq/size.hpp>
  37. #include <boost/preprocessor/cat.hpp>
  38. #include <boost/preprocessor/stringize.hpp>
  39. #define KEYS_5
  40. #include "keywords.hpp"
  41. #define declOptions(r, data, i, elem) boost::optional<int> BOOST_PP_CAT(option,i);
  42. #define fusionOptions(r, data, i, elem) (boost::optional<int>, BOOST_PP_CAT(option,i))
  43. namespace client
  44. {
  45. namespace qi = boost::spirit::qi;
  46. namespace ascii = boost::spirit::ascii;
  47. ///////////////////////////////////////////////////////////////////////////
  48. // Our parsedData struct
  49. ///////////////////////////////////////////////////////////////////////////
  50. //[tutorial_parsedData_struct
  51. struct parsedDataOptions
  52. {
  53. BOOST_PP_SEQ_FOR_EACH_I(declOptions,_,keys)
  54. };
  55. struct parsedData
  56. {
  57. std::string name;
  58. parsedDataOptions options;
  59. void clear()
  60. {
  61. name.clear();
  62. }
  63. };
  64. struct parsedData2
  65. {
  66. std::string name;
  67. BOOST_PP_SEQ_FOR_EACH_I(declOptions,_,keys)
  68. void clear()
  69. {
  70. name.clear();
  71. }
  72. };
  73. }
  74. std::ostream &operator<<(std::ostream & os, client::parsedData &data)
  75. {
  76. os << data.name <<std::endl;
  77. #define generateOutput1(r, d, i, elem) if( BOOST_PP_CAT(data.options.option, i) ) os<< BOOST_PP_STRINGIZE( BOOST_PP_CAT(option,i)) <<" "<< * BOOST_PP_CAT(data.options.option , i)<<std::endl;
  78. BOOST_PP_SEQ_FOR_EACH_I(generateOutput1,_,keys)
  79. os<<std::endl;
  80. return os;
  81. }
  82. std::ostream &operator<<(std::ostream & os, client::parsedData2 &data)
  83. {
  84. os << data.name <<std::endl;
  85. #define generateOutput2(r, d, i, elem) if(BOOST_PP_CAT(data.option, i)) os<< BOOST_PP_STRINGIZE( BOOST_PP_CAT(option,i)) <<" "<< * BOOST_PP_CAT(data.option,i)<<std::endl;
  86. BOOST_PP_SEQ_FOR_EACH_I(generateOutput2,_,keys)
  87. os<<std::endl;
  88. return os;
  89. }
  90. BOOST_FUSION_ADAPT_STRUCT(
  91. client::parsedDataOptions,
  92. BOOST_PP_SEQ_FOR_EACH_I(fusionOptions,_,keys)
  93. )
  94. BOOST_FUSION_ADAPT_STRUCT(
  95. client::parsedData,
  96. (std::string, name)
  97. (client::parsedDataOptions, options)
  98. )
  99. BOOST_FUSION_ADAPT_STRUCT(
  100. client::parsedData2,
  101. (std::string, name)
  102. BOOST_PP_SEQ_FOR_EACH_I(fusionOptions,_,keys)
  103. )
  104. enum variation
  105. {
  106. full,
  107. no_assign,
  108. assign
  109. };
  110. namespace client
  111. {
  112. ///////////////////////////////////////////////////////////////////////////////
  113. // Our parsedData parser
  114. ///////////////////////////////////////////////////////////////////////////////
  115. //[tutorial_parsedData_parser
  116. template <typename Iterator>
  117. struct permutation_parser : qi::grammar<Iterator, parsedData(), ascii::space_type>
  118. {
  119. permutation_parser() : permutation_parser::base_type(start)
  120. {
  121. using qi::int_;
  122. using qi::lit;
  123. using qi::double_;
  124. using qi::lexeme;
  125. using ascii::char_;
  126. using boost::phoenix::at_c;
  127. using boost::phoenix::assign;
  128. using qi::_r1;
  129. using qi::_1;
  130. using qi::_val;
  131. using qi::omit;
  132. using qi::repeat;
  133. quoted_string %= lexeme[+(char_-' ')];
  134. #define generateOptions1(r, data, i, elem) BOOST_PP_IF(i, ^(lit(elem) > int_) , (lit(elem) > int_))
  135. options = (BOOST_PP_SEQ_FOR_EACH_I(generateOptions1,_,keys));
  136. start %=
  137. quoted_string
  138. >> options;
  139. ;
  140. v_vals = repeat(1,2)[int_];
  141. }
  142. typedef parsedData parser_target_type;
  143. qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
  144. qi::rule<Iterator, parsedDataOptions(), ascii::space_type> options;
  145. qi::rule<Iterator, std::vector<int>(), ascii::space_type> v_vals;
  146. qi::rule<Iterator, parsedData(), ascii::space_type> start;
  147. };
  148. template <typename Iterator>
  149. struct alternative_parser : qi::grammar<Iterator, parsedData2(), ascii::space_type>
  150. {
  151. alternative_parser() : alternative_parser::base_type(start)
  152. {
  153. using qi::int_;
  154. using qi::lit;
  155. using qi::double_;
  156. using qi::lexeme;
  157. using ascii::char_;
  158. using boost::phoenix::at_c;
  159. using qi::_r1;
  160. using qi::_1;
  161. using qi::_val;
  162. quoted_string %= lexeme[+(char_-' ')];
  163. #define generateOptions2(r, data, i, elem) BOOST_PP_IF(i, |(lit(elem) > int_[at_c<i+1>(_r1)=_1]) , (lit(elem) > int_[at_c<i+1>(_r1)=_1]))
  164. options = (BOOST_PP_SEQ_FOR_EACH_I(generateOptions2,_,keys));
  165. start =
  166. quoted_string [at_c<0>(_val)=_1]
  167. >> *options(_val);
  168. ;
  169. }
  170. typedef parsedData2 parser_target_type;
  171. qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
  172. qi::rule<Iterator, void(parsedData2 & ), ascii::space_type> options;
  173. qi::rule<Iterator, parsedData2(), ascii::space_type> start;
  174. };
  175. template <typename Iterator,typename variation>
  176. struct tst_parser : qi::grammar<Iterator, parsedData2(), ascii::space_type>
  177. {
  178. typedef variation variation_type;
  179. tst_parser() : tst_parser::base_type(startalias)
  180. {
  181. namespace phx = boost::phoenix;
  182. using qi::int_;
  183. using qi::lit;
  184. using qi::double_;
  185. using qi::lexeme;
  186. using ascii::char_;
  187. using boost::phoenix::at_c;
  188. using qi::_r1;
  189. using qi::_1;
  190. using qi::_a;
  191. using qi::_val;
  192. using qi::locals;
  193. using qi::parameterized_nonterminal;
  194. startalias = start.alias();
  195. quoted_string %= lexeme[+(char_-' ')];
  196. #define generateRules(r, data, i, elem) BOOST_PP_CAT(rule,i) = int_[phx::at_c<i+1>(*phx::ref(currentObj))=_1];
  197. BOOST_PP_SEQ_FOR_EACH_I(generateRules,_,keys)
  198. #define generateOptions3(r, data, i, elem) (elem,& BOOST_PP_CAT(rule,i))
  199. options.add BOOST_PP_SEQ_FOR_EACH_I(generateOptions3,_,keys);
  200. switch(variation_type::value)
  201. {
  202. case full:
  203. {
  204. start =
  205. quoted_string [at_c<0>(_val)=_1][phx::ref(currentObj)=&_val]
  206. >> *( options [_a=_1] >> lazy(*_a));
  207. ;
  208. break;
  209. }
  210. case no_assign:
  211. {
  212. start =
  213. quoted_string [at_c<0>(_val)=_1][phx::ref(currentObj)=&_val]
  214. >> *( options >> int_);
  215. ;
  216. break;
  217. }
  218. case assign:
  219. {
  220. start =
  221. quoted_string [at_c<0>(_val)=_1][phx::ref(currentObj)=&_val]
  222. >> *( options [_a=_1] >> int_);
  223. ;
  224. break;
  225. }
  226. }
  227. }
  228. parsedData2 *currentObj;
  229. typedef parsedData2 parser_target_type;
  230. qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
  231. typedef qi::rule<Iterator, ascii::space_type> optionsRule;
  232. #define declareRules(r, data, i, elem) optionsRule BOOST_PP_CAT(rule,i);
  233. BOOST_PP_SEQ_FOR_EACH_I(declareRules,_,keys)
  234. qi::symbols<char,optionsRule* > options;
  235. qi::rule<Iterator, parsedData2(), ascii::space_type> startalias;
  236. qi::rule<Iterator, parsedData2(), qi::locals<optionsRule*>, ascii::space_type> start;
  237. };
  238. template <typename Iterator,typename variation>
  239. struct tst_map_parser : qi::grammar<Iterator, parsedData2(), ascii::space_type>
  240. {
  241. typedef variation variation_type;
  242. tst_map_parser() : tst_map_parser::base_type(startalias)
  243. {
  244. namespace phx = boost::phoenix;
  245. using qi::int_;
  246. using qi::lit;
  247. using qi::double_;
  248. using qi::lexeme;
  249. using ascii::char_;
  250. using boost::phoenix::at_c;
  251. using qi::_r1;
  252. using qi::_1;
  253. using qi::_a;
  254. using qi::_val;
  255. using qi::locals;
  256. using qi::parameterized_nonterminal;
  257. startalias = start.alias();
  258. quoted_string %= lexeme[+(char_-' ')];
  259. #define generateRules3(r, data, i, elem) BOOST_PP_CAT(rule,i) = int_[phx::at_c<i+1>(*phx::ref(currentObj))=_1];
  260. BOOST_PP_SEQ_FOR_EACH_I(generateRules3,_,keys)
  261. #define generateOptions3(r, data, i, elem) (elem,& BOOST_PP_CAT(rule,i))
  262. options.add BOOST_PP_SEQ_FOR_EACH_I(generateOptions3,_,keys);
  263. switch(variation_type::value)
  264. {
  265. case full:
  266. {
  267. start =
  268. quoted_string [at_c<0>(_val)=_1][phx::ref(currentObj)=&_val]
  269. >> *( options [_a=_1] >> lazy(*_a));
  270. ;
  271. break;
  272. }
  273. case no_assign:
  274. {
  275. start =
  276. quoted_string [at_c<0>(_val)=_1][phx::ref(currentObj)=&_val]
  277. >> *( options >> int_);
  278. ;
  279. break;
  280. }
  281. case assign:
  282. {
  283. start =
  284. quoted_string [at_c<0>(_val)=_1][phx::ref(currentObj)=&_val]
  285. >> *( options [_a=_1] >> int_);
  286. ;
  287. break;
  288. }
  289. }
  290. }
  291. parsedData2 *currentObj;
  292. typedef parsedData2 parser_target_type;
  293. qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
  294. typedef qi::rule<Iterator, ascii::space_type> optionsRule;
  295. #define declareRules(r, data, i, elem) optionsRule BOOST_PP_CAT(rule,i);
  296. BOOST_PP_SEQ_FOR_EACH_I(declareRules,_,keys)
  297. qi::symbols<char,optionsRule*, boost::spirit::qi::tst_map<char,optionsRule*> > options;
  298. qi::rule<Iterator, parsedData2(), ascii::space_type> startalias;
  299. qi::rule<Iterator, parsedData2(), qi::locals<optionsRule*>, ascii::space_type> start;
  300. };
  301. template <typename Iterator>
  302. struct kwd_parser : qi::grammar<Iterator, parsedData(), ascii::space_type>
  303. {
  304. kwd_parser() : kwd_parser::base_type(start)
  305. {
  306. using qi::int_;
  307. using qi::lit;
  308. using qi::double_;
  309. using qi::lexeme;
  310. using ascii::char_;
  311. using qi::_r1;
  312. using qi::_1;
  313. using qi::_val;
  314. using boost::spirit::repository::qi::kwd;
  315. quoted_string %= lexeme[+(char_-' ')];
  316. #define generateOptions4(r, data, i, elem) BOOST_PP_IF(i, / kwd( elem )[ int_ ] , kwd( elem )[ int_ ] )
  317. options = (BOOST_PP_SEQ_FOR_EACH_I(generateOptions4,_,keys));
  318. start %=
  319. quoted_string
  320. >> options;
  321. ;
  322. }
  323. typedef parsedData parser_target_type;
  324. qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
  325. qi::rule<Iterator, parsedDataOptions(), ascii::space_type> options;
  326. qi::rule<Iterator, boost::fusion::vector<boost::optional<int>,boost::optional<int> > () , ascii::space_type> v_vals;
  327. qi::rule<Iterator, parsedData(), ascii::space_type> start;
  328. };
  329. }
  330. template <typename parserType>
  331. struct timeParser : test::base{
  332. timeParser(const std::string & str) : str(str)
  333. {
  334. }
  335. parserType &get_parser(){
  336. static parserType parser;
  337. return parser;
  338. }
  339. std::string str;
  340. void benchmark()
  341. {
  342. using boost::spirit::ascii::space;
  343. bool r = false;
  344. std::string::const_iterator end = str.end();
  345. std::string::const_iterator iter = str.begin();
  346. typename parserType::parser_target_type data;
  347. r = phrase_parse(iter, end, get_parser(), space, data);
  348. if (r && iter == end)
  349. {
  350. this->val += data.name.size();
  351. }
  352. else
  353. {
  354. throw std::runtime_error("Parsing failed");
  355. }
  356. }
  357. };
  358. typedef std::string::const_iterator iterator_type;
  359. typedef client::permutation_parser<iterator_type> permutation_parser;
  360. typedef client::kwd_parser<iterator_type> kwd_parser;
  361. typedef client::alternative_parser<iterator_type> alternative_parser;
  362. typedef client::tst_map_parser<iterator_type, boost::mpl::int_<full> > tst_map_parser;
  363. struct permutation_timer_fwd : timeParser<permutation_parser>
  364. {
  365. permutation_timer_fwd() : timeParser<permutation_parser>(fwd) {}
  366. };
  367. struct permutation_timer_back : timeParser<permutation_parser>
  368. {
  369. permutation_timer_back() : timeParser<permutation_parser>(back) {}
  370. };
  371. struct alternative_timer_fwd : timeParser<alternative_parser>
  372. {
  373. alternative_timer_fwd() : timeParser<alternative_parser>(fwd) {}
  374. };
  375. struct alternative_timer_back : timeParser<alternative_parser>
  376. {
  377. alternative_timer_back() : timeParser<alternative_parser>(back) {}
  378. };
  379. struct tst_timer_fwd_full : timeParser< client::tst_parser<iterator_type, boost::mpl::int_<full> > >
  380. {
  381. tst_timer_fwd_full() : timeParser< client::tst_parser<iterator_type, boost::mpl::int_<full> > >(fwd) {}
  382. };
  383. struct tst_timer_fwd_no_assign : timeParser< client::tst_parser<iterator_type, boost::mpl::int_<no_assign> > >
  384. {
  385. tst_timer_fwd_no_assign() : timeParser< client::tst_parser<iterator_type,boost::mpl::int_<no_assign> > >(fwd) {}
  386. };
  387. struct tst_timer_fwd_assign : timeParser< client::tst_parser<iterator_type,boost::mpl::int_<assign> > >
  388. {
  389. tst_timer_fwd_assign() : timeParser< client::tst_parser<iterator_type,boost::mpl::int_<assign> > >(fwd) {}
  390. };
  391. struct tst_timer_back : timeParser< client::tst_parser<iterator_type,boost::mpl::int_<full> > >
  392. {
  393. tst_timer_back() : timeParser< client::tst_parser<iterator_type,boost::mpl::int_<full> > >(back) {}
  394. };
  395. struct tst_map_timer_fwd : timeParser<tst_map_parser>
  396. {
  397. tst_map_timer_fwd() : timeParser<tst_map_parser>(fwd) {}
  398. };
  399. struct tst_map_timer_back : timeParser<tst_map_parser>
  400. {
  401. tst_map_timer_back() : timeParser<tst_map_parser>(back) {}
  402. };
  403. struct kwd_timer_fwd : timeParser<kwd_parser>
  404. {
  405. kwd_timer_fwd() : timeParser<kwd_parser>(fwd) {}
  406. };
  407. struct kwd_timer_back : timeParser<kwd_parser>
  408. {
  409. kwd_timer_back() : timeParser<kwd_parser>(back) {}
  410. };
  411. ////////////////////////////////////////////////////////////////////////////
  412. // Main program
  413. ////////////////////////////////////////////////////////////////////////////
  414. int
  415. main()
  416. {
  417. BOOST_SPIRIT_TEST_BENCHMARK(
  418. 10000000000, // This is the maximum repetitions to execute
  419. (permutation_timer_fwd)
  420. (permutation_timer_back)
  421. (alternative_timer_fwd)
  422. (alternative_timer_back)
  423. (tst_timer_fwd_full)
  424. (tst_timer_fwd_no_assign)
  425. (tst_timer_fwd_assign)
  426. (tst_timer_back)
  427. (tst_map_timer_fwd)
  428. (tst_map_timer_back)
  429. (kwd_timer_fwd)
  430. (kwd_timer_back)
  431. )
  432. // This is ultimately responsible for preventing all the test code
  433. // from being optimized away. Change this to return 0 and you
  434. // unplug the whole test's life support system.
  435. return test::live_code != 0;
  436. }