You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
431 lines
13 KiB
431 lines
13 KiB
/*============================================================================= |
|
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); |
|
} |
|
|
|
#if defined(BOOST_NO_RVALUE_REFERENCES) |
|
// 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); |
|
} |
|
#else |
|
// for rvalue references |
|
template <typename Str> |
|
friend adder const& |
|
operator+=(symbols& sym, Str&& str) |
|
{ |
|
return sym.add(str); |
|
} |
|
|
|
// for rvalue references |
|
template <typename Str> |
|
friend remover const& |
|
operator-=(symbols& sym, Str&& str) |
|
{ |
|
return sym.remove(str); |
|
} |
|
#endif |
|
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()); |
|
} |
|
}; |
|
}}} |
|
|
|
namespace boost { namespace spirit { namespace traits |
|
{ |
|
/////////////////////////////////////////////////////////////////////////// |
|
template <typename Char, typename T, typename Lookup, typename Filter |
|
, typename Attr, typename Context, typename Iterator> |
|
struct handles_container<qi::symbols<Char, T, Lookup, Filter>, Attr, Context, Iterator> |
|
: traits::is_container<Attr> {}; |
|
}}} |
|
|
|
#if defined(BOOST_MSVC) |
|
# pragma warning(pop) |
|
#endif |
|
|
|
#endif
|
|
|