/*============================================================================= 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define KEYS_5 #include "keywords.hpp" #define declOptions(r, data, i, elem) boost::optional BOOST_PP_CAT(option,i); #define fusionOptions(r, data, i, elem) (boost::optional, 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 < struct permutation_parser : qi::grammar { 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 quoted_string; qi::rule options; qi::rule(), ascii::space_type> v_vals; qi::rule start; }; template struct alternative_parser : qi::grammar { 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(_r1)=_1]) , (lit(elem) > int_[at_c(_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 quoted_string; qi::rule options; qi::rule start; }; template struct tst_parser : qi::grammar { 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(*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 quoted_string; typedef qi::rule optionsRule; #define declareRules(r, data, i, elem) optionsRule BOOST_PP_CAT(rule,i); BOOST_PP_SEQ_FOR_EACH_I(declareRules,_,keys) qi::symbols options; qi::rule startalias; qi::rule, ascii::space_type> start; }; template struct tst_map_parser : qi::grammar { 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(*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 quoted_string; typedef qi::rule optionsRule; #define declareRules(r, data, i, elem) optionsRule BOOST_PP_CAT(rule,i); BOOST_PP_SEQ_FOR_EACH_I(declareRules,_,keys) qi::symbols > options; qi::rule startalias; qi::rule, ascii::space_type> start; }; template struct kwd_parser : qi::grammar { 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 quoted_string; qi::rule options; qi::rule,boost::optional > () , ascii::space_type> v_vals; qi::rule start; }; } template 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 permutation_parser; typedef client::kwd_parser kwd_parser; typedef client::alternative_parser alternative_parser; typedef client::tst_map_parser > tst_map_parser; struct permutation_timer_fwd : timeParser { permutation_timer_fwd() : timeParser(fwd) {} }; struct permutation_timer_back : timeParser { permutation_timer_back() : timeParser(back) {} }; struct alternative_timer_fwd : timeParser { alternative_timer_fwd() : timeParser(fwd) {} }; struct alternative_timer_back : timeParser { alternative_timer_back() : timeParser(back) {} }; struct tst_timer_fwd_full : timeParser< client::tst_parser > > { tst_timer_fwd_full() : timeParser< client::tst_parser > >(fwd) {} }; struct tst_timer_fwd_no_assign : timeParser< client::tst_parser > > { tst_timer_fwd_no_assign() : timeParser< client::tst_parser > >(fwd) {} }; struct tst_timer_fwd_assign : timeParser< client::tst_parser > > { tst_timer_fwd_assign() : timeParser< client::tst_parser > >(fwd) {} }; struct tst_timer_back : timeParser< client::tst_parser > > { tst_timer_back() : timeParser< client::tst_parser > >(back) {} }; struct tst_map_timer_fwd : timeParser { tst_map_timer_fwd() : timeParser(fwd) {} }; struct tst_map_timer_back : timeParser { tst_map_timer_back() : timeParser(back) {} }; struct kwd_timer_fwd : timeParser { kwd_timer_fwd() : timeParser(fwd) {} }; struct kwd_timer_back : timeParser { kwd_timer_back() : timeParser(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; }