123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553 |
- /*=============================================================================
- Copyright (c) 2001-2011 Joel de Guzman
- Copyright (c) 2011 Thomas Bernard
- Distributed under the Boost Software License, Version 1.0. (See accompanying
- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- =============================================================================*/
- #define FUSION_MAX_VECTOR_SIZE 50
- #define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
- #define BOOST_MPL_LIMIT_LIST_SIZE 50
- #define BOOST_MPL_LIMIT_VECTOR_SIZE 50
- #include "../measure.hpp"
- #include <boost/config/warning_disable.hpp>
- #include <boost/spirit/include/qi.hpp>
- #include <boost/spirit/include/phoenix_core.hpp>
- #include <boost/spirit/include/phoenix_operator.hpp>
- #include <boost/spirit/include/phoenix_object.hpp>
- #include <boost/spirit/include/phoenix_fusion.hpp>
- #include <boost/spirit/include/phoenix_container.hpp>
- #include <boost/fusion/include/adapt_struct.hpp>
- #include <boost/fusion/include/io.hpp>
- #include <boost/spirit/include/qi_permutation.hpp>
- #include <boost/spirit/home/qi/string/tst_map.hpp>
- #include <boost/spirit/repository/include/qi_kwd.hpp>
- #include <boost/spirit/repository/include/qi_keywords.hpp>
- #include <boost/optional.hpp>
- #include <boost/spirit/home/phoenix/core/argument.hpp>
- #include <boost/spirit/home/phoenix/bind/bind_member_variable.hpp>
- #include <iostream>
- #include <string>
- #include <complex>
- #include <vector>
- #include <iterator>
- #include <stdexcept>
- #include <boost/preprocessor/control/if.hpp>
- #include <boost/preprocessor/seq/for_each_i.hpp>
- #include <boost/preprocessor/seq/size.hpp>
- #include <boost/preprocessor/cat.hpp>
- #include <boost/preprocessor/stringize.hpp>
- #define KEYS_5
- #include "keywords.hpp"
- #define declOptions(r, data, i, elem) boost::optional<int> BOOST_PP_CAT(option,i);
- #define fusionOptions(r, data, i, elem) (boost::optional<int>, BOOST_PP_CAT(option,i))
- namespace client
- {
- namespace qi = boost::spirit::qi;
- namespace ascii = boost::spirit::ascii;
- ///////////////////////////////////////////////////////////////////////////
- // Our parsedData struct
- ///////////////////////////////////////////////////////////////////////////
- //[tutorial_parsedData_struct
- struct parsedDataOptions
- {
- BOOST_PP_SEQ_FOR_EACH_I(declOptions,_,keys)
- };
- struct parsedData
- {
- std::string name;
- parsedDataOptions options;
- void clear()
- {
- name.clear();
- }
- };
- struct parsedData2
- {
- std::string name;
- BOOST_PP_SEQ_FOR_EACH_I(declOptions,_,keys)
- void clear()
- {
- name.clear();
- }
- };
- }
- std::ostream &operator<<(std::ostream & os, client::parsedData &data)
- {
- os << data.name <<std::endl;
- #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;
- BOOST_PP_SEQ_FOR_EACH_I(generateOutput1,_,keys)
- os<<std::endl;
- return os;
- }
- std::ostream &operator<<(std::ostream & os, client::parsedData2 &data)
- {
- os << data.name <<std::endl;
- #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;
- BOOST_PP_SEQ_FOR_EACH_I(generateOutput2,_,keys)
- os<<std::endl;
- return os;
- }
- BOOST_FUSION_ADAPT_STRUCT(
- client::parsedDataOptions,
- BOOST_PP_SEQ_FOR_EACH_I(fusionOptions,_,keys)
- )
- BOOST_FUSION_ADAPT_STRUCT(
- client::parsedData,
- (std::string, name)
- (client::parsedDataOptions, options)
- )
- BOOST_FUSION_ADAPT_STRUCT(
- client::parsedData2,
- (std::string, name)
- BOOST_PP_SEQ_FOR_EACH_I(fusionOptions,_,keys)
- )
- enum variation
- {
- full,
- no_assign,
- assign
- };
- namespace client
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Our parsedData parser
- ///////////////////////////////////////////////////////////////////////////////
- //[tutorial_parsedData_parser
- template <typename Iterator>
- struct permutation_parser : qi::grammar<Iterator, parsedData(), ascii::space_type>
- {
- permutation_parser() : permutation_parser::base_type(start)
- {
- using qi::int_;
- using qi::lit;
- using qi::double_;
- using qi::lexeme;
- using ascii::char_;
- using boost::phoenix::at_c;
- using boost::phoenix::assign;
- using qi::_r1;
- using qi::_1;
- using qi::_val;
- using qi::omit;
- using qi::repeat;
- quoted_string %= lexeme[+(char_-' ')];
- #define generateOptions1(r, data, i, elem) BOOST_PP_IF(i, ^(lit(elem) > int_) , (lit(elem) > int_))
- options = (BOOST_PP_SEQ_FOR_EACH_I(generateOptions1,_,keys));
- start %=
- quoted_string
- >> options;
- ;
- v_vals = repeat(1,2)[int_];
- }
- typedef parsedData parser_target_type;
- qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
- qi::rule<Iterator, parsedDataOptions(), ascii::space_type> options;
- qi::rule<Iterator, std::vector<int>(), ascii::space_type> v_vals;
- qi::rule<Iterator, parsedData(), ascii::space_type> start;
- };
- template <typename Iterator>
- struct alternative_parser : qi::grammar<Iterator, parsedData2(), ascii::space_type>
- {
- alternative_parser() : alternative_parser::base_type(start)
- {
- using qi::int_;
- using qi::lit;
- using qi::double_;
- using qi::lexeme;
- using ascii::char_;
- using boost::phoenix::at_c;
- using qi::_r1;
- using qi::_1;
- using qi::_val;
- quoted_string %= lexeme[+(char_-' ')];
- #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]))
- options = (BOOST_PP_SEQ_FOR_EACH_I(generateOptions2,_,keys));
- start =
- quoted_string [at_c<0>(_val)=_1]
- >> *options(_val);
- ;
- }
- typedef parsedData2 parser_target_type;
- qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
- qi::rule<Iterator, void(parsedData2 & ), ascii::space_type> options;
- qi::rule<Iterator, parsedData2(), ascii::space_type> start;
- };
- template <typename Iterator,typename variation>
- struct tst_parser : qi::grammar<Iterator, parsedData2(), ascii::space_type>
- {
- typedef variation variation_type;
- tst_parser() : tst_parser::base_type(startalias)
- {
- namespace phx = boost::phoenix;
- using qi::int_;
- using qi::lit;
- using qi::double_;
- using qi::lexeme;
- using ascii::char_;
- using boost::phoenix::at_c;
- using qi::_r1;
- using qi::_1;
- using qi::_a;
- using qi::_val;
- using qi::locals;
- using qi::parameterized_nonterminal;
- startalias = start.alias();
- quoted_string %= lexeme[+(char_-' ')];
- #define generateRules(r, data, i, elem) BOOST_PP_CAT(rule,i) = int_[phx::at_c<i+1>(*phx::ref(currentObj))=_1];
- BOOST_PP_SEQ_FOR_EACH_I(generateRules,_,keys)
- #define generateOptions3(r, data, i, elem) (elem,& BOOST_PP_CAT(rule,i))
- options.add BOOST_PP_SEQ_FOR_EACH_I(generateOptions3,_,keys);
- switch(variation_type::value)
- {
- case full:
- {
- start =
- quoted_string [at_c<0>(_val)=_1][phx::ref(currentObj)=&_val]
- >> *( options [_a=_1] >> lazy(*_a));
- ;
- break;
- }
- case no_assign:
- {
- start =
- quoted_string [at_c<0>(_val)=_1][phx::ref(currentObj)=&_val]
- >> *( options >> int_);
- ;
- break;
- }
- case assign:
- {
- start =
- quoted_string [at_c<0>(_val)=_1][phx::ref(currentObj)=&_val]
- >> *( options [_a=_1] >> int_);
- ;
- break;
- }
- }
- }
- parsedData2 *currentObj;
- typedef parsedData2 parser_target_type;
- qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
- typedef qi::rule<Iterator, ascii::space_type> optionsRule;
- #define declareRules(r, data, i, elem) optionsRule BOOST_PP_CAT(rule,i);
- BOOST_PP_SEQ_FOR_EACH_I(declareRules,_,keys)
- qi::symbols<char,optionsRule* > options;
- qi::rule<Iterator, parsedData2(), ascii::space_type> startalias;
- qi::rule<Iterator, parsedData2(), qi::locals<optionsRule*>, ascii::space_type> start;
- };
- template <typename Iterator,typename variation>
- struct tst_map_parser : qi::grammar<Iterator, parsedData2(), ascii::space_type>
- {
- typedef variation variation_type;
- tst_map_parser() : tst_map_parser::base_type(startalias)
- {
- namespace phx = boost::phoenix;
- using qi::int_;
- using qi::lit;
- using qi::double_;
- using qi::lexeme;
- using ascii::char_;
- using boost::phoenix::at_c;
- using qi::_r1;
- using qi::_1;
- using qi::_a;
- using qi::_val;
- using qi::locals;
- using qi::parameterized_nonterminal;
- startalias = start.alias();
- quoted_string %= lexeme[+(char_-' ')];
- #define generateRules3(r, data, i, elem) BOOST_PP_CAT(rule,i) = int_[phx::at_c<i+1>(*phx::ref(currentObj))=_1];
- BOOST_PP_SEQ_FOR_EACH_I(generateRules3,_,keys)
- #define generateOptions3(r, data, i, elem) (elem,& BOOST_PP_CAT(rule,i))
- options.add BOOST_PP_SEQ_FOR_EACH_I(generateOptions3,_,keys);
- switch(variation_type::value)
- {
- case full:
- {
- start =
- quoted_string [at_c<0>(_val)=_1][phx::ref(currentObj)=&_val]
- >> *( options [_a=_1] >> lazy(*_a));
- ;
- break;
- }
- case no_assign:
- {
- start =
- quoted_string [at_c<0>(_val)=_1][phx::ref(currentObj)=&_val]
- >> *( options >> int_);
- ;
- break;
- }
- case assign:
- {
- start =
- quoted_string [at_c<0>(_val)=_1][phx::ref(currentObj)=&_val]
- >> *( options [_a=_1] >> int_);
- ;
- break;
- }
- }
- }
- parsedData2 *currentObj;
- typedef parsedData2 parser_target_type;
- qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
- typedef qi::rule<Iterator, ascii::space_type> optionsRule;
- #define declareRules(r, data, i, elem) optionsRule BOOST_PP_CAT(rule,i);
- BOOST_PP_SEQ_FOR_EACH_I(declareRules,_,keys)
- qi::symbols<char,optionsRule*, boost::spirit::qi::tst_map<char,optionsRule*> > options;
- qi::rule<Iterator, parsedData2(), ascii::space_type> startalias;
- qi::rule<Iterator, parsedData2(), qi::locals<optionsRule*>, ascii::space_type> start;
- };
- template <typename Iterator>
- struct kwd_parser : qi::grammar<Iterator, parsedData(), ascii::space_type>
- {
- kwd_parser() : kwd_parser::base_type(start)
- {
- using qi::int_;
- using qi::lit;
- using qi::double_;
- using qi::lexeme;
- using ascii::char_;
- using qi::_r1;
- using qi::_1;
- using qi::_val;
- using boost::spirit::repository::qi::kwd;
- quoted_string %= lexeme[+(char_-' ')];
- #define generateOptions4(r, data, i, elem) BOOST_PP_IF(i, / kwd( elem )[ int_ ] , kwd( elem )[ int_ ] )
- options = (BOOST_PP_SEQ_FOR_EACH_I(generateOptions4,_,keys));
- start %=
- quoted_string
- >> options;
- ;
- }
- typedef parsedData parser_target_type;
- qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
- qi::rule<Iterator, parsedDataOptions(), ascii::space_type> options;
- qi::rule<Iterator, boost::fusion::vector<boost::optional<int>,boost::optional<int> > () , ascii::space_type> v_vals;
- qi::rule<Iterator, parsedData(), ascii::space_type> start;
- };
- }
- template <typename parserType>
- struct timeParser : test::base{
- timeParser(const std::string & str) : str(str)
- {
- }
- parserType &get_parser(){
- static parserType parser;
- return parser;
- }
- std::string str;
- void benchmark()
- {
- using boost::spirit::ascii::space;
- bool r = false;
- std::string::const_iterator end = str.end();
- std::string::const_iterator iter = str.begin();
- typename parserType::parser_target_type data;
- r = phrase_parse(iter, end, get_parser(), space, data);
- if (r && iter == end)
- {
- this->val += data.name.size();
- }
- else
- {
- throw std::runtime_error("Parsing failed");
- }
- }
- };
- typedef std::string::const_iterator iterator_type;
- typedef client::permutation_parser<iterator_type> permutation_parser;
- typedef client::kwd_parser<iterator_type> kwd_parser;
- typedef client::alternative_parser<iterator_type> alternative_parser;
- typedef client::tst_map_parser<iterator_type, boost::mpl::int_<full> > tst_map_parser;
- struct permutation_timer_fwd : timeParser<permutation_parser>
- {
- permutation_timer_fwd() : timeParser<permutation_parser>(fwd) {}
- };
- struct permutation_timer_back : timeParser<permutation_parser>
- {
- permutation_timer_back() : timeParser<permutation_parser>(back) {}
- };
- struct alternative_timer_fwd : timeParser<alternative_parser>
- {
- alternative_timer_fwd() : timeParser<alternative_parser>(fwd) {}
- };
- struct alternative_timer_back : timeParser<alternative_parser>
- {
- alternative_timer_back() : timeParser<alternative_parser>(back) {}
- };
- struct tst_timer_fwd_full : timeParser< client::tst_parser<iterator_type, boost::mpl::int_<full> > >
- {
- tst_timer_fwd_full() : timeParser< client::tst_parser<iterator_type, boost::mpl::int_<full> > >(fwd) {}
- };
- struct tst_timer_fwd_no_assign : timeParser< client::tst_parser<iterator_type, boost::mpl::int_<no_assign> > >
- {
- tst_timer_fwd_no_assign() : timeParser< client::tst_parser<iterator_type,boost::mpl::int_<no_assign> > >(fwd) {}
- };
- struct tst_timer_fwd_assign : timeParser< client::tst_parser<iterator_type,boost::mpl::int_<assign> > >
- {
- tst_timer_fwd_assign() : timeParser< client::tst_parser<iterator_type,boost::mpl::int_<assign> > >(fwd) {}
- };
- struct tst_timer_back : timeParser< client::tst_parser<iterator_type,boost::mpl::int_<full> > >
- {
- tst_timer_back() : timeParser< client::tst_parser<iterator_type,boost::mpl::int_<full> > >(back) {}
- };
- struct tst_map_timer_fwd : timeParser<tst_map_parser>
- {
- tst_map_timer_fwd() : timeParser<tst_map_parser>(fwd) {}
- };
- struct tst_map_timer_back : timeParser<tst_map_parser>
- {
- tst_map_timer_back() : timeParser<tst_map_parser>(back) {}
- };
- struct kwd_timer_fwd : timeParser<kwd_parser>
- {
- kwd_timer_fwd() : timeParser<kwd_parser>(fwd) {}
- };
- struct kwd_timer_back : timeParser<kwd_parser>
- {
- kwd_timer_back() : timeParser<kwd_parser>(back) {}
- };
- ////////////////////////////////////////////////////////////////////////////
- // Main program
- ////////////////////////////////////////////////////////////////////////////
- int
- main()
- {
- BOOST_SPIRIT_TEST_BENCHMARK(
- 10000000000, // This is the maximum repetitions to execute
- (permutation_timer_fwd)
- (permutation_timer_back)
- (alternative_timer_fwd)
- (alternative_timer_back)
- (tst_timer_fwd_full)
- (tst_timer_fwd_no_assign)
- (tst_timer_fwd_assign)
- (tst_timer_back)
- (tst_map_timer_fwd)
- (tst_map_timer_back)
- (kwd_timer_fwd)
- (kwd_timer_back)
- )
- // This is ultimately responsible for preventing all the test code
- // from being optimized away. Change this to return 0 and you
- // unplug the whole test's life support system.
- return test::live_code != 0;
- }
|