1 /*============================================================================= 2 Copyright (c) 2001-2014 Joel de Guzman 3 Copyright (c) 2013 Carl Barron 4 5 Distributed under the Boost Software License, Version 1.0. (See accompanying 6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 ==============================================================================*/ 8 #if !defined(BOOST_SPIRIT_X3_SYMBOLS_MARCH_11_2007_1055AM) 9 #define BOOST_SPIRIT_X3_SYMBOLS_MARCH_11_2007_1055AM 10 11 #include <boost/spirit/home/x3/core/skip_over.hpp> 12 #include <boost/spirit/home/x3/core/parser.hpp> 13 #include <boost/spirit/home/x3/string/tst.hpp> 14 #include <boost/spirit/home/x3/support/unused.hpp> 15 #include <boost/spirit/home/x3/support/traits/string_traits.hpp> 16 #include <boost/spirit/home/x3/support/traits/move_to.hpp> 17 #include <boost/spirit/home/x3/support/no_case.hpp> 18 19 #include <boost/spirit/home/support/char_encoding/ascii.hpp> 20 #include <boost/spirit/home/support/char_encoding/iso8859_1.hpp> 21 #include <boost/spirit/home/support/char_encoding/standard.hpp> 22 #include <boost/spirit/home/support/char_encoding/standard_wide.hpp> 23 24 #include <initializer_list> 25 #include <iterator> // std::begin 26 #include <memory> // std::shared_ptr 27 #include <type_traits> 28 29 #if defined(BOOST_MSVC) 30 # pragma warning(push) 31 # pragma warning(disable: 4355) // 'this' : used in base member initializer list warning 32 #endif 33 34 namespace boost { namespace spirit { namespace x3 35 { 36 template < 37 typename Encoding 38 , typename T = unused_type 39 , typename Lookup = tst<typename Encoding::char_type, T> > 40 struct symbols_parser : parser<symbols_parser<Encoding, T, Lookup>> 41 { 42 typedef typename Encoding::char_type char_type; // the character type 43 typedef Encoding encoding; 44 typedef T value_type; // the value associated with each entry 45 typedef value_type attribute_type; 46 47 static bool const has_attribute = 48 !std::is_same<unused_type, attribute_type>::value; 49 static bool const handles_container = 50 traits::is_container<attribute_type>::value; 51 symbols_parserboost::spirit::x3::symbols_parser52 symbols_parser(std::string const& name = "symbols") 53 : add{*this} 54 , remove{*this} 55 , lookup(std::make_shared<Lookup>()) 56 , name_(name) 57 { 58 } 59 symbols_parserboost::spirit::x3::symbols_parser60 symbols_parser(symbols_parser const& syms) 61 : add{*this} 62 , remove{*this} 63 , lookup(syms.lookup) 64 , name_(syms.name_) 65 { 66 } 67 68 template <typename Symbols> symbols_parserboost::spirit::x3::symbols_parser69 symbols_parser(Symbols const& syms, std::string const& name = "symbols") 70 : symbols_parser(name) 71 { 72 for (auto& sym : syms) 73 add(sym); 74 } 75 76 template <typename Symbols, typename Data> symbols_parserboost::spirit::x3::symbols_parser77 symbols_parser(Symbols const& syms, Data const& data 78 , std::string const& name = "symbols") 79 : symbols_parser(name) 80 { 81 using std::begin; 82 auto di = begin(data); 83 for (auto& sym : syms) 84 add(sym, *di++); 85 } 86 symbols_parserboost::spirit::x3::symbols_parser87 symbols_parser(std::initializer_list<std::pair<char_type const*, T>> syms 88 , std::string const & name="symbols") 89 : symbols_parser(name) 90 { 91 for (auto& sym : syms) 92 add(sym.first, sym.second); 93 } 94 symbols_parserboost::spirit::x3::symbols_parser95 symbols_parser(std::initializer_list<char_type const*> syms 96 , std::string const &name="symbols") 97 : symbols_parser(name) 98 { 99 for (auto str : syms) 100 add(str); 101 } 102 103 symbols_parser& operator =boost::spirit::x3::symbols_parser104 operator=(symbols_parser const& rhs) 105 { 106 name_ = rhs.name_; 107 lookup = rhs.lookup; 108 return *this; 109 } 110 clearboost::spirit::x3::symbols_parser111 void clear() 112 { 113 lookup->clear(); 114 } 115 116 struct adder; 117 struct remover; 118 119 template <typename Str> 120 adder const& operator =boost::spirit::x3::symbols_parser121 operator=(Str const& str) 122 { 123 lookup->clear(); 124 return add(str); 125 } 126 127 template <typename Str> 128 friend adder const& operator +=(symbols_parser & sym,Str const & str)129 operator+=(symbols_parser& sym, Str const& str) 130 { 131 return sym.add(str); 132 } 133 134 template <typename Str> 135 friend remover const& operator -=(symbols_parser & sym,Str const & str)136 operator-=(symbols_parser& sym, Str const& str) 137 { 138 return sym.remove(str); 139 } 140 141 template <typename F> for_eachboost::spirit::x3::symbols_parser142 void for_each(F f) const 143 { 144 lookup->for_each(f); 145 } 146 147 template <typename Str> atboost::spirit::x3::symbols_parser148 value_type& at(Str const& str) 149 { 150 return *lookup->add(traits::get_string_begin<char_type>(str) 151 , traits::get_string_end<char_type>(str), T()); 152 } 153 154 template <typename Iterator> prefix_findboost::spirit::x3::symbols_parser155 value_type* prefix_find(Iterator& first, Iterator const& last) 156 { 157 return lookup->find(first, last, case_compare<Encoding>()); 158 } 159 160 template <typename Iterator> prefix_findboost::spirit::x3::symbols_parser161 value_type const* prefix_find(Iterator& first, Iterator const& last) const 162 { 163 return lookup->find(first, last, case_compare<Encoding>()); 164 } 165 166 template <typename Str> findboost::spirit::x3::symbols_parser167 value_type* find(Str const& str) 168 { 169 return find_impl(traits::get_string_begin<char_type>(str) 170 , traits::get_string_end<char_type>(str)); 171 } 172 173 template <typename Str> findboost::spirit::x3::symbols_parser174 value_type const* find(Str const& str) const 175 { 176 return find_impl(traits::get_string_begin<char_type>(str) 177 , traits::get_string_end<char_type>(str)); 178 } 179 180 private: 181 182 template <typename Iterator> find_implboost::spirit::x3::symbols_parser183 value_type* find_impl(Iterator begin, Iterator end) 184 { 185 value_type* r = lookup->find(begin, end, case_compare<Encoding>()); 186 return begin == end ? r : 0; 187 } 188 189 template <typename Iterator> find_implboost::spirit::x3::symbols_parser190 value_type const* find_impl(Iterator begin, Iterator end) const 191 { 192 value_type const* r = lookup->find(begin, end, case_compare<Encoding>()); 193 return begin == end ? r : 0; 194 } 195 196 public: 197 198 template <typename Iterator, typename Context, typename Attribute> parseboost::spirit::x3::symbols_parser199 bool parse(Iterator& first, Iterator const& last 200 , Context const& context, unused_type, Attribute& attr) const 201 { 202 x3::skip_over(first, last, context); 203 204 if (value_type const* val_ptr 205 = lookup->find(first, last, get_case_compare<Encoding>(context))) 206 { 207 x3::traits::move_to(*val_ptr, attr); 208 return true; 209 } 210 return false; 211 } 212 nameboost::spirit::x3::symbols_parser213 void name(std::string const &str) 214 { 215 name_ = str; 216 } nameboost::spirit::x3::symbols_parser217 std::string const &name() const 218 { 219 return name_; 220 } 221 222 struct adder 223 { 224 template <typename Iterator> 225 adder const& operator ()boost::spirit::x3::symbols_parser::adder226 operator()(Iterator first, Iterator last, T const& val) const 227 { 228 sym.lookup->add(first, last, val); 229 return *this; 230 } 231 232 template <typename Str> 233 adder const& operator ()boost::spirit::x3::symbols_parser::adder234 operator()(Str const& s, T const& val = T()) const 235 { 236 sym.lookup->add(traits::get_string_begin<char_type>(s) 237 , traits::get_string_end<char_type>(s), val); 238 return *this; 239 } 240 241 template <typename Str> 242 adder const& operator ,boost::spirit::x3::symbols_parser::adder243 operator,(Str const& s) const 244 { 245 sym.lookup->add(traits::get_string_begin<char_type>(s) 246 , traits::get_string_end<char_type>(s), T()); 247 return *this; 248 } 249 250 symbols_parser& sym; 251 }; 252 253 struct remover 254 { 255 template <typename Iterator> 256 remover const& operator ()boost::spirit::x3::symbols_parser::remover257 operator()(Iterator const& first, Iterator const& last) const 258 { 259 sym.lookup->remove(first, last); 260 return *this; 261 } 262 263 template <typename Str> 264 remover const& operator ()boost::spirit::x3::symbols_parser::remover265 operator()(Str const& s) const 266 { 267 sym.lookup->remove(traits::get_string_begin<char_type>(s) 268 , traits::get_string_end<char_type>(s)); 269 return *this; 270 } 271 272 template <typename Str> 273 remover const& operator ,boost::spirit::x3::symbols_parser::remover274 operator,(Str const& s) const 275 { 276 sym.lookup->remove(traits::get_string_begin<char_type>(s) 277 , traits::get_string_end<char_type>(s)); 278 return *this; 279 } 280 281 symbols_parser& sym; 282 }; 283 284 adder add; 285 remover remove; 286 std::shared_ptr<Lookup> lookup; 287 std::string name_; 288 }; 289 290 template <typename Encoding, typename T, typename Lookup> 291 struct get_info<symbols_parser<Encoding, T, Lookup>> 292 { 293 typedef std::string result_type; operator ()boost::spirit::x3::get_info294 result_type operator()(symbols_parser< Encoding, T 295 , Lookup 296 > const& symbols) const 297 { 298 return symbols.name(); 299 } 300 }; 301 302 namespace standard 303 { 304 template <typename T = unused_type> 305 using symbols = symbols_parser<char_encoding::standard, T>; 306 } 307 308 using standard::symbols; 309 310 #ifndef BOOST_SPIRIT_NO_STANDARD_WIDE 311 namespace standard_wide 312 { 313 template <typename T = unused_type> 314 using symbols = symbols_parser<char_encoding::standard_wide, T>; 315 } 316 #endif 317 318 namespace ascii 319 { 320 template <typename T = unused_type> 321 using symbols = symbols_parser<char_encoding::ascii, T>; 322 } 323 324 namespace iso8859_1 325 { 326 template <typename T = unused_type> 327 using symbols = symbols_parser<char_encoding::iso8859_1, T>; 328 } 329 330 }}} 331 332 #if defined(BOOST_MSVC) 333 # pragma warning(pop) 334 #endif 335 336 #endif 337