/*============================================================================= | |
Copyright (c) 2001-2011 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_SYMBOLS_MARCH_11_2007_1055AM) | |
#define BOOST_SPIRIT_SYMBOLS_MARCH_11_2007_1055AM | |
#if defined(_MSC_VER) | |
#pragma once | |
#endif | |
#include <boost/spirit/home/qi/domain.hpp> | |
#include <boost/spirit/home/qi/skip_over.hpp> | |
#include <boost/spirit/home/qi/string/tst.hpp> | |
#include <boost/spirit/home/qi/reference.hpp> | |
#include <boost/spirit/home/qi/meta_compiler.hpp> | |
#include <boost/spirit/home/qi/detail/assign_to.hpp> | |
#include <boost/spirit/home/qi/parser.hpp> | |
#include <boost/spirit/home/support/detail/get_encoding.hpp> | |
#include <boost/spirit/home/support/modify.hpp> | |
#include <boost/spirit/home/support/info.hpp> | |
#include <boost/spirit/home/support/unused.hpp> | |
#include <boost/spirit/home/support/string_traits.hpp> | |
#include <boost/fusion/include/at.hpp> | |
#include <boost/range.hpp> | |
#include <boost/type_traits/add_reference.hpp> | |
#include <boost/shared_ptr.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 Char = char | |
, typename T = unused_type | |
, typename Lookup = tst<Char, T> | |
, typename Filter = tst_pass_through> | |
struct symbols | |
: proto::extends< | |
typename proto::terminal< | |
reference<symbols<Char, T, Lookup, Filter> > | |
>::type | |
, symbols<Char, T, Lookup, Filter> | |
> | |
, primitive_parser<symbols<Char, T, Lookup, Filter> > | |
{ | |
typedef Char char_type; // the character type | |
typedef T value_type; // the value associated with each entry | |
typedef symbols<Char, T, Lookup, Filter> this_type; | |
typedef reference<this_type> reference_; | |
typedef typename proto::terminal<reference_>::type terminal; | |
typedef proto::extends<terminal, this_type> base_type; | |
template <typename Context, typename Iterator> | |
struct attribute | |
{ | |
typedef value_type 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 Filter_> | |
symbols(symbols<Char, T, Lookup, Filter_> const& syms) | |
: base_type(terminal::make(reference_(*this))) | |
, add(*this) | |
, remove(*this) | |
, lookup(syms.lookup) | |
, name_(syms.name_) | |
{ | |
} | |
template <typename Symbols> | |
symbols(Symbols const& syms, 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); | |
while (si != boost::end(syms)) | |
add(*si++); | |
} | |
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) | |
{ | |
name_ = rhs.name_; | |
*lookup = *rhs.lookup; | |
return *this; | |
} | |
template <typename Filter_> | |
symbols& | |
operator=(symbols<Char, T, Lookup, Filter_> 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& sym, Str const& str) | |
{ | |
return sym.add(str); | |
} | |
template <typename Str> | |
friend remover const& | |
operator-=(symbols& sym, Str const& str) | |
{ | |
return sym.remove(str); | |
} | |
// non-const version needed to suppress proto's += kicking in | |
template <typename Str> | |
friend adder const& | |
operator+=(symbols& sym, Str& str) | |
{ | |
return sym.add(str); | |
} | |
// non-const version needed to suppress proto's -= kicking in | |
template <typename Str> | |
friend remover const& | |
operator-=(symbols& sym, Str& 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_begin<Char>(str) | |
, traits::get_end<Char>(str), T()); | |
} | |
template <typename Iterator> | |
value_type* prefix_find(Iterator& first, Iterator const& last) | |
{ | |
return lookup->find(first, last, Filter()); | |
} | |
template <typename Iterator> | |
value_type const* prefix_find(Iterator& first, Iterator const& last) const | |
{ | |
return lookup->find(first, last, Filter()); | |
} | |
template <typename Str> | |
value_type* find(Str const& str) | |
{ | |
return find_impl(traits::get_begin<Char>(str) | |
, traits::get_end<Char>(str)); | |
} | |
template <typename Str> | |
value_type const* find(Str const& str) const | |
{ | |
return find_impl(traits::get_begin<Char>(str) | |
, traits::get_end<Char>(str)); | |
} | |
private: | |
template <typename Iterator> | |
value_type* find_impl(Iterator begin, Iterator end) | |
{ | |
value_type* r = lookup->find(begin, end, Filter()); | |
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, Filter()); | |
return begin == end ? r : 0; | |
} | |
public: | |
template <typename Iterator, typename Context | |
, typename Skipper, typename Attribute> | |
bool parse(Iterator& first, Iterator const& last | |
, Context& /*context*/, Skipper const& skipper, Attribute& attr) const | |
{ | |
qi::skip_over(first, last, skipper); | |
if (value_type* val_ptr | |
= lookup->find(first, last, Filter())) | |
{ | |
spirit::traits::assign_to(*val_ptr, attr); | |
return true; | |
} | |
return false; | |
} | |
template <typename Context> | |
info what(Context& /*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, 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) 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_begin<Char>(s) | |
, traits::get_end<Char>(s), val); | |
return *this; | |
} | |
template <typename Str> | |
adder const& | |
operator,(Str const& s) const | |
{ | |
sym.lookup->add(traits::get_begin<Char>(s) | |
, traits::get_end<Char>(s), T()); | |
return *this; | |
} | |
symbols& sym; | |
private: | |
// silence MSVC warning C4512: assignment operator could not be generated | |
adder& operator= (adder const&); | |
}; | |
struct remover | |
{ | |
template <typename, typename = unused_type, typename = unused_type> | |
struct result { typedef remover 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; | |
} | |
template <typename Str> | |
remover const& | |
operator()(Str const& s) const | |
{ | |
sym.lookup->remove(traits::get_begin<Char>(s) | |
, traits::get_end<Char>(s)); | |
return *this; | |
} | |
template <typename Str> | |
remover const& | |
operator,(Str const& s) const | |
{ | |
sym.lookup->remove(traits::get_begin<Char>(s) | |
, traits::get_end<Char>(s)); | |
return *this; | |
} | |
symbols& sym; | |
private: | |
// silence MSVC warning C4512: assignment operator could not be generated | |
remover& operator= (remover const&); | |
}; | |
adder add; | |
remover remove; | |
shared_ptr<Lookup> lookup; | |
std::string name_; | |
}; | |
/////////////////////////////////////////////////////////////////////////// | |
// Parser generators: make_xxx function (objects) | |
/////////////////////////////////////////////////////////////////////////// | |
template <typename Char, typename T, typename Lookup | |
, typename Filter, typename Modifiers> | |
struct make_primitive<reference<symbols<Char, T, Lookup, Filter> >, Modifiers> | |
{ | |
template <typename CharEncoding> | |
struct no_case_filter | |
{ | |
Char operator()(Char ch) const | |
{ | |
return static_cast<Char>(CharEncoding::tolower(ch)); | |
} | |
}; | |
typedef has_modifier<Modifiers, tag::char_code_base<tag::no_case> > no_case; | |
typedef reference<symbols<Char, T, Lookup, Filter> > reference_; | |
typedef no_case_filter< | |
typename spirit::detail::get_encoding_with_case< | |
Modifiers | |
, char_encoding::standard | |
, no_case::value>::type> | |
nc_filter; | |
typedef typename mpl::if_< | |
no_case | |
, symbols<Char, T, Lookup, nc_filter> | |
, reference_>::type | |
result_type; | |
result_type operator()(reference_ ref, unused_type) const | |
{ | |
return result_type(ref.ref.get()); | |
} | |
}; | |
}}} | |
#if defined(BOOST_MSVC) | |
# pragma warning(pop) | |
#endif | |
#endif |