| /*============================================================================= |
| Copyright (c) 2001-2014 Joel de Guzman |
| Copyright (c) 2013 Carl Barron |
| |
| Distributed under the Boost Software License, Version 1.0. (See accompanying |
| file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| ==============================================================================*/ |
| #if !defined(BOOST_SPIRIT_X3_SYMBOLS_MARCH_11_2007_1055AM) |
| #define BOOST_SPIRIT_X3_SYMBOLS_MARCH_11_2007_1055AM |
| |
| #include <boost/spirit/home/x3/core/skip_over.hpp> |
| #include <boost/spirit/home/x3/core/parser.hpp> |
| #include <boost/spirit/home/x3/string/tst.hpp> |
| #include <boost/spirit/home/x3/support/unused.hpp> |
| #include <boost/spirit/home/x3/support/traits/string_traits.hpp> |
| #include <boost/spirit/home/x3/support/traits/move_to.hpp> |
| #include <boost/spirit/home/x3/support/no_case.hpp> |
| |
| #include <boost/spirit/home/support/char_encoding/ascii.hpp> |
| #include <boost/spirit/home/support/char_encoding/iso8859_1.hpp> |
| #include <boost/spirit/home/support/char_encoding/standard.hpp> |
| #include <boost/spirit/home/support/char_encoding/standard_wide.hpp> |
| |
| #include <initializer_list> |
| #include <iterator> // std::begin |
| #include <memory> // std::shared_ptr |
| #include <type_traits> |
| |
| #if defined(BOOST_MSVC) |
| # pragma warning(push) |
| # pragma warning(disable: 4355) // 'this' : used in base member initializer list warning |
| #endif |
| |
| namespace boost { namespace spirit { namespace x3 |
| { |
| template < |
| typename Encoding |
| , typename T = unused_type |
| , typename Lookup = tst<typename Encoding::char_type, T> > |
| struct symbols_parser : parser<symbols_parser<Encoding, T, Lookup>> |
| { |
| typedef typename Encoding::char_type char_type; // the character type |
| typedef Encoding encoding; |
| typedef T value_type; // the value associated with each entry |
| typedef value_type attribute_type; |
| |
| static bool const has_attribute = |
| !std::is_same<unused_type, attribute_type>::value; |
| static bool const handles_container = |
| traits::is_container<attribute_type>::value; |
| |
| symbols_parser(std::string const& name = "symbols") |
| : add{*this} |
| , remove{*this} |
| , lookup(std::make_shared<Lookup>()) |
| , name_(name) |
| { |
| } |
| |
| symbols_parser(symbols_parser const& syms) |
| : add{*this} |
| , remove{*this} |
| , lookup(syms.lookup) |
| , name_(syms.name_) |
| { |
| } |
| |
| template <typename Symbols> |
| symbols_parser(Symbols const& syms, std::string const& name = "symbols") |
| : symbols_parser(name) |
| { |
| for (auto& sym : syms) |
| add(sym); |
| } |
| |
| template <typename Symbols, typename Data> |
| symbols_parser(Symbols const& syms, Data const& data |
| , std::string const& name = "symbols") |
| : symbols_parser(name) |
| { |
| using std::begin; |
| auto di = begin(data); |
| for (auto& sym : syms) |
| add(sym, *di++); |
| } |
| |
| symbols_parser(std::initializer_list<std::pair<char_type const*, T>> syms |
| , std::string const & name="symbols") |
| : symbols_parser(name) |
| { |
| for (auto& sym : syms) |
| add(sym.first, sym.second); |
| } |
| |
| symbols_parser(std::initializer_list<char_type const*> syms |
| , std::string const &name="symbols") |
| : symbols_parser(name) |
| { |
| for (auto str : syms) |
| add(str); |
| } |
| |
| symbols_parser& |
| operator=(symbols_parser const& rhs) |
| { |
| name_ = rhs.name_; |
| lookup = rhs.lookup; |
| return *this; |
| } |
| |
| void clear() |
| { |
| lookup->clear(); |
| } |
| |
| struct adder; |
| struct remover; |
| |
| template <typename Str> |
| adder const& |
| operator=(Str const& str) |
| { |
| lookup->clear(); |
| return add(str); |
| } |
| |
| template <typename Str> |
| friend adder const& |
| operator+=(symbols_parser& sym, Str const& str) |
| { |
| return sym.add(str); |
| } |
| |
| template <typename Str> |
| friend remover const& |
| operator-=(symbols_parser& sym, Str const& str) |
| { |
| return sym.remove(str); |
| } |
| |
| template <typename F> |
| void for_each(F f) const |
| { |
| lookup->for_each(f); |
| } |
| |
| template <typename Str> |
| value_type& at(Str const& str) |
| { |
| return *lookup->add(traits::get_string_begin<char_type>(str) |
| , traits::get_string_end<char_type>(str), T()); |
| } |
| |
| template <typename Iterator> |
| value_type* prefix_find(Iterator& first, Iterator const& last) |
| { |
| return lookup->find(first, last, case_compare<Encoding>()); |
| } |
| |
| template <typename Iterator> |
| value_type const* prefix_find(Iterator& first, Iterator const& last) const |
| { |
| return lookup->find(first, last, case_compare<Encoding>()); |
| } |
| |
| template <typename Str> |
| value_type* find(Str const& str) |
| { |
| return find_impl(traits::get_string_begin<char_type>(str) |
| , traits::get_string_end<char_type>(str)); |
| } |
| |
| template <typename Str> |
| value_type const* find(Str const& str) const |
| { |
| return find_impl(traits::get_string_begin<char_type>(str) |
| , traits::get_string_end<char_type>(str)); |
| } |
| |
| private: |
| |
| template <typename Iterator> |
| value_type* find_impl(Iterator begin, Iterator end) |
| { |
| value_type* r = lookup->find(begin, end, case_compare<Encoding>()); |
| return begin == end ? r : 0; |
| } |
| |
| template <typename Iterator> |
| value_type const* find_impl(Iterator begin, Iterator end) const |
| { |
| value_type const* r = lookup->find(begin, end, case_compare<Encoding>()); |
| return begin == end ? r : 0; |
| } |
| |
| public: |
| |
| template <typename Iterator, typename Context, typename Attribute> |
| bool parse(Iterator& first, Iterator const& last |
| , Context const& context, unused_type, Attribute& attr) const |
| { |
| x3::skip_over(first, last, context); |
| |
| if (value_type const* val_ptr |
| = lookup->find(first, last, get_case_compare<Encoding>(context))) |
| { |
| x3::traits::move_to(*val_ptr, attr); |
| return true; |
| } |
| return false; |
| } |
| |
| void name(std::string const &str) |
| { |
| name_ = str; |
| } |
| std::string const &name() const |
| { |
| return name_; |
| } |
| |
| struct adder |
| { |
| template <typename Iterator> |
| adder const& |
| operator()(Iterator first, Iterator last, T const& val) const |
| { |
| sym.lookup->add(first, last, val); |
| return *this; |
| } |
| |
| template <typename Str> |
| adder const& |
| operator()(Str const& s, T const& val = T()) const |
| { |
| sym.lookup->add(traits::get_string_begin<char_type>(s) |
| , traits::get_string_end<char_type>(s), val); |
| return *this; |
| } |
| |
| template <typename Str> |
| adder const& |
| operator,(Str const& s) const |
| { |
| sym.lookup->add(traits::get_string_begin<char_type>(s) |
| , traits::get_string_end<char_type>(s), T()); |
| return *this; |
| } |
| |
| symbols_parser& sym; |
| }; |
| |
| struct remover |
| { |
| template <typename Iterator> |
| remover const& |
| operator()(Iterator const& first, Iterator const& last) const |
| { |
| sym.lookup->remove(first, last); |
| return *this; |
| } |
| |
| template <typename Str> |
| remover const& |
| operator()(Str const& s) const |
| { |
| sym.lookup->remove(traits::get_string_begin<char_type>(s) |
| , traits::get_string_end<char_type>(s)); |
| return *this; |
| } |
| |
| template <typename Str> |
| remover const& |
| operator,(Str const& s) const |
| { |
| sym.lookup->remove(traits::get_string_begin<char_type>(s) |
| , traits::get_string_end<char_type>(s)); |
| return *this; |
| } |
| |
| symbols_parser& sym; |
| }; |
| |
| adder add; |
| remover remove; |
| std::shared_ptr<Lookup> lookup; |
| std::string name_; |
| }; |
| |
| template <typename Encoding, typename T, typename Lookup> |
| struct get_info<symbols_parser<Encoding, T, Lookup>> |
| { |
| typedef std::string result_type; |
| result_type operator()(symbols_parser< Encoding, T |
| , Lookup |
| > const& symbols) const |
| { |
| return symbols.name(); |
| } |
| }; |
| |
| namespace standard |
| { |
| template <typename T = unused_type> |
| using symbols = symbols_parser<char_encoding::standard, T>; |
| } |
| |
| using standard::symbols; |
| |
| #ifndef BOOST_SPIRIT_NO_STANDARD_WIDE |
| namespace standard_wide |
| { |
| template <typename T = unused_type> |
| using symbols = symbols_parser<char_encoding::standard_wide, T>; |
| } |
| #endif |
| |
| namespace ascii |
| { |
| template <typename T = unused_type> |
| using symbols = symbols_parser<char_encoding::ascii, T>; |
| } |
| |
| namespace iso8859_1 |
| { |
| template <typename T = unused_type> |
| using symbols = symbols_parser<char_encoding::iso8859_1, T>; |
| } |
| |
| }}} |
| |
| #if defined(BOOST_MSVC) |
| # pragma warning(pop) |
| #endif |
| |
| #endif |