123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766 |
- // Copyright (c) 2001-2011 Hartmut Kaiser
- //
- // 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_KARMA_SYMBOLS_NOV_23_2009_1251PM)
- #define BOOST_SPIRIT_KARMA_SYMBOLS_NOV_23_2009_1251PM
- #include <boost/spirit/home/support/common_terminals.hpp>
- #include <boost/spirit/home/support/info.hpp>
- #include <boost/spirit/home/support/unused.hpp>
- #include <boost/spirit/home/support/attributes_fwd.hpp>
- #include <boost/spirit/home/support/detail/get_encoding.hpp>
- #include <boost/spirit/home/karma/detail/attributes.hpp>
- #include <boost/spirit/home/karma/detail/extract_from.hpp>
- #include <boost/spirit/home/karma/domain.hpp>
- #include <boost/spirit/home/karma/meta_compiler.hpp>
- #include <boost/spirit/home/karma/reference.hpp>
- #include <boost/spirit/home/karma/generate.hpp>
- #include <boost/spirit/home/karma/delimit_out.hpp>
- #include <boost/spirit/home/karma/detail/get_casetag.hpp>
- #include <boost/spirit/home/karma/detail/string_generate.hpp>
- #include <boost/config.hpp>
- #include <boost/proto/extends.hpp>
- #include <boost/proto/traits.hpp>
- #include <boost/shared_ptr.hpp>
- #include <boost/mpl/if.hpp>
- #include <map>
- #include <set>
- #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 traits
- {
- template <typename T, typename Attribute, typename Enable>
- struct symbols_lookup
- {
- typedef
- mpl::eval_if<fusion::traits::is_sequence<T>
- , traits::detail::value_at_c<T, 0>
- , detail::add_const_ref<T> > sequence_type;
- typedef typename
- mpl::eval_if<traits::is_container<T>
- , traits::container_value<T>
- , sequence_type>::type type;
- // fusion sequence
- template <typename T_>
- static type call(T_ const& t, mpl::false_, mpl::true_)
- {
- return fusion::at_c<0>(t);
- }
- // container
- template <typename T_, typename IsSequence>
- static type call(T_ const& t, mpl::true_, IsSequence)
- {
- return t[0];
- }
- // not a container and not a fusion sequence
- template <typename T_>
- static type call(T_ const& t, mpl::false_, mpl::false_)
- {
- return t;
- }
- static type call(T const& t)
- {
- typedef typename traits::is_container<T>::type is_container;
- typedef typename fusion::traits::is_sequence<T>::type is_sequence;
- return call(t, is_container(), is_sequence());
- }
- };
- template <typename Attribute>
- struct symbols_lookup<Attribute, Attribute>
- {
- typedef Attribute const& type;
- static type call(Attribute const& t)
- {
- return t;
- }
- };
- template <typename Attribute, typename T, typename Enable>
- struct symbols_value
- {
- typedef
- mpl::eval_if<fusion::traits::is_sequence<T>
- , traits::detail::value_at_c<T, 1>
- , mpl::identity<unused_type> > sequence_type;
- typedef typename
- mpl::eval_if<traits::is_container<T>
- , traits::container_value<T>
- , sequence_type>::type type;
- // fusion sequence
- template <typename T_>
- static type call(T_ const& t, mpl::false_, mpl::true_)
- {
- return fusion::at_c<1>(t);
- }
- // container
- template <typename T_, typename IsSequence>
- static type call(T_ const& t, mpl::true_, IsSequence)
- {
- return t[1];
- }
- // not a container nor a fusion sequence
- template <typename T_>
- static type call(T_ const&, mpl::false_, mpl::false_)
- {
- return unused;
- }
- static type call(T const& t)
- {
- typedef typename traits::is_container<T>::type is_container;
- typedef typename fusion::traits::is_sequence<T>::type is_sequence;
- return call(t, is_container(), is_sequence());
- }
- };
- template <typename Attribute>
- struct symbols_value<Attribute, Attribute>
- {
- typedef unused_type type;
- static type call(Attribute const&)
- {
- return unused;
- }
- };
- }}}
- ///////////////////////////////////////////////////////////////////////////////
- namespace boost { namespace spirit { namespace karma
- {
- ///////////////////////////////////////////////////////////////////////////
- template <typename T, typename Attribute>
- struct symbols_lookup
- : mpl::if_<
- traits::not_is_unused<T>
- , std::map<Attribute, T>
- , std::set<Attribute>
- >
- {};
- ///////////////////////////////////////////////////////////////////////////
- namespace detail
- {
- ///////////////////////////////////////////////////////////////////////
- template <typename CharEncoding, typename Tag>
- struct generate_encoded
- {
- typedef typename
- proto::terminal<tag::char_code<Tag, CharEncoding> >::type
- encoding_type;
- template <typename OutputIterator, typename Expr, typename Attribute>
- static bool call(OutputIterator& sink, Expr const& expr
- , Attribute const& attr)
- {
- encoding_type const encoding = encoding_type();
- return karma::generate(sink, encoding[expr], attr);
- }
- };
- template <>
- struct generate_encoded<unused_type, unused_type>
- {
- template <typename OutputIterator, typename Expr, typename Attribute>
- static bool call(OutputIterator& sink, Expr const& expr
- , Attribute const& attr)
- {
- return karma::generate(sink, expr, attr);
- }
- };
- }
- template <
- typename Attribute = char, typename T = unused_type
- , typename Lookup = typename symbols_lookup<T, Attribute>::type
- , typename CharEncoding = unused_type, typename Tag = unused_type>
- struct symbols
- : proto::extends<
- typename proto::terminal<
- reference<symbols<Attribute, T, Lookup, CharEncoding, Tag> >
- >::type
- , symbols<Attribute, T, Lookup, CharEncoding, Tag> >
- , primitive_generator<
- symbols<Attribute, T, Lookup, CharEncoding, Tag> >
- {
- typedef T value_type; // the value associated with each entry
- typedef reference<symbols> reference_;
- typedef typename proto::terminal<reference_>::type terminal;
- typedef proto::extends<terminal, symbols> base_type;
- template <typename Context, typename Unused>
- struct attribute
- {
- typedef Attribute type;
- };
- symbols(std::string const& name = "symbols")
- : base_type(terminal::make(reference_(*this)))
- , add(*this)
- , remove(*this)
- , lookup(new Lookup())
- , name_(name)
- {}
- symbols(symbols const& syms)
- : base_type(terminal::make(reference_(*this)))
- , add(*this)
- , remove(*this)
- , lookup(syms.lookup)
- , name_(syms.name_)
- {}
- template <typename CharEncoding_, typename Tag_>
- symbols(symbols<Attribute, T, Lookup, CharEncoding_, Tag_> const& syms)
- : base_type(terminal::make(reference_(*this)))
- , add(*this)
- , remove(*this)
- , lookup(syms.lookup)
- , name_(syms.name_)
- {}
- template <typename Symbols, typename Data>
- symbols(Symbols const& syms, Data const& data
- , std::string const& name = "symbols")
- : base_type(terminal::make(reference_(*this)))
- , add(*this)
- , remove(*this)
- , lookup(new Lookup())
- , name_(name)
- {
- 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)
- {
- *lookup = *rhs.lookup;
- name_ = rhs.name_;
- return *this;
- }
- template <typename CharEncoding_, typename Tag_>
- symbols&
- operator=(symbols<Attribute, T, Lookup, CharEncoding_, Tag_> const& rhs)
- {
- *lookup = *rhs.lookup;
- name_ = rhs.name_;
- return *this;
- }
- void clear()
- {
- lookup->clear();
- }
- struct adder;
- struct remover;
- template <typename Attr, typename T_>
- adder const&
- operator=(std::pair<Attr, T_> const& p)
- {
- lookup->clear();
- return add(p.first, p.second);
- }
- template <typename Attr, typename T_>
- friend adder const&
- operator+= (symbols& sym, std::pair<Attr, T_> const& p)
- {
- return sym.add(p.first, p.second);
- }
- template <typename Attr>
- friend remover const&
- operator-= (symbols& sym, Attr const& attr)
- {
- return sym.remove(attr);
- }
- #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- // non-const version needed to suppress proto's += kicking in
- template <typename Attr, typename T_>
- friend adder const&
- operator+= (symbols& sym, std::pair<Attr, T_>& p)
- {
- return sym.add(p.first, p.second);
- }
- // non-const version needed to suppress proto's -= kicking in
- template <typename Attr>
- friend remover const&
- operator-= (symbols& sym, Attr& attr)
- {
- return sym.remove(attr);
- }
- #else
- // for rvalue references
- template <typename Attr, typename T_>
- friend adder const&
- operator+= (symbols& sym, std::pair<Attr, T_>&& p)
- {
- return sym.add(p.first, p.second);
- }
- // for rvalue references
- template <typename Attr>
- friend remover const&
- operator-= (symbols& sym, Attr&& attr)
- {
- return sym.remove(attr);
- }
- #endif
- template <typename F>
- void for_each(F f) const
- {
- std::for_each(lookup->begin(), lookup->end(), f);
- }
- template <typename Attr>
- value_type* find(Attr const& attr)
- {
- typename Lookup::iterator it = lookup->find(attr);
- return (it != lookup->end()) ? &(*it).second : 0;
- }
- template <typename Attr>
- value_type& at(Attr const& attr)
- {
- return (*lookup)[attr];
- }
- ///////////////////////////////////////////////////////////////////////
- template <typename OutputIterator, typename Context, typename Delimiter
- , typename Attr>
- bool generate(OutputIterator& sink, Context&, Delimiter const& d
- , Attr const& attr) const
- {
- typename Lookup::iterator it = lookup->find(
- traits::symbols_lookup<Attr, Attribute>::call(attr));
- if (it == lookup->end())
- return false;
- return karma::detail::generate_encoded<CharEncoding, Tag>::call(
- sink, (*it).second
- , traits::symbols_value<Attribute, Attr>::call(attr)) &&
- karma::delimit_out(sink, d);
- }
- template <typename Context>
- info what(Context&) const
- {
- return info(name_);
- }
- void name(std::string const &str)
- {
- name_ = str;
- }
- std::string const &name() const
- {
- return name_;
- }
- ///////////////////////////////////////////////////////////////////////
- struct adder
- {
- template <typename, typename = unused_type>
- struct result { typedef adder const& type; };
- adder(symbols& sym)
- : sym(sym)
- {
- }
- template <typename Attr>
- adder const&
- operator()(Attr const& attr, T const& val = T()) const
- {
- sym.lookup->insert(typename Lookup::value_type(attr, val));
- return *this;
- }
- template <typename Attr>
- adder const&
- operator, (Attr const& attr) const
- {
- sym.lookup->insert(typename Lookup::value_type(attr, T()));
- return *this;
- }
- symbols& sym;
- // silence MSVC warning C4512: assignment operator could not be generated
- BOOST_DELETED_FUNCTION(adder& operator= (adder const&))
- };
- struct remover
- {
- template <typename>
- struct result { typedef remover const& type; };
- remover(symbols& sym)
- : sym(sym)
- {
- }
- template <typename Attr>
- remover const&
- operator()(Attr const& attr) const
- {
- sym.lookup->erase(attr);
- return *this;
- }
- template <typename Attr>
- remover const&
- operator, (Attr const& attr) const
- {
- sym.lookup->erase(attr);
- return *this;
- }
- symbols& sym;
- // silence MSVC warning C4512: assignment operator could not be generated
- BOOST_DELETED_FUNCTION(remover& operator= (remover const&))
- };
- adder add;
- remover remove;
- shared_ptr<Lookup> lookup;
- std::string name_;
- };
- ///////////////////////////////////////////////////////////////////////////
- // specialization for unused stored type
- template <
- typename Attribute, typename Lookup
- , typename CharEncoding, typename Tag>
- struct symbols<Attribute, unused_type, Lookup, CharEncoding, Tag>
- : proto::extends<
- typename proto::terminal<
- spirit::karma::reference<
- symbols<Attribute, unused_type, Lookup, CharEncoding, Tag> >
- >::type
- , symbols<Attribute, unused_type, Lookup, CharEncoding, Tag>
- >
- , spirit::karma::generator<
- symbols<Attribute, unused_type, Lookup, CharEncoding, Tag> >
- {
- typedef unused_type value_type; // the value associated with each entry
- typedef spirit::karma::reference<symbols> reference_;
- typedef typename proto::terminal<reference_>::type terminal;
- typedef proto::extends<terminal, symbols> base_type;
- template <typename Context, typename Unused>
- struct attribute
- {
- typedef Attribute type;
- };
- symbols(std::string const& name = "symbols")
- : base_type(terminal::make(reference_(*this)))
- , add(*this)
- , remove(*this)
- , lookup(new Lookup())
- , name_(name)
- {}
- symbols(symbols const& syms)
- : base_type(terminal::make(reference_(*this)))
- , add(*this)
- , remove(*this)
- , lookup(syms.lookup)
- , name_(syms.name_)
- {}
- template <typename CharEncoding_, typename Tag_>
- symbols(symbols<Attribute, unused_type, Lookup, CharEncoding_, Tag_> const& syms)
- : base_type(terminal::make(reference_(*this)))
- , add(*this)
- , remove(*this)
- , lookup(syms.lookup)
- , name_(syms.name_)
- {}
- template <typename Symbols, typename Data>
- symbols(Symbols const& syms, Data const& data
- , std::string const& name = "symbols")
- : base_type(terminal::make(reference_(*this)))
- , add(*this)
- , remove(*this)
- , lookup(new Lookup())
- , name_(name)
- {
- 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)
- {
- *lookup = *rhs.lookup;
- name_ = rhs.name_;
- return *this;
- }
- template <typename CharEncoding_, typename Tag_>
- symbols&
- operator=(symbols<Attribute, unused_type, Lookup, CharEncoding_, Tag_> const& rhs)
- {
- *lookup = *rhs.lookup;
- name_ = rhs.name_;
- return *this;
- }
- void clear()
- {
- lookup->clear();
- }
- struct adder;
- struct remover;
- template <typename Attr>
- adder const&
- operator=(Attr const& attr)
- {
- lookup->clear();
- return add(attr);
- }
- template <typename Attr>
- friend adder const&
- operator+= (symbols& sym, Attr const& attr)
- {
- return sym.add(attr);
- }
- template <typename Attr>
- friend remover const&
- operator-= (symbols& sym, Attr const& attr)
- {
- return sym.remove(attr);
- }
- // non-const version needed to suppress proto's += kicking in
- template <typename Attr>
- friend adder const&
- operator+= (symbols& sym, Attr& attr)
- {
- return sym.add(attr);
- }
- // non-const version needed to suppress proto's -= kicking in
- template <typename Attr>
- friend remover const&
- operator-= (symbols& sym, Attr& attr)
- {
- return sym.remove(attr);
- }
- template <typename F>
- void for_each(F f) const
- {
- std::for_each(lookup->begin(), lookup->end(), f);
- }
- template <typename Attr>
- value_type const* find(Attr const& attr)
- {
- typename Lookup::iterator it = lookup->find(attr);
- return (it != lookup->end()) ? &unused : 0;
- }
- template <typename Attr>
- value_type at(Attr const& attr)
- {
- typename Lookup::iterator it = lookup->find(attr);
- if (it == lookup->end())
- add(attr);
- return unused;
- }
- ///////////////////////////////////////////////////////////////////////
- template <typename OutputIterator, typename Context, typename Delimiter
- , typename Attr>
- bool generate(OutputIterator& sink, Context&, Delimiter const& d
- , Attr const& attr) const
- {
- typename Lookup::iterator it = lookup->find(
- traits::symbols_lookup<Attr, Attribute>::call(attr));
- if (it == lookup->end())
- return false;
- return karma::detail::generate_encoded<CharEncoding, Tag>::
- call(sink
- , traits::symbols_lookup<Attr, Attribute>::call(attr)
- , unused) &&
- karma::delimit_out(sink, d);
- }
- template <typename Context>
- info what(Context&) const
- {
- return info(name_);
- }
- void name(std::string const &str)
- {
- name_ = str;
- }
- std::string const &name() const
- {
- return name_;
- }
- ///////////////////////////////////////////////////////////////////////
- struct adder
- {
- template <typename, typename = unused_type>
- struct result { typedef adder const& type; };
- adder(symbols& sym)
- : sym(sym)
- {
- }
- template <typename Attr>
- adder const&
- operator()(Attr const& attr) const
- {
- sym.lookup->insert(attr);
- return *this;
- }
- template <typename Attr>
- adder const&
- operator, (Attr const& attr) const
- {
- sym.lookup->insert(attr);
- return *this;
- }
- symbols& sym;
- // silence MSVC warning C4512: assignment operator could not be generated
- BOOST_DELETED_FUNCTION(adder& operator= (adder const&))
- };
- struct remover
- {
- template <typename>
- struct result { typedef remover const& type; };
- remover(symbols& sym)
- : sym(sym)
- {
- }
- template <typename Attr>
- remover const&
- operator()(Attr const& attr) const
- {
- sym.lookup->erase(attr);
- return *this;
- }
- template <typename Attr>
- remover const&
- operator, (Attr const& attr) const
- {
- sym.lookup->erase(attr);
- return *this;
- }
- symbols& sym;
- // silence MSVC warning C4512: assignment operator could not be generated
- BOOST_DELETED_FUNCTION(remover& operator= (remover const&))
- };
- adder add;
- remover remove;
- shared_ptr<Lookup> lookup;
- std::string name_;
- };
- ///////////////////////////////////////////////////////////////////////////
- // Generator generators: make_xxx function (objects)
- ///////////////////////////////////////////////////////////////////////////
- template <typename Attribute, typename T, typename Lookup
- , typename CharEnconding, typename Tag, typename Modifiers>
- struct make_primitive<
- reference<symbols<Attribute, T, Lookup, CharEnconding, Tag> >
- , Modifiers>
- {
- static bool const lower =
- has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
- static bool const upper =
- has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
- typedef reference<
- symbols<Attribute, T, Lookup, CharEnconding, Tag>
- > reference_;
- typedef typename mpl::if_c<
- lower || upper
- , symbols<
- Attribute, T, Lookup
- , typename spirit::detail::get_encoding_with_case<
- Modifiers, unused_type, lower || upper>::type
- , typename detail::get_casetag<Modifiers, lower || upper>::type>
- , reference_>::type
- result_type;
- result_type operator()(reference_ ref, unused_type) const
- {
- return result_type(ref.ref.get());
- }
- };
- }}}
- namespace boost { namespace spirit { namespace traits
- {
- ///////////////////////////////////////////////////////////////////////////
- template <typename Attribute, typename T, typename Lookup
- , typename CharEncoding, typename Tag
- , typename Attr, typename Context, typename Iterator>
- struct handles_container<karma::symbols<Attribute, T, Lookup, CharEncoding, Tag>
- , Attr, Context, Iterator>
- : traits::is_container<Attr> {};
- }}}
- #if defined(BOOST_MSVC)
- # pragma warning(pop)
- #endif
- #endif
|