| 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 | |
| 52 | 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 | |
| 60 | 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> |
| 69 | 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> |
| 77 | 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 | |
| 87 | 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 | |
| 95 | 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& |
| 104 | operator=(symbols_parser const& rhs) |
| 105 | { |
| 106 | name_ = rhs.name_; |
| 107 | lookup = rhs.lookup; |
| 108 | return *this; |
| 109 | } |
| 110 | |
| 111 | void clear() |
| 112 | { |
| 113 | lookup->clear(); |
| 114 | } |
| 115 | |
| 116 | struct adder; |
| 117 | struct remover; |
| 118 | |
| 119 | template <typename Str> |
| 120 | adder const& |
| 121 | operator=(Str const& str) |
| 122 | { |
| 123 | lookup->clear(); |
| 124 | return add(str); |
| 125 | } |
| 126 | |
| 127 | template <typename Str> |
| 128 | friend adder const& |
| 129 | operator+=(symbols_parser& sym, Str const& str) |
| 130 | { |
| 131 | return sym.add(str); |
| 132 | } |
| 133 | |
| 134 | template <typename Str> |
| 135 | friend remover const& |
| 136 | operator-=(symbols_parser& sym, Str const& str) |
| 137 | { |
| 138 | return sym.remove(str); |
| 139 | } |
| 140 | |
| 141 | template <typename F> |
| 142 | void for_each(F f) const |
| 143 | { |
| 144 | lookup->for_each(f); |
| 145 | } |
| 146 | |
| 147 | template <typename Str> |
| 148 | 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> |
| 155 | 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> |
| 161 | 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> |
| 167 | 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> |
| 174 | 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> |
| 183 | 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> |
| 190 | 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> |
| 199 | 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 | |
| 213 | void name(std::string const &str) |
| 214 | { |
| 215 | name_ = str; |
| 216 | } |
| 217 | std::string const &name() const |
| 218 | { |
| 219 | return name_; |
| 220 | } |
| 221 | |
| 222 | struct adder |
| 223 | { |
| 224 | template <typename Iterator> |
| 225 | adder const& |
| 226 | 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& |
| 234 | 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& |
| 243 | 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& |
| 257 | 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& |
| 265 | 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& |
| 274 | 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; |
| 294 | 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 | |