1 /*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 Copyright (c) 2011 Thomas Bernard
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 =============================================================================*/
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
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>
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>
47 #include "keywords.hpp"
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))
55 namespace qi
= boost::spirit::qi
;
56 namespace ascii
= boost::spirit::ascii
;
58 ///////////////////////////////////////////////////////////////////////////
59 // Our parsedData struct
60 ///////////////////////////////////////////////////////////////////////////
61 //[tutorial_parsedData_struct
62 struct parsedDataOptions
64 BOOST_PP_SEQ_FOR_EACH_I(declOptions
,_
,keys
)
70 parsedDataOptions options
;
80 BOOST_PP_SEQ_FOR_EACH_I(declOptions
,_
,keys
)
89 std::ostream
&operator<<(std::ostream
& os
, client::parsedData
&data
)
91 os
<< data
.name
<<std::endl
;
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
)
101 std::ostream
&operator<<(std::ostream
& os
, client::parsedData2
&data
)
103 os
<< data
.name
<<std::endl
;
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
)
115 BOOST_FUSION_ADAPT_STRUCT(
116 client::parsedDataOptions
,
117 BOOST_PP_SEQ_FOR_EACH_I(fusionOptions
,_
,keys
)
120 BOOST_FUSION_ADAPT_STRUCT(
123 (client::parsedDataOptions
, options
)
126 BOOST_FUSION_ADAPT_STRUCT(
129 BOOST_PP_SEQ_FOR_EACH_I(fusionOptions
,_
,keys
)
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
>
148 permutation_parser() : permutation_parser::base_type(start
)
155 using boost::phoenix::at_c
;
156 using boost::phoenix::assign
;
164 quoted_string
%= lexeme
[+(char_
-' ')];
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
));
173 v_vals
= repeat(1,2)[int_
];
176 typedef parsedData parser_target_type
;
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
;
182 qi::rule
<Iterator
, parsedData(), ascii::space_type
> start
;
185 template <typename Iterator
>
186 struct alternative_parser
: qi::grammar
<Iterator
, parsedData2(), ascii::space_type
>
188 alternative_parser() : alternative_parser::base_type(start
)
195 using boost::phoenix::at_c
;
200 quoted_string
%= lexeme
[+(char_
-' ')];
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
));
206 quoted_string
[at_c
<0>(_val
)=_1
]
211 typedef parsedData2 parser_target_type
;
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
;
220 template <typename Iterator
,typename variation
>
221 struct tst_parser
: qi::grammar
<Iterator
, parsedData2(), ascii::space_type
>
223 typedef variation variation_type
;
225 tst_parser() : tst_parser::base_type(startalias
)
227 namespace phx
= boost::phoenix
;
233 using boost::phoenix::at_c
;
239 using qi::parameterized_nonterminal
;
241 startalias
= start
.alias();
242 quoted_string
%= lexeme
[+(char_
-' ')];
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
)
247 #define generateOptions3(r, data, i, elem) (elem,& BOOST_PP_CAT(rule,i))
250 options
.add
BOOST_PP_SEQ_FOR_EACH_I(generateOptions3
,_
,keys
);
251 switch(variation_type::value
)
256 quoted_string
[at_c
<0>(_val
)=_1
][phx::ref(currentObj
)=&_val
]
257 >> *( options
[_a
=_1
] >> lazy(*_a
));
264 quoted_string
[at_c
<0>(_val
)=_1
][phx::ref(currentObj
)=&_val
]
265 >> *( options
>> int_
);
272 quoted_string
[at_c
<0>(_val
)=_1
][phx::ref(currentObj
)=&_val
]
273 >> *( options
[_a
=_1
] >> int_
);
282 parsedData2
*currentObj
;
284 typedef parsedData2 parser_target_type
;
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);
290 BOOST_PP_SEQ_FOR_EACH_I(declareRules
,_
,keys
)
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
;
299 template <typename Iterator
,typename variation
>
300 struct tst_map_parser
: qi::grammar
<Iterator
, parsedData2(), ascii::space_type
>
302 typedef variation variation_type
;
303 tst_map_parser() : tst_map_parser::base_type(startalias
)
305 namespace phx
= boost::phoenix
;
311 using boost::phoenix::at_c
;
317 using qi::parameterized_nonterminal
;
319 startalias
= start
.alias();
320 quoted_string
%= lexeme
[+(char_
-' ')];
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
)
325 #define generateOptions3(r, data, i, elem) (elem,& BOOST_PP_CAT(rule,i))
328 options
.add
BOOST_PP_SEQ_FOR_EACH_I(generateOptions3
,_
,keys
);
330 switch(variation_type::value
)
335 quoted_string
[at_c
<0>(_val
)=_1
][phx::ref(currentObj
)=&_val
]
336 >> *( options
[_a
=_1
] >> lazy(*_a
));
343 quoted_string
[at_c
<0>(_val
)=_1
][phx::ref(currentObj
)=&_val
]
344 >> *( options
>> int_
);
351 quoted_string
[at_c
<0>(_val
)=_1
][phx::ref(currentObj
)=&_val
]
352 >> *( options
[_a
=_1
] >> int_
);
359 parsedData2
*currentObj
;
361 typedef parsedData2 parser_target_type
;
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);
367 BOOST_PP_SEQ_FOR_EACH_I(declareRules
,_
,keys
)
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
;
375 template <typename Iterator
>
376 struct kwd_parser
: qi::grammar
<Iterator
, parsedData(), ascii::space_type
>
378 kwd_parser() : kwd_parser::base_type(start
)
388 using boost::spirit::repository::qi::kwd
;
390 quoted_string
%= lexeme
[+(char_
-' ')];
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
));
401 typedef parsedData parser_target_type
;
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
;
407 qi::rule
<Iterator
, parsedData(), ascii::space_type
> start
;
413 template <typename parserType
>
414 struct timeParser
: test::base
{
415 timeParser(const std::string
& str
) : str(str
)
418 parserType
&get_parser(){
419 static parserType parser
;
428 using boost::spirit::ascii::space
;
430 std::string::const_iterator end
= str
.end();
431 std::string::const_iterator iter
= str
.begin();
434 typename
parserType::parser_target_type data
;
435 r
= phrase_parse(iter
, end
, get_parser(), space
, data
);
437 if (r
&& iter
== end
)
439 this->val
+= data
.name
.size();
443 throw std::runtime_error("Parsing failed");
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
;
458 struct permutation_timer_fwd
: timeParser
<permutation_parser
>
460 permutation_timer_fwd() : timeParser
<permutation_parser
>(fwd
) {}
463 struct permutation_timer_back
: timeParser
<permutation_parser
>
465 permutation_timer_back() : timeParser
<permutation_parser
>(back
) {}
468 struct alternative_timer_fwd
: timeParser
<alternative_parser
>
470 alternative_timer_fwd() : timeParser
<alternative_parser
>(fwd
) {}
473 struct alternative_timer_back
: timeParser
<alternative_parser
>
475 alternative_timer_back() : timeParser
<alternative_parser
>(back
) {}
478 struct tst_timer_fwd_full
: timeParser
< client::tst_parser
<iterator_type
, boost::mpl::int_
<full
> > >
480 tst_timer_fwd_full() : timeParser
< client::tst_parser
<iterator_type
, boost::mpl::int_
<full
> > >(fwd
) {}
483 struct tst_timer_fwd_no_assign
: timeParser
< client::tst_parser
<iterator_type
, boost::mpl::int_
<no_assign
> > >
485 tst_timer_fwd_no_assign() : timeParser
< client::tst_parser
<iterator_type
,boost::mpl::int_
<no_assign
> > >(fwd
) {}
488 struct tst_timer_fwd_assign
: timeParser
< client::tst_parser
<iterator_type
,boost::mpl::int_
<assign
> > >
490 tst_timer_fwd_assign() : timeParser
< client::tst_parser
<iterator_type
,boost::mpl::int_
<assign
> > >(fwd
) {}
495 struct tst_timer_back
: timeParser
< client::tst_parser
<iterator_type
,boost::mpl::int_
<full
> > >
497 tst_timer_back() : timeParser
< client::tst_parser
<iterator_type
,boost::mpl::int_
<full
> > >(back
) {}
500 struct tst_map_timer_fwd
: timeParser
<tst_map_parser
>
502 tst_map_timer_fwd() : timeParser
<tst_map_parser
>(fwd
) {}
505 struct tst_map_timer_back
: timeParser
<tst_map_parser
>
507 tst_map_timer_back() : timeParser
<tst_map_parser
>(back
) {}
510 struct kwd_timer_fwd
: timeParser
<kwd_parser
>
512 kwd_timer_fwd() : timeParser
<kwd_parser
>(fwd
) {}
515 struct kwd_timer_back
: timeParser
<kwd_parser
>
517 kwd_timer_back() : timeParser
<kwd_parser
>(back
) {}
524 ////////////////////////////////////////////////////////////////////////////
526 ////////////////////////////////////////////////////////////////////////////
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
)
538 (tst_timer_fwd_no_assign
)
539 (tst_timer_fwd_assign
)
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;