| /*============================================================================= |
| Copyright (c) 2001-2007 Joel de Guzman |
| |
| 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_SYMBOL_MARCH_11_2007_1055AM) |
| #define BOOST_SPIRIT_SYMBOL_MARCH_11_2007_1055AM |
| |
| #include <boost/spirit/home/qi/domain.hpp> |
| #include <boost/spirit/home/qi/skip.hpp> |
| #include <boost/spirit/home/qi/string/tst.hpp> |
| #include <boost/spirit/home/support/modifier.hpp> |
| #include <boost/spirit/home/qi/detail/assign_to.hpp> |
| #include <boost/fusion/include/at.hpp> |
| #include <boost/proto/core.hpp> |
| #include <boost/shared_ptr.hpp> |
| #include <boost/range.hpp> |
| #include <boost/type_traits/add_reference.hpp> |
| |
| #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 qi |
| { |
| template <typename Filter = tst_pass_through> |
| struct symbols_director |
| { |
| template <typename Component, typename Context, typename Iterator> |
| struct attribute |
| { |
| typedef typename |
| result_of::subject<Component>::type::ptr_type::element_type::value_type |
| type; |
| }; |
| |
| template < |
| typename Component |
| , typename Iterator, typename Context |
| , typename Skipper, typename Attribute> |
| static bool parse( |
| Component const& component |
| , Iterator& first, Iterator const& last |
| , Context& /*context*/, Skipper const& skipper |
| , Attribute& attr) |
| { |
| typedef typename |
| result_of::subject<Component>::type::ptr_type::element_type::value_type |
| value_type; |
| |
| qi::skip(first, last, skipper); |
| |
| if (value_type* val_ptr |
| = fusion::at_c<0>(component.elements) |
| .lookup->find(first, last, Filter())) |
| { |
| detail::assign_to(*val_ptr, attr); |
| return true; |
| } |
| return false; |
| } |
| |
| template <typename Component, typename Context> |
| static std::string what(Component const& component, Context const& ctx) |
| { |
| // perhaps we should show some of the contents? |
| return "symbols"; |
| } |
| }; |
| |
| template <typename Lookup> |
| struct symbols_lookup |
| { |
| typedef shared_ptr<Lookup> ptr_type; |
| ptr_type lookup; |
| }; |
| |
| template <typename Char, typename T, typename Lookup = tst<Char, T> > |
| struct symbols |
| : proto::extends< |
| typename proto::terminal<symbols_lookup<Lookup> >::type |
| , symbols<Char, T> |
| > |
| { |
| typedef Char char_type; // the character type |
| typedef T value_type; // the value associated with each entry |
| typedef shared_ptr<Lookup> ptr_type; |
| |
| symbols() |
| : add(*this) |
| , remove(*this) |
| { |
| proto::child(*this).lookup = ptr_type(new Lookup()); |
| } |
| |
| template <typename Symbols> |
| symbols(Symbols const& syms) |
| : add(*this) |
| , remove(*this) |
| { |
| proto::child(*this).lookup = ptr_type(new Lookup()); |
| typename range_const_iterator<Symbols>::type si = boost::begin(syms); |
| while (si != boost::end(syms)) |
| add(*si++); |
| } |
| |
| template <typename Symbols, typename Data> |
| symbols(Symbols const& syms, Data const& data) |
| : add(*this) |
| , remove(*this) |
| { |
| proto::child(*this).lookup = ptr_type(new Lookup()); |
| typename range_const_iterator<Symbols>::type si = boost::begin(syms); |
| typename range_const_iterator<Data>::type di = boost::begin(data); |
| while (si != boost::end(syms)) |
| add(*si++, *di++); |
| } |
| |
| symbols& |
| operator=(symbols const& rhs) |
| { |
| proto::child(*this) = proto::child(rhs); |
| return *this; |
| } |
| |
| void clear() |
| { |
| lookup()->clear(); |
| } |
| |
| struct adder; |
| struct remover; |
| |
| adder const& |
| operator=(Char const* str) |
| { |
| lookup()->clear(); |
| return add(str); |
| } |
| |
| adder const& |
| operator+=(Char const* str) |
| { |
| return add(str); |
| } |
| |
| remover const& |
| operator-=(Char const* str) |
| { |
| return remove(str); |
| } |
| |
| ptr_type lookup() const |
| { |
| return proto::child(*this).lookup; |
| } |
| |
| template <typename F> |
| void for_each(F f) const |
| { |
| lookup()->for_each(f); |
| } |
| |
| struct adder |
| { |
| template <typename, typename = unused_type, typename = unused_type> |
| struct result { typedef adder const& type; }; |
| |
| adder(symbols& sym) |
| : sym(sym) |
| { |
| } |
| |
| template <typename Iterator> |
| adder const& |
| operator()(Iterator const& first, Iterator const& last, T const& val = T()) const |
| { |
| sym.lookup()->add(first, last, val); |
| return *this; |
| } |
| |
| adder const& |
| operator()(Char const* s, T const& val = T()) const |
| { |
| Char const* last = s; |
| while (*last) |
| last++; |
| sym.lookup()->add(s, last, val); |
| return *this; |
| } |
| |
| adder const& |
| operator,(Char const* s) const |
| { |
| Char const* last = s; |
| while (*last) |
| last++; |
| sym.lookup()->add(s, last, T()); |
| return *this; |
| } |
| |
| symbols& sym; |
| }; |
| |
| struct remover |
| { |
| template <typename, typename = unused_type, typename = unused_type> |
| struct result { typedef adder const& type; }; |
| |
| remover(symbols& sym) |
| : sym(sym) |
| { |
| } |
| |
| template <typename Iterator> |
| remover const& |
| operator()(Iterator const& first, Iterator const& last) const |
| { |
| sym.lookup()->remove(first, last); |
| return *this; |
| } |
| |
| remover const& |
| operator()(Char const* s) const |
| { |
| Char const* last = s; |
| while (*last) |
| last++; |
| sym.lookup()->remove(s, last); |
| return *this; |
| } |
| |
| remover const& |
| operator,(Char const* s) const |
| { |
| Char const* last = s; |
| while (*last) |
| last++; |
| sym.lookup()->remove(s, last); |
| return *this; |
| } |
| |
| symbols& sym; |
| }; |
| |
| adder add; |
| remover remove; |
| }; |
| }}} |
| |
| |
| namespace boost { namespace spirit { namespace traits |
| { |
| namespace detail |
| { |
| template <typename CharSet> |
| struct no_case_filter |
| { |
| template <typename Char> |
| Char operator()(Char ch) const |
| { |
| return CharSet::tolower(ch); |
| } |
| }; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // generator for no-case symbols |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Domain, typename Elements, typename Modifier> |
| struct make_modified_component<Domain, qi::symbols_director<>, Elements, Modifier |
| , typename enable_if< |
| is_member_of_modifier<Modifier, spirit::char_class::no_case_base_tag> |
| >::type |
| > |
| { |
| typedef detail::no_case_filter<typename Modifier::char_set> filter; |
| typedef component<qi::domain, qi::symbols_director<filter>, Elements> type; |
| |
| static type |
| call(Elements const& elements) |
| { |
| // we return the same lookup but this time we use a director |
| // with a filter that converts to lower-case. |
| return elements; |
| } |
| }; |
| }}} |
| |
| |
| #if defined(BOOST_MSVC) |
| # pragma warning(pop) |
| #endif |
| |
| #endif |