1 /*============================================================================= 2 Copyright (c) 2002-2003 Joel de Guzman 3 Copyright (c) 2002-2003 Martin Wille 4 http://spirit.sourceforge.net/ 5 6 Distributed under the Boost Software License, Version 1.0. (See accompanying 7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 =============================================================================*/ 9 #ifndef BOOST_SPIRIT_FOR_HPP 10 #define BOOST_SPIRIT_FOR_HPP 11 //////////////////////////////////////////////////////////////////////////////// 12 #include <boost/spirit/home/classic/namespace.hpp> 13 #include <boost/spirit/home/classic/core/parser.hpp> 14 #include <boost/spirit/home/classic/core/composite/composite.hpp> 15 #include <boost/spirit/home/classic/dynamic/impl/conditions.ipp> 16 17 //////////////////////////////////////////////////////////////////////////////// 18 19 namespace boost { namespace spirit { 20 21 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN 22 23 namespace impl 24 { 25 26 template <typename FuncT> 27 struct for_functor 28 { 29 typedef typename boost::call_traits<FuncT>::param_type param_t; 30 for_functorboost::spirit::impl::for_functor31 for_functor(param_t f) : func(f) {} for_functorboost::spirit::impl::for_functor32 for_functor() {} 33 FuncT func; 34 }; 35 36 template <typename InitF> 37 struct for_init_functor : for_functor<InitF> 38 { 39 typedef for_functor<InitF> base_t; 40 typedef typename base_t::param_t param_t; 41 for_init_functorboost::spirit::impl::for_init_functor42 for_init_functor(param_t f) : base_t(f) {} for_init_functorboost::spirit::impl::for_init_functor43 for_init_functor() : base_t() {} initboost::spirit::impl::for_init_functor44 void init() const { /*return*/ this->func(); } 45 }; 46 47 template <typename StepF> 48 struct for_step_functor : for_functor<StepF> 49 { 50 typedef for_functor<StepF> base_t; 51 typedef typename base_t::param_t param_t; 52 for_step_functorboost::spirit::impl::for_step_functor53 for_step_functor(param_t f) : base_t(f) {} for_step_functorboost::spirit::impl::for_step_functor54 for_step_functor() : base_t() {} stepboost::spirit::impl::for_step_functor55 void step() const { /*return*/ this->func(); } 56 }; 57 58 ////////////////////////////////// 59 // for_parser 60 template 61 < 62 typename InitF, typename CondT, typename StepF, 63 typename ParsableT 64 > 65 struct for_parser 66 : private for_init_functor<InitF> 67 , private for_step_functor<StepF> 68 , private condition_evaluator<typename as_parser<CondT>::type> 69 , public unary 70 < 71 typename as_parser<ParsableT>::type, 72 parser< for_parser<InitF, CondT, StepF, ParsableT> > 73 > 74 { 75 typedef for_parser<InitF, CondT, StepF, ParsableT> self_t; 76 typedef as_parser<CondT> cond_as_parser_t; 77 typedef typename cond_as_parser_t::type condition_t; 78 typedef condition_evaluator<condition_t> eval_t; 79 typedef as_parser<ParsableT> as_parser_t; 80 typedef typename as_parser_t::type parser_t; 81 typedef unary< parser_t, parser< self_t > > base_t; 82 83 84 ////////////////////////////// 85 // constructor, saves init, condition and step functors 86 // for later use the parse member function for_parserboost::spirit::impl::for_parser87 for_parser 88 ( 89 InitF const &i, CondT const &c, StepF const &s, 90 ParsableT const &p 91 ) 92 : for_init_functor<InitF>(i) 93 , for_step_functor<StepF>(s) 94 , eval_t(cond_as_parser_t::convert(c)) 95 , base_t(as_parser_t::convert(p)) 96 { } 97 for_parserboost::spirit::impl::for_parser98 for_parser() 99 : for_init_functor<InitF>() 100 , for_step_functor<StepF>() 101 , eval_t() 102 , base_t() 103 {} 104 105 ////////////////////////////// 106 // parse member function 107 template <typename ScannerT> 108 typename parser_result<self_t, ScannerT>::type parseboost::spirit::impl::for_parser109 parse(ScannerT const &scan) const 110 { 111 typedef typename parser_result<parser_t, ScannerT>::type 112 body_result_t; 113 114 typename ScannerT::iterator_t save(scan.first); 115 116 std::size_t length = 0; 117 std::ptrdiff_t eval_length = 0; 118 119 this->init(); 120 while ((eval_length = this->evaluate(scan))>=0) 121 { 122 length += eval_length; 123 body_result_t tmp(this->subject().parse(scan)); 124 if (tmp) 125 { 126 length+=tmp.length(); 127 } 128 else 129 { 130 return scan.no_match(); 131 } 132 this->step(); 133 } 134 135 BOOST_SPIRIT_CLASSIC_NS::nil_t attr; 136 return scan.create_match 137 (length, attr, save, scan.first); 138 } 139 }; 140 141 ////////////////////////////////// 142 // for_parser_gen generates takes the body parser in brackets 143 // and returns the for_parser 144 template <typename InitF, typename CondT, typename StepF> 145 struct for_parser_gen 146 { for_parser_genboost::spirit::impl::for_parser_gen147 for_parser_gen(InitF const &i, CondT const &c, StepF const &s) 148 : init(i) 149 , condition(c) 150 , step(s) 151 {} 152 153 template <typename ParsableT> 154 for_parser<InitF, CondT, StepF, ParsableT> operator []boost::spirit::impl::for_parser_gen155 operator[](ParsableT const &p) const 156 { 157 return for_parser<InitF, CondT, StepF, ParsableT> 158 (init, condition, step, p); 159 } 160 161 InitF const &init; 162 CondT const &condition; 163 StepF const &step; 164 }; 165 } // namespace impl 166 167 ////////////////////////////// 168 // for_p, returns for-parser generator 169 // Usage: spirit::for_p(init-ftor, condition, step-ftor)[body] 170 template 171 < 172 typename InitF, typename ConditionT, typename StepF 173 > 174 impl::for_parser_gen<InitF, ConditionT, StepF> for_p(InitF const & init_f,ConditionT const & condition,StepF const & step_f)175 for_p(InitF const &init_f, ConditionT const &condition, StepF const &step_f) 176 { 177 return impl::for_parser_gen<InitF, ConditionT, StepF> 178 (init_f, condition, step_f); 179 } 180 181 BOOST_SPIRIT_CLASSIC_NAMESPACE_END 182 183 }} // namespace BOOST_SPIRIT_CLASSIC_NS 184 185 #endif // BOOST_SPIRIT_FOR_HPP 186