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