1 /*============================================================================= 2 Copyright (c) 2001-2011 Joel de Guzman 3 4 Distributed under the Boost Software License, Version 1.0. (See accompanying 5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 ==============================================================================*/ 7 #if !defined(BOOST_SPIRIT_SYMBOLS_MARCH_11_2007_1055AM) 8 #define BOOST_SPIRIT_SYMBOLS_MARCH_11_2007_1055AM 9 10 #if defined(_MSC_VER) 11 #pragma once 12 #endif 13 14 #include <boost/spirit/home/qi/domain.hpp> 15 #include <boost/spirit/home/qi/skip_over.hpp> 16 #include <boost/spirit/home/qi/string/tst.hpp> 17 #include <boost/spirit/home/qi/reference.hpp> 18 #include <boost/spirit/home/qi/meta_compiler.hpp> 19 #include <boost/spirit/home/qi/detail/assign_to.hpp> 20 #include <boost/spirit/home/qi/parser.hpp> 21 #include <boost/spirit/home/support/detail/get_encoding.hpp> 22 #include <boost/spirit/home/support/modify.hpp> 23 #include <boost/spirit/home/support/info.hpp> 24 #include <boost/spirit/home/support/unused.hpp> 25 #include <boost/spirit/home/support/string_traits.hpp> 26 #include <boost/proto/extends.hpp> 27 #include <boost/proto/traits.hpp> 28 #include <boost/range/begin.hpp> 29 #include <boost/range/end.hpp> 30 #include <boost/shared_ptr.hpp> 31 32 #if defined(BOOST_MSVC) 33 # pragma warning(push) 34 # pragma warning(disable: 4355) // 'this' : used in base member initializer list warning 35 #endif 36 37 namespace boost { namespace spirit { namespace qi 38 { 39 template < 40 typename Char = char 41 , typename T = unused_type 42 , typename Lookup = tst<Char, T> 43 , typename Filter = tst_pass_through> 44 struct symbols 45 : proto::extends< 46 typename proto::terminal< 47 reference<symbols<Char, T, Lookup, Filter> > 48 >::type 49 , symbols<Char, T, Lookup, Filter> 50 > 51 , primitive_parser<symbols<Char, T, Lookup, Filter> > 52 { 53 typedef Char char_type; // the character type 54 typedef T value_type; // the value associated with each entry 55 typedef symbols<Char, T, Lookup, Filter> this_type; 56 typedef reference<this_type> reference_; 57 typedef typename proto::terminal<reference_>::type terminal; 58 typedef proto::extends<terminal, this_type> base_type; 59 60 template <typename Context, typename Iterator> 61 struct attribute 62 { 63 typedef value_type type; 64 }; 65 symbolsboost::spirit::qi::symbols66 symbols(std::string const& name = "symbols") 67 : base_type(terminal::make(reference_(*this))) 68 , add(*this) 69 , remove(*this) 70 , lookup(new Lookup()) 71 , name_(name) 72 { 73 } 74 symbolsboost::spirit::qi::symbols75 symbols(symbols const& syms) 76 : base_type(terminal::make(reference_(*this))) 77 , add(*this) 78 , remove(*this) 79 , lookup(syms.lookup) 80 , name_(syms.name_) 81 { 82 } 83 84 template <typename Filter_> symbolsboost::spirit::qi::symbols85 symbols(symbols<Char, T, Lookup, Filter_> const& syms) 86 : base_type(terminal::make(reference_(*this))) 87 , add(*this) 88 , remove(*this) 89 , lookup(syms.lookup) 90 , name_(syms.name_) 91 { 92 } 93 94 template <typename Symbols> symbolsboost::spirit::qi::symbols95 symbols(Symbols const& syms, std::string const& name = "symbols") 96 : base_type(terminal::make(reference_(*this))) 97 , add(*this) 98 , remove(*this) 99 , lookup(new Lookup()) 100 , name_(name) 101 { 102 typename range_const_iterator<Symbols>::type si = boost::begin(syms); 103 while (si != boost::end(syms)) 104 add(*si++); 105 } 106 107 template <typename Symbols, typename Data> symbolsboost::spirit::qi::symbols108 symbols(Symbols const& syms, Data const& data 109 , std::string const& name = "symbols") 110 : base_type(terminal::make(reference_(*this))) 111 , add(*this) 112 , remove(*this) 113 , lookup(new Lookup()) 114 , name_(name) 115 { 116 typename range_const_iterator<Symbols>::type si = boost::begin(syms); 117 typename range_const_iterator<Data>::type di = boost::begin(data); 118 while (si != boost::end(syms)) 119 add(*si++, *di++); 120 } 121 122 symbols& operator =boost::spirit::qi::symbols123 operator=(symbols const& rhs) 124 { 125 name_ = rhs.name_; 126 *lookup = *rhs.lookup; 127 return *this; 128 } 129 130 template <typename Filter_> 131 symbols& operator =boost::spirit::qi::symbols132 operator=(symbols<Char, T, Lookup, Filter_> const& rhs) 133 { 134 name_ = rhs.name_; 135 *lookup = *rhs.lookup; 136 return *this; 137 } 138 clearboost::spirit::qi::symbols139 void clear() 140 { 141 lookup->clear(); 142 } 143 144 struct adder; 145 struct remover; 146 147 template <typename Str> 148 adder const& operator =boost::spirit::qi::symbols149 operator=(Str const& str) 150 { 151 lookup->clear(); 152 return add(str); 153 } 154 155 template <typename Str> 156 friend adder const& operator +=(symbols & sym,Str const & str)157 operator+=(symbols& sym, Str const& str) 158 { 159 return sym.add(str); 160 } 161 162 template <typename Str> 163 friend remover const& operator -=(symbols & sym,Str const & str)164 operator-=(symbols& sym, Str const& str) 165 { 166 return sym.remove(str); 167 } 168 169 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 170 // non-const version needed to suppress proto's += kicking in 171 template <typename Str> 172 friend adder const& operator +=(symbols & sym,Str & str)173 operator+=(symbols& sym, Str& str) 174 { 175 return sym.add(str); 176 } 177 178 // non-const version needed to suppress proto's -= kicking in 179 template <typename Str> 180 friend remover const& operator -=(symbols & sym,Str & str)181 operator-=(symbols& sym, Str& str) 182 { 183 return sym.remove(str); 184 } 185 #else 186 // for rvalue references 187 template <typename Str> 188 friend adder const& operator +=(symbols & sym,Str && str)189 operator+=(symbols& sym, Str&& str) 190 { 191 return sym.add(str); 192 } 193 194 // for rvalue references 195 template <typename Str> 196 friend remover const& operator -=(symbols & sym,Str && str)197 operator-=(symbols& sym, Str&& str) 198 { 199 return sym.remove(str); 200 } 201 #endif 202 template <typename F> for_eachboost::spirit::qi::symbols203 void for_each(F f) const 204 { 205 lookup->for_each(f); 206 } 207 208 template <typename Str> atboost::spirit::qi::symbols209 value_type& at(Str const& str) 210 { 211 return *lookup->add(traits::get_begin<Char>(str) 212 , traits::get_end<Char>(str), T()); 213 } 214 215 template <typename Iterator> prefix_findboost::spirit::qi::symbols216 value_type* prefix_find(Iterator& first, Iterator const& last) 217 { 218 return lookup->find(first, last, Filter()); 219 } 220 221 template <typename Iterator> prefix_findboost::spirit::qi::symbols222 value_type const* prefix_find(Iterator& first, Iterator const& last) const 223 { 224 return lookup->find(first, last, Filter()); 225 } 226 227 template <typename Str> findboost::spirit::qi::symbols228 value_type* find(Str const& str) 229 { 230 return find_impl(traits::get_begin<Char>(str) 231 , traits::get_end<Char>(str)); 232 } 233 234 template <typename Str> findboost::spirit::qi::symbols235 value_type const* find(Str const& str) const 236 { 237 return find_impl(traits::get_begin<Char>(str) 238 , traits::get_end<Char>(str)); 239 } 240 241 private: 242 template <typename Iterator> find_implboost::spirit::qi::symbols243 value_type* find_impl(Iterator begin, Iterator end) 244 { 245 value_type* r = lookup->find(begin, end, Filter()); 246 return begin == end ? r : 0; 247 } 248 249 template <typename Iterator> find_implboost::spirit::qi::symbols250 value_type const* find_impl(Iterator begin, Iterator end) const 251 { 252 value_type const* r = lookup->find(begin, end, Filter()); 253 return begin == end ? r : 0; 254 } 255 256 public: 257 template <typename Iterator, typename Context 258 , typename Skipper, typename Attribute> parseboost::spirit::qi::symbols259 bool parse(Iterator& first, Iterator const& last 260 , Context& /*context*/, Skipper const& skipper, Attribute& attr_) const 261 { 262 qi::skip_over(first, last, skipper); 263 264 if (value_type* val_ptr 265 = lookup->find(first, last, Filter())) 266 { 267 spirit::traits::assign_to(*val_ptr, attr_); 268 return true; 269 } 270 return false; 271 } 272 273 template <typename Context> whatboost::spirit::qi::symbols274 info what(Context& /*context*/) const 275 { 276 return info(name_); 277 } 278 nameboost::spirit::qi::symbols279 void name(std::string const &str) 280 { 281 name_ = str; 282 } nameboost::spirit::qi::symbols283 std::string const &name() const 284 { 285 return name_; 286 } 287 288 struct adder 289 { 290 template <typename, typename = unused_type, typename = unused_type> 291 struct result { typedef adder const& type; }; 292 adderboost::spirit::qi::symbols::adder293 adder(symbols& sym_) 294 : sym(sym_) 295 { 296 } 297 298 template <typename Iterator> 299 adder const& operator ()boost::spirit::qi::symbols::adder300 operator()(Iterator const& first, Iterator const& last, T const& val) const 301 { 302 sym.lookup->add(first, last, val); 303 return *this; 304 } 305 306 template <typename Str> 307 adder const& operator ()boost::spirit::qi::symbols::adder308 operator()(Str const& s, T const& val = T()) const 309 { 310 sym.lookup->add(traits::get_begin<Char>(s) 311 , traits::get_end<Char>(s), val); 312 return *this; 313 } 314 315 template <typename Str> 316 adder const& operator ,boost::spirit::qi::symbols::adder317 operator,(Str const& s) const 318 { 319 sym.lookup->add(traits::get_begin<Char>(s) 320 , traits::get_end<Char>(s), T()); 321 return *this; 322 } 323 324 symbols& sym; 325 326 // silence MSVC warning C4512: assignment operator could not be generated 327 BOOST_DELETED_FUNCTION(adder& operator= (adder const&)) 328 }; 329 330 struct remover 331 { 332 template <typename, typename = unused_type, typename = unused_type> 333 struct result { typedef remover const& type; }; 334 removerboost::spirit::qi::symbols::remover335 remover(symbols& sym_) 336 : sym(sym_) 337 { 338 } 339 340 template <typename Iterator> 341 remover const& operator ()boost::spirit::qi::symbols::remover342 operator()(Iterator const& first, Iterator const& last) const 343 { 344 sym.lookup->remove(first, last); 345 return *this; 346 } 347 348 template <typename Str> 349 remover const& operator ()boost::spirit::qi::symbols::remover350 operator()(Str const& s) const 351 { 352 sym.lookup->remove(traits::get_begin<Char>(s) 353 , traits::get_end<Char>(s)); 354 return *this; 355 } 356 357 template <typename Str> 358 remover const& operator ,boost::spirit::qi::symbols::remover359 operator,(Str const& s) const 360 { 361 sym.lookup->remove(traits::get_begin<Char>(s) 362 , traits::get_end<Char>(s)); 363 return *this; 364 } 365 366 symbols& sym; 367 368 // silence MSVC warning C4512: assignment operator could not be generated 369 BOOST_DELETED_FUNCTION(remover& operator= (remover const&)) 370 }; 371 372 adder add; 373 remover remove; 374 shared_ptr<Lookup> lookup; 375 std::string name_; 376 }; 377 378 /////////////////////////////////////////////////////////////////////////// 379 // Parser generators: make_xxx function (objects) 380 /////////////////////////////////////////////////////////////////////////// 381 template <typename Char, typename T, typename Lookup 382 , typename Filter, typename Modifiers> 383 struct make_primitive<reference<symbols<Char, T, Lookup, Filter> >, Modifiers> 384 { 385 template <typename CharEncoding> 386 struct no_case_filter 387 { operator ()boost::spirit::qi::make_primitive::no_case_filter388 Char operator()(Char ch) const 389 { 390 return static_cast<Char>(CharEncoding::tolower(ch)); 391 } 392 }; 393 394 typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case; 395 typedef reference<symbols<Char, T, Lookup, Filter> > reference_; 396 typedef no_case_filter< 397 typename spirit::detail::get_encoding_with_case< 398 Modifiers 399 , char_encoding::standard 400 , no_case::value>::type> 401 nc_filter; 402 403 typedef typename mpl::if_< 404 no_case 405 , symbols<Char, T, Lookup, nc_filter> 406 , reference_>::type 407 result_type; 408 operator ()boost::spirit::qi::make_primitive409 result_type operator()(reference_ ref, unused_type) const 410 { 411 return result_type(ref.ref.get()); 412 } 413 }; 414 }}} 415 416 namespace boost { namespace spirit { namespace traits 417 { 418 /////////////////////////////////////////////////////////////////////////// 419 template <typename Char, typename T, typename Lookup, typename Filter 420 , typename Attr, typename Context, typename Iterator> 421 struct handles_container<qi::symbols<Char, T, Lookup, Filter>, Attr, Context, Iterator> 422 : traits::is_container<Attr> {}; 423 }}} 424 425 #if defined(BOOST_MSVC) 426 # pragma warning(pop) 427 #endif 428 429 #endif 430