337 lines
9.7 KiB
C++
337 lines
9.7 KiB
C++
/*=============================================================================
|
|
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
|