1 /*============================================================================= 2 Copyright (c) 1998-2003 Joel de Guzman 3 Copyright (c) 2002 Raghavendra Satish 4 Copyright (c) 2002 Jeff Westfahl 5 http://spirit.sourceforge.net/ 6 7 Distributed under the Boost Software License, Version 1.0. (See accompanying 8 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 =============================================================================*/ 10 #if !defined(BOOST_SPIRIT_LOOPS_HPP) 11 #define BOOST_SPIRIT_LOOPS_HPP 12 13 /////////////////////////////////////////////////////////////////////////////// 14 #include <boost/spirit/home/classic/namespace.hpp> 15 #include <boost/spirit/home/classic/core/parser.hpp> 16 #include <boost/spirit/home/classic/core/composite/composite.hpp> 17 #include <boost/mpl/if.hpp> 18 #include <boost/type_traits/is_same.hpp> 19 20 /////////////////////////////////////////////////////////////////////////////// 21 namespace boost { namespace spirit { 22 23 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN 24 25 /////////////////////////////////////////////////////////////////////////// 26 // 27 // fixed_loop class 28 // 29 // This class takes care of the construct: 30 // 31 // repeat_p (exact) [p] 32 // 33 // where 'p' is a parser and 'exact' is the number of times to 34 // repeat. The parser iterates over the input exactly 'exact' times. 35 // The parse function fails if the parser does not match the input 36 // exactly 'exact' times. 37 // 38 // This class is parametizable and can accept constant arguments 39 // (e.g. repeat_p (5) [p]) as well as references to variables (e.g. 40 // repeat_p (ref (n)) [p]). 41 // 42 /////////////////////////////////////////////////////////////////////////// 43 template <typename ParserT, typename ExactT> 44 class fixed_loop 45 : public unary<ParserT, parser <fixed_loop <ParserT, ExactT> > > 46 { 47 public: 48 49 typedef fixed_loop<ParserT, ExactT> self_t; 50 typedef unary<ParserT, parser<self_t> > base_t; 51 fixed_loop(ParserT const & subject_,ExactT const & exact)52 fixed_loop (ParserT const & subject_, ExactT const & exact) 53 : base_t(subject_), m_exact(exact) {} 54 55 template <typename ScannerT> 56 typename parser_result <self_t, ScannerT>::type parse(ScannerT const & scan) const57 parse (ScannerT const & scan) const 58 { 59 typedef typename parser_result<self_t, ScannerT>::type result_t; 60 result_t hit = scan.empty_match(); 61 std::size_t n = m_exact; 62 63 for (std::size_t i = 0; i < n; ++i) 64 { 65 if (result_t next = this->subject().parse(scan)) 66 { 67 scan.concat_match(hit, next); 68 } 69 else 70 { 71 return scan.no_match(); 72 } 73 } 74 75 return hit; 76 } 77 78 template <typename ScannerT> 79 struct result 80 { 81 typedef typename match_result<ScannerT, nil_t>::type type; 82 }; 83 84 private: 85 86 ExactT m_exact; 87 }; 88 89 /////////////////////////////////////////////////////////////////////////////// 90 // 91 // finite_loop class 92 // 93 // This class takes care of the construct: 94 // 95 // repeat_p (min, max) [p] 96 // 97 // where 'p' is a parser, 'min' and 'max' specifies the minimum and 98 // maximum iterations over 'p'. The parser iterates over the input 99 // at least 'min' times and at most 'max' times. The parse function 100 // fails if the parser does not match the input at least 'min' times 101 // and at most 'max' times. 102 // 103 // This class is parametizable and can accept constant arguments 104 // (e.g. repeat_p (5, 10) [p]) as well as references to variables 105 // (e.g. repeat_p (ref (n1), ref (n2)) [p]). 106 // 107 /////////////////////////////////////////////////////////////////////////////// 108 template <typename ParserT, typename MinT, typename MaxT> 109 class finite_loop 110 : public unary<ParserT, parser<finite_loop<ParserT, MinT, MaxT> > > 111 { 112 public: 113 114 typedef finite_loop <ParserT, MinT, MaxT> self_t; 115 typedef unary<ParserT, parser<self_t> > base_t; 116 finite_loop(ParserT const & subject_,MinT const & min,MaxT const & max)117 finite_loop (ParserT const & subject_, MinT const & min, MaxT const & max) 118 : base_t(subject_), m_min(min), m_max(max) {} 119 120 template <typename ScannerT> 121 typename parser_result <self_t, ScannerT>::type parse(ScannerT const & scan) const122 parse(ScannerT const & scan) const 123 { 124 BOOST_SPIRIT_ASSERT(m_min <= m_max); 125 typedef typename parser_result<self_t, ScannerT>::type result_t; 126 result_t hit = scan.empty_match(); 127 128 std::size_t n1 = m_min; 129 std::size_t n2 = m_max; 130 131 for (std::size_t i = 0; i < n2; ++i) 132 { 133 typename ScannerT::iterator_t save = scan.first; 134 result_t next = this->subject().parse(scan); 135 136 if (!next) 137 { 138 if (i >= n1) 139 { 140 scan.first = save; 141 break; 142 } 143 else 144 { 145 return scan.no_match(); 146 } 147 } 148 149 scan.concat_match(hit, next); 150 } 151 152 return hit; 153 } 154 155 template <typename ScannerT> 156 struct result 157 { 158 typedef typename match_result<ScannerT, nil_t>::type type; 159 }; 160 161 private: 162 163 MinT m_min; 164 MaxT m_max; 165 }; 166 167 /////////////////////////////////////////////////////////////////////////////// 168 // 169 // infinite_loop class 170 // 171 // This class takes care of the construct: 172 // 173 // repeat_p (min, more) [p] 174 // 175 // where 'p' is a parser, 'min' is the minimum iteration over 'p' 176 // and more specifies that the iteration should proceed 177 // indefinitely. The parser iterates over the input at least 'min' 178 // times and continues indefinitely until 'p' fails or all of the 179 // input is parsed. The parse function fails if the parser does not 180 // match the input at least 'min' times. 181 // 182 // This class is parametizable and can accept constant arguments 183 // (e.g. repeat_p (5, more) [p]) as well as references to variables 184 // (e.g. repeat_p (ref (n), more) [p]). 185 // 186 /////////////////////////////////////////////////////////////////////////////// 187 188 struct more_t {}; 189 more_t const more = more_t (); 190 191 template <typename ParserT, typename MinT> 192 class infinite_loop 193 : public unary<ParserT, parser<infinite_loop<ParserT, MinT> > > 194 { 195 public: 196 197 typedef infinite_loop <ParserT, MinT> self_t; 198 typedef unary<ParserT, parser<self_t> > base_t; 199 infinite_loop(ParserT const & subject_,MinT const & min,more_t const &)200 infinite_loop ( 201 ParserT const& subject_, 202 MinT const& min, 203 more_t const& 204 ) 205 : base_t(subject_), m_min(min) {} 206 207 template <typename ScannerT> 208 typename parser_result <self_t, ScannerT>::type parse(ScannerT const & scan) const209 parse(ScannerT const & scan) const 210 { 211 typedef typename parser_result<self_t, ScannerT>::type result_t; 212 result_t hit = scan.empty_match(); 213 std::size_t n = m_min; 214 215 for (std::size_t i = 0; ; ++i) 216 { 217 typename ScannerT::iterator_t save = scan.first; 218 result_t next = this->subject().parse(scan); 219 220 if (!next) 221 { 222 if (i >= n) 223 { 224 scan.first = save; 225 break; 226 } 227 else 228 { 229 return scan.no_match(); 230 } 231 } 232 233 scan.concat_match(hit, next); 234 } 235 236 return hit; 237 } 238 239 template <typename ScannerT> 240 struct result 241 { 242 typedef typename match_result<ScannerT, nil_t>::type type; 243 }; 244 245 private: 246 247 MinT m_min; 248 }; 249 250 template <typename ExactT> 251 struct fixed_loop_gen 252 { fixed_loop_genboost::spirit::fixed_loop_gen253 fixed_loop_gen (ExactT const & exact) 254 : m_exact (exact) {} 255 256 template <typename ParserT> 257 fixed_loop <ParserT, ExactT> operator []boost::spirit::fixed_loop_gen258 operator[](parser <ParserT> const & subject_) const 259 { 260 return fixed_loop <ParserT, ExactT> (subject_.derived (), m_exact); 261 } 262 263 ExactT m_exact; 264 }; 265 266 namespace impl { 267 268 template <typename ParserT, typename MinT, typename MaxT> 269 struct loop_traits 270 { 271 typedef typename mpl::if_< 272 boost::is_same<MaxT, more_t>, 273 infinite_loop<ParserT, MinT>, 274 finite_loop<ParserT, MinT, MaxT> 275 >::type type; 276 }; 277 278 } // namespace impl 279 280 template <typename MinT, typename MaxT> 281 struct nonfixed_loop_gen 282 { nonfixed_loop_genboost::spirit::nonfixed_loop_gen283 nonfixed_loop_gen (MinT min, MaxT max) 284 : m_min (min), m_max (max) {} 285 286 template <typename ParserT> 287 typename impl::loop_traits<ParserT, MinT, MaxT>::type operator []boost::spirit::nonfixed_loop_gen288 operator[](parser <ParserT> const & subject_) const 289 { 290 typedef typename impl::loop_traits<ParserT, MinT, MaxT>::type ret_t; 291 return ret_t( 292 subject_.derived(), 293 m_min, 294 m_max); 295 } 296 297 MinT m_min; 298 MaxT m_max; 299 }; 300 301 template <typename ExactT> 302 fixed_loop_gen <ExactT> repeat_p(ExactT const & exact)303 repeat_p(ExactT const & exact) 304 { 305 return fixed_loop_gen <ExactT> (exact); 306 } 307 308 template <typename MinT, typename MaxT> 309 nonfixed_loop_gen <MinT, MaxT> repeat_p(MinT const & min,MaxT const & max)310 repeat_p(MinT const & min, MaxT const & max) 311 { 312 return nonfixed_loop_gen <MinT, MaxT> (min, max); 313 } 314 315 BOOST_SPIRIT_CLASSIC_NAMESPACE_END 316 317 }} // namespace BOOST_SPIRIT_CLASSIC_NS 318 319 #endif // #if !defined(BOOST_SPIRIT_LOOPS_HPP) 320