Imported Upstream version 1.51.0
[platform/upstream/boost.git] / 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