diff options
Diffstat (limited to 'boost/spirit/home/x3/support')
40 files changed, 4509 insertions, 0 deletions
diff --git a/boost/spirit/home/x3/support/ast/position_tagged.hpp b/boost/spirit/home/x3/support/ast/position_tagged.hpp new file mode 100644 index 0000000000..22cfd7588b --- /dev/null +++ b/boost/spirit/home/x3/support/ast/position_tagged.hpp @@ -0,0 +1,96 @@ +/*============================================================================= + Copyright (c) 2014 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_X3_POSITION_TAGGED_MAY_01_2014_0321PM) +#define BOOST_SPIRIT_X3_POSITION_TAGGED_MAY_01_2014_0321PM + +#include <boost/range.hpp> +#include <boost/type_traits/is_base_of.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + struct position_tagged + { + // Use this to annotate an AST with the iterator position. + // These ids are used as a key to the position_cache (below) + // and marks the start and end of an AST node. + int id_first = -1; + int id_last = -1; + }; + + template <typename Container> + class position_cache + { + public: + + typedef typename Container::value_type iterator_type; + + position_cache( + iterator_type first + , iterator_type last) + : first_(first), last_(last) {} + + // This will catch all nodes inheriting from position_tagged + boost::iterator_range<iterator_type> + position_of(position_tagged const& ast) const + { + return + boost::iterator_range<iterator_type>( + positions.at(ast.id_first) // throws if out of range + , positions.at(ast.id_last) // throws if out of range + ); + } + + // This will catch all nodes except those inheriting from position_tagged + template <typename AST> + boost::iterator_range<iterator_type> + position_of(AST const& ast) const + { + // returns an empty position + return boost::iterator_range<iterator_type>(); + } + + // This will catch all nodes except those inheriting from position_tagged + template <typename AST> + void annotate(AST& ast, iterator_type first, iterator_type last, mpl::false_) + { + // (no-op) no need for tags + } + + // This will catch all nodes inheriting from position_tagged + void annotate(position_tagged& ast, iterator_type first, iterator_type last, mpl::true_) + { + ast.id_first = int(positions.size()); + positions.push_back(first); + ast.id_last = int(positions.size()); + positions.push_back(last); + } + + template <typename AST> + void annotate(AST& ast, iterator_type first, iterator_type last) + { + annotate(ast, first, last, is_base_of<position_tagged, AST>()); + } + + Container const& + get_positions() const + { + return positions; + } + + iterator_type first() const { return first_; } + iterator_type last() const { return last_; } + + private: + + Container positions; + iterator_type first_; + iterator_type last_; + }; + +}}} + +#endif diff --git a/boost/spirit/home/x3/support/ast/variant.hpp b/boost/spirit/home/x3/support/ast/variant.hpp new file mode 100644 index 0000000000..cf626e88be --- /dev/null +++ b/boost/spirit/home/x3/support/ast/variant.hpp @@ -0,0 +1,249 @@ +/*============================================================================= + Copyright (c) 2001-2014 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_X3_VARIANT_AUGUST_6_2011_0859AM) +#define BOOST_SPIRIT_X3_VARIANT_AUGUST_6_2011_0859AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/variant.hpp> +#include <boost/mpl/list.hpp> +#include <boost/type_traits/is_base_of.hpp> + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { namespace x3 +{ + template <typename T> + class forward_ast + { + public: + + typedef T type; + + public: + + forward_ast() : p_(new T) {} + + forward_ast(forward_ast const& operand) + : p_(new T(operand.get())) {} + + forward_ast(forward_ast&& operand) + : p_(operand.p_) + { + operand.p_ = 0; + } + + forward_ast(T const& operand) + : p_(new T(operand)) {} + + forward_ast(T&& operand) + : p_(new T(std::move(operand))) {} + + ~forward_ast() + { + boost::checked_delete(p_); + } + + forward_ast& operator=(forward_ast const& rhs) + { + assign(rhs.get()); + return *this; + } + + void swap(forward_ast& operand) BOOST_NOEXCEPT + { + T* temp = operand.p_; + operand.p_ = p_; + p_ = temp; + } + + forward_ast& operator=(T const& rhs) + { + assign(rhs); + return *this; + } + + forward_ast& operator=(forward_ast&& rhs) BOOST_NOEXCEPT + { + swap(rhs); + return *this; + } + + forward_ast& operator=(T&& rhs) + { + get() = std::move(rhs); + return *this; + } + + T& get() { return *get_pointer(); } + const T& get() const { return *get_pointer(); } + + T* get_pointer() { return p_; } + const T* get_pointer() const { return p_; } + + operator T const&() const { return this->get(); } + operator T&() { return this->get(); } + + private: + + void assign(const T& rhs) + { + this->get() = rhs; + } + + T* p_; + }; + + // function template swap + // + // Swaps two forward_ast<T> objects of the same type T. + // + template <typename T> + inline void swap(forward_ast<T>& lhs, forward_ast<T>& rhs) BOOST_NOEXCEPT + { + lhs.swap(rhs); + } + + namespace detail + { + template <typename T> + struct remove_forward : mpl::identity<T> + {}; + + template <typename T> + struct remove_forward<forward_ast<T>> : mpl::identity<T> + {}; + } + + template <typename ...Types> + struct variant + { + // tell spirit that this is an adapted variant + struct adapted_variant_tag; + + typedef boost::variant<Types...> variant_type; + typedef mpl::list<typename detail::remove_forward<Types>::type...> types; + typedef variant<Types...> base_type; + + variant() : var() {} + + template <typename T, typename disable_if<is_base_of<base_type, T>>::type> + explicit variant(T const& rhs) + : var(rhs) {} + + template <typename T, typename disable_if<is_base_of<base_type, T>>::type> + explicit variant(T&& rhs) + : var(std::forward<T>(rhs)) {} + + variant(variant const& rhs) + : var(rhs.var) {} + + variant(variant& rhs) + : var(rhs.var) {} + + variant(variant&& rhs) + : var(std::forward<variant_type>(rhs.var)) {} + + variant& operator=(variant const& rhs) + { + var = rhs.get(); + return *this; + } + + variant& operator=(variant&& rhs) + { + var = std::forward<variant_type>(rhs.get()); + return *this; + } + + template <typename T> + //typename disable_if<is_base_of<base_type, T>, variant&>::type + variant& operator=(T const& rhs) + { + var = rhs; + return *this; + } + + template <typename T> + //typename disable_if<is_base_of<base_type, T>, variant&>::type + variant& operator=(T&& rhs) + { + var = std::forward<T>(rhs); + return *this; + } + + template <typename F> + typename F::result_type apply_visitor(F const& v) + { + return var.apply_visitor(v); + } + + template <typename F> + typename F::result_type apply_visitor(F const& v) const + { + return var.apply_visitor(v); + } + + template <typename F> + typename F::result_type apply_visitor(F& v) + { + return var.apply_visitor(v); + } + + template <typename F> + typename F::result_type apply_visitor(F& v) const + { + return var.apply_visitor(v); + } + + variant_type const& get() const + { + return var; + } + + variant_type& get() + { + return var; + } + + variant_type var; + }; +}}} + +namespace boost +{ + template <typename T, typename ...Types> + inline T const& + get(boost::spirit::x3::variant<Types...> const& x) + { + return boost::get<T>(x.get()); + } + + template <typename T, typename ...Types> + inline T& + get(boost::spirit::x3::variant<Types...>& x) + { + return boost::get<T>(x.get()); + } + + template <typename T, typename ...Types> + inline T const* + get(boost::spirit::x3::variant<Types...> const* x) + { + return boost::get<T>(&x->get()); + } + + template <typename T, typename ...Types> + inline T* + get(boost::spirit::x3::variant<Types...>* x) + { + return boost::get<T>(&x->get()); + } +} + +#endif diff --git a/boost/spirit/home/x3/support/context.hpp b/boost/spirit/home/x3/support/context.hpp new file mode 100644 index 0000000000..93bcb24070 --- /dev/null +++ b/boost/spirit/home/x3/support/context.hpp @@ -0,0 +1,135 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + http://spirit.sourceforge.net/ + + 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_CONTEXT_JAN_4_2012_1215PM) +#define BOOST_SPIRIT_X3_CONTEXT_JAN_4_2012_1215PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/unused.hpp> +#include <boost/mpl/identity.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename ID, typename T, typename Next = unused_type> + struct context + { + context(T& val, Next const& next) + : val(val), next(next) {} + + template <typename ID_, typename Unused = void> + struct get_result + { + typedef typename Next::template get_result<ID_>::type type; + }; + + template <typename Unused> + struct get_result<mpl::identity<ID>, Unused> + { + typedef T& type; + }; + + T& get(mpl::identity<ID>) const + { + return val; + } + + template <typename ID_> + typename Next::template get_result<ID_>::type + get(ID_ id) const + { + return next.get(id); + } + + T& val; + Next const& next; + }; + + template <typename ID, typename T> + struct context<ID, T, unused_type> + { + context(T& val) + : val(val) {} + + context(T& val, unused_type) + : val(val) {} + + template <typename ID_, typename Unused = void> + struct get_result + { + typedef unused_type type; + }; + + template <typename Unused> + struct get_result<mpl::identity<ID>, Unused> + { + typedef T& type; + }; + + T& get(mpl::identity<ID>) const + { + return val; + } + + template <typename ID_> + unused_type + get(ID_) const + { + return unused; + } + + T& val; + }; + + template <typename Tag, typename Context> + inline auto + get(Context const& context) + -> decltype(context.get(mpl::identity<Tag>())) + { + return context.get(mpl::identity<Tag>()); + } + + template <typename ID, typename T, typename Next> + inline context<ID, T, Next> make_context(T& val, Next const& next) + { + return context<ID, T, Next>(val, next); + } + + template <typename ID, typename T> + inline context<ID, T> make_context(T& val) + { + return context<ID, T>(val); + } + + namespace detail + { + template <typename ID, typename T, typename Next, typename FoundVal> + inline Next const& + make_unique_context(T& val, Next const& next, FoundVal&) + { + return next; + } + + template <typename ID, typename T, typename Next> + inline context<ID, T, Next> + make_unique_context(T& val, Next const& next, unused_type) + { + return context<ID, T, Next>(val, next); + } + } + + template <typename ID, typename T, typename Next> + inline auto + make_unique_context(T& val, Next const& next) + { + return detail::make_unique_context<ID>(val, next, x3::get<ID>(next)); + } +}}} + +#endif diff --git a/boost/spirit/home/x3/support/numeric_utils/detail/extract_int.hpp b/boost/spirit/home/x3/support/numeric_utils/detail/extract_int.hpp new file mode 100644 index 0000000000..73770c87d0 --- /dev/null +++ b/boost/spirit/home/x3/support/numeric_utils/detail/extract_int.hpp @@ -0,0 +1,512 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + Copyright (c) 2011 Jan Frederick Eick + Copyright (c) 2011 Christopher Jefferson + Copyright (c) 2006 Stephen Nutt + + 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_DETAIL_EXTRACT_INT_APRIL_17_2006_0816AM) +#define BOOST_SPIRIT_X3_DETAIL_EXTRACT_INT_APRIL_17_2006_0816AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/unused.hpp> +#include <boost/spirit/home/x3/support/traits/attribute_type.hpp> +#include <boost/spirit/home/x3/support/traits/move_to.hpp> +#include <boost/spirit/home/x3/support/traits/numeric_traits.hpp> +#include <boost/spirit/home/support/char_encoding/ascii.hpp> + +#include <boost/preprocessor/repetition/repeat.hpp> +#include <boost/preprocessor/iteration/local.hpp> +#include <boost/preprocessor/comparison/less.hpp> +#include <boost/preprocessor/control/if.hpp> +#include <boost/preprocessor/seq/elem.hpp> + +#include <boost/detail/iterator.hpp> +#include <boost/utility/enable_if.hpp> + +#include <boost/type_traits/is_integral.hpp> +#include <boost/type_traits/is_signed.hpp> +#include <boost/type_traits/make_unsigned.hpp> + +#include <boost/mpl/bool.hpp> +#include <boost/mpl/and.hpp> +#include <boost/limits.hpp> + +#if !defined(SPIRIT_NUMERICS_LOOP_UNROLL) +# define SPIRIT_NUMERICS_LOOP_UNROLL 3 +#endif + +namespace boost { namespace spirit { namespace x3 { namespace detail +{ + /////////////////////////////////////////////////////////////////////////// + // + // The maximum radix digits that can be represented without + // overflow: + // + // template<typename T, unsigned Radix> + // struct digits_traits::value; + // + /////////////////////////////////////////////////////////////////////////// + template <typename T, unsigned Radix> + struct digits_traits; + +// lookup table for log2(x) : 2 <= x <= 36 +#define BOOST_SPIRIT_X3_LOG2 (#error)(#error) \ + (1000000)(1584960)(2000000)(2321920)(2584960)(2807350) \ + (3000000)(3169920)(3321920)(3459430)(3584960)(3700430) \ + (3807350)(3906890)(4000000)(4087460)(4169920)(4247920) \ + (4321920)(4392310)(4459430)(4523560)(4584960)(4643850) \ + (4700430)(4754880)(4807350)(4857980)(4906890)(4954190) \ + (5000000)(5044390)(5087460)(5129280)(5169925) \ + /***/ + +#define BOOST_PP_LOCAL_MACRO(Radix) \ + template <typename T> struct digits_traits<T, Radix> \ + { \ + typedef std::numeric_limits<T> numeric_limits_type; \ + BOOST_STATIC_CONSTANT(int, value = static_cast<int>( \ + (numeric_limits_type::digits * 1000000) / \ + BOOST_PP_SEQ_ELEM(Radix, BOOST_SPIRIT_X3_LOG2))); \ + }; \ + /***/ + +#define BOOST_PP_LOCAL_LIMITS (2, 36) +#include BOOST_PP_LOCAL_ITERATE() + +#undef BOOST_SPIRIT_X3_LOG2 + + /////////////////////////////////////////////////////////////////////////// + // + // Traits class for radix specific number conversion + // + // Test the validity of a single character: + // + // template<typename Char> static bool is_valid(Char ch); + // + // Convert a digit from character representation to binary + // representation: + // + // template<typename Char> static int digit(Char ch); + // + /////////////////////////////////////////////////////////////////////////// + template <unsigned Radix> + struct radix_traits + { + template <typename Char> + inline static bool is_valid(Char ch) + { + if (Radix <= 10) + return (ch >= '0' && ch <= static_cast<Char>('0' + Radix -1)); + return (ch >= '0' && ch <= '9') + || (ch >= 'a' && ch <= static_cast<Char>('a' + Radix -10 -1)) + || (ch >= 'A' && ch <= static_cast<Char>('A' + Radix -10 -1)); + } + + template <typename Char> + inline static unsigned digit(Char ch) + { + if (Radix <= 10 || (ch >= '0' && ch <= '9')) + return ch - '0'; + return char_encoding::ascii::tolower(ch) - 'a' + 10; + } + }; + + /////////////////////////////////////////////////////////////////////////// + // positive_accumulator/negative_accumulator: Accumulator policies for + // extracting integers. Use positive_accumulator if number is positive. + // Use negative_accumulator if number is negative. + /////////////////////////////////////////////////////////////////////////// + template <unsigned Radix> + struct positive_accumulator + { + template <typename T, typename Char> + inline static void add(T& n, Char ch, mpl::false_) // unchecked add + { + const int digit = radix_traits<Radix>::digit(ch); + n = n * T(Radix) + T(digit); + } + + template <typename T, typename Char> + inline static bool add(T& n, Char ch, mpl::true_) // checked add + { + // Ensure n *= Radix will not overflow + static T const max = (std::numeric_limits<T>::max)(); + static T const val = max / Radix; + if (n > val) + return false; + + n *= Radix; + + // Ensure n += digit will not overflow + const int digit = radix_traits<Radix>::digit(ch); + if (n > max - digit) + return false; + + n += static_cast<T>(digit); + return true; + } + }; + + template <unsigned Radix> + struct negative_accumulator + { + template <typename T, typename Char> + inline static void add(T& n, Char ch, mpl::false_) // unchecked subtract + { + const int digit = radix_traits<Radix>::digit(ch); + n = n * T(Radix) - T(digit); + } + + template <typename T, typename Char> + inline static bool add(T& n, Char ch, mpl::true_) // checked subtract + { + // Ensure n *= Radix will not underflow + static T const min = (std::numeric_limits<T>::min)(); + static T const val = (min + 1) / T(Radix); + if (n < val) + return false; + + n *= Radix; + + // Ensure n -= digit will not underflow + int const digit = radix_traits<Radix>::digit(ch); + if (n < min + digit) + return false; + + n -= static_cast<T>(digit); + return true; + } + }; + + /////////////////////////////////////////////////////////////////////////// + // Common code for extract_int::parse specializations + /////////////////////////////////////////////////////////////////////////// + template <unsigned Radix, typename Accumulator, int MaxDigits> + struct int_extractor + { + template <typename Char, typename T> + inline static bool + call(Char ch, std::size_t count, T& n, mpl::true_) + { + static std::size_t const + overflow_free = digits_traits<T, Radix>::value - 1; + + if (count < overflow_free) + { + Accumulator::add(n, ch, mpl::false_()); + } + else + { + if (!Accumulator::add(n, ch, mpl::true_())) + return false; // over/underflow! + } + return true; + } + + template <typename Char, typename T> + inline static bool + call(Char ch, std::size_t /*count*/, T& n, mpl::false_) + { + // no need to check for overflow + Accumulator::add(n, ch, mpl::false_()); + return true; + } + + template <typename Char> + inline static bool + call(Char /*ch*/, std::size_t /*count*/, unused_type, mpl::false_) + { + return true; + } + + template <typename Char, typename T> + inline static bool + call(Char ch, std::size_t count, T& n) + { + return call(ch, count, n + , mpl::bool_< + ( (MaxDigits < 0) + || (MaxDigits > digits_traits<T, Radix>::value) + ) + && traits::check_overflow<T>::value + >() + ); + } + }; + + /////////////////////////////////////////////////////////////////////////// + // End of loop checking: check if the number of digits + // being parsed exceeds MaxDigits. Note: if MaxDigits == -1 + // we don't do any checking. + /////////////////////////////////////////////////////////////////////////// + template <int MaxDigits> + struct check_max_digits + { + inline static bool + call(std::size_t count) + { + return count < MaxDigits; // bounded + } + }; + + template <> + struct check_max_digits<-1> + { + inline static bool + call(std::size_t /*count*/) + { + return true; // unbounded + } + }; + + /////////////////////////////////////////////////////////////////////////// + // extract_int: main code for extracting integers + /////////////////////////////////////////////////////////////////////////// +#define SPIRIT_NUMERIC_INNER_LOOP(z, x, data) \ + if (!check_max_digits<MaxDigits>::call(count + leading_zeros) \ + || it == last) \ + break; \ + ch = *it; \ + if (!radix_check::is_valid(ch) || !extractor::call(ch, count, val)) \ + break; \ + ++it; \ + ++count; \ + /**/ + + template < + typename T, unsigned Radix, unsigned MinDigits, int MaxDigits + , typename Accumulator = positive_accumulator<Radix> + , bool Accumulate = false + > + struct extract_int + { +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + template <typename Iterator, typename Attribute> + inline static bool + parse_main( + Iterator& first + , Iterator const& last + , Attribute& attr) + { + typedef radix_traits<Radix> radix_check; + typedef int_extractor<Radix, Accumulator, MaxDigits> extractor; + typedef typename + boost::detail::iterator_traits<Iterator>::value_type + char_type; + + Iterator it = first; + std::size_t leading_zeros = 0; + if (!Accumulate) + { + // skip leading zeros + while (it != last && *it == '0' && leading_zeros < MaxDigits) + { + ++it; + ++leading_zeros; + } + } + + typedef typename + traits::attribute_type<Attribute>::type + attribute_type; + + attribute_type val = Accumulate ? attr : attribute_type(0); + std::size_t count = 0; + char_type ch; + + while (true) + { + BOOST_PP_REPEAT( + SPIRIT_NUMERICS_LOOP_UNROLL + , SPIRIT_NUMERIC_INNER_LOOP, _) + } + + if (count + leading_zeros >= MinDigits) + { + traits::move_to(val, attr); + first = it; + return true; + } + return false; + } +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +# pragma warning(pop) +#endif + + template <typename Iterator> + inline static bool + parse( + Iterator& first + , Iterator const& last + , unused_type) + { + T n = 0; // must calculate value to detect over/underflow + return parse_main(first, last, n); + } + + template <typename Iterator, typename Attribute> + inline static bool + parse( + Iterator& first + , Iterator const& last + , Attribute& attr) + { + return parse_main(first, last, attr); + } + }; +#undef SPIRIT_NUMERIC_INNER_LOOP + + /////////////////////////////////////////////////////////////////////////// + // extract_int: main code for extracting integers + // common case where MinDigits == 1 and MaxDigits = -1 + /////////////////////////////////////////////////////////////////////////// +#define SPIRIT_NUMERIC_INNER_LOOP(z, x, data) \ + if (it == last) \ + break; \ + ch = *it; \ + if (!radix_check::is_valid(ch)) \ + break; \ + if (!extractor::call(ch, count, val)) \ + return false; \ + ++it; \ + ++count; \ + /**/ + + template <typename T, unsigned Radix, typename Accumulator, bool Accumulate> + struct extract_int<T, Radix, 1, -1, Accumulator, Accumulate> + { +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + template <typename Iterator, typename Attribute> + inline static bool + parse_main( + Iterator& first + , Iterator const& last + , Attribute& attr) + { + typedef radix_traits<Radix> radix_check; + typedef int_extractor<Radix, Accumulator, -1> extractor; + typedef typename + boost::detail::iterator_traits<Iterator>::value_type + char_type; + + Iterator it = first; + std::size_t count = 0; + if (!Accumulate) + { + // skip leading zeros + while (it != last && *it == '0') + { + ++it; + ++count; + } + + if (it == last) + { + if (count == 0) // must have at least one digit + return false; + attr = 0; + first = it; + return true; + } + } + + typedef typename + traits::attribute_type<Attribute>::type + attribute_type; + + attribute_type val = Accumulate ? attr : attribute_type(0); + char_type ch = *it; + + if (!radix_check::is_valid(ch) || !extractor::call(ch, 0, val)) + { + if (count == 0) // must have at least one digit + return false; + traits::move_to(val, attr); + first = it; + return true; + } + + count = 0; + ++it; + while (true) + { + BOOST_PP_REPEAT( + SPIRIT_NUMERICS_LOOP_UNROLL + , SPIRIT_NUMERIC_INNER_LOOP, _) + } + + traits::move_to(val, attr); + first = it; + return true; + } +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +# pragma warning(pop) +#endif + + template <typename Iterator> + inline static bool + parse( + Iterator& first + , Iterator const& last + , unused_type) + { + T n = 0; // must calculate value to detect over/underflow + return parse_main(first, last, n); + } + + template <typename Iterator, typename Attribute> + inline static bool + parse( + Iterator& first + , Iterator const& last + , Attribute& attr) + { + return parse_main(first, last, attr); + } + }; + +#undef SPIRIT_NUMERIC_INNER_LOOP + + /////////////////////////////////////////////////////////////////////////// + // Cast an signed integer to an unsigned integer + /////////////////////////////////////////////////////////////////////////// + template <typename T, + bool force_unsigned + = mpl::and_<is_integral<T>, is_signed<T> >::value> + struct cast_unsigned; + + template <typename T> + struct cast_unsigned<T, true> + { + typedef typename make_unsigned<T>::type unsigned_type; + typedef typename make_unsigned<T>::type& unsigned_type_ref; + + inline static unsigned_type_ref call(T& n) + { + return unsigned_type_ref(n); + } + }; + + template <typename T> + struct cast_unsigned<T, false> + { + inline static T& call(T& n) + { + return n; + } + }; +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/numeric_utils/extract_int.hpp b/boost/spirit/home/x3/support/numeric_utils/extract_int.hpp new file mode 100644 index 0000000000..aa80cdd6ea --- /dev/null +++ b/boost/spirit/home/x3/support/numeric_utils/extract_int.hpp @@ -0,0 +1,147 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2011 Jan Frederick Eick + + 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_EXTRACT_INT_APRIL_17_2006_0830AM) +#define BOOST_SPIRIT_X3_EXTRACT_INT_APRIL_17_2006_0830AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/traits/move_to.hpp> +#include <boost/spirit/home/x3/support/numeric_utils/detail/extract_int.hpp> +#include <boost/assert.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + /////////////////////////////////////////////////////////////////////////// + // Extract the prefix sign (- or +), return true if a '-' was found + /////////////////////////////////////////////////////////////////////////// + template <typename Iterator> + inline bool + extract_sign(Iterator& first, Iterator const& last) + { + (void)last; // silence unused warnings + BOOST_ASSERT(first != last); // precondition + + // Extract the sign + bool neg = *first == '-'; + if (neg || (*first == '+')) + { + ++first; + return neg; + } + return false; + } + + /////////////////////////////////////////////////////////////////////////// + // Low level unsigned integer parser + /////////////////////////////////////////////////////////////////////////// + template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits + , bool Accumulate = false> + struct extract_uint + { + // check template parameter 'Radix' for validity + static_assert( + (Radix >= 2 && Radix <= 36), + "Error Unsupported Radix"); + + template <typename Iterator> + inline static bool call(Iterator& first, Iterator const& last, T& attr) + { + if (first == last) + return false; + + typedef detail::extract_int< + T + , Radix + , MinDigits + , MaxDigits + , detail::positive_accumulator<Radix> + , Accumulate> + extract_type; + + Iterator save = first; + if (!extract_type::parse(first, last, + detail::cast_unsigned<T>::call(attr))) + { + first = save; + return false; + } + return true; + } + + template <typename Iterator, typename Attribute> + inline static bool call(Iterator& first, Iterator const& last, Attribute& attr_) + { + // this case is called when Attribute is not T + T attr; + if (call(first, last, attr)) + { + traits::move_to(attr, attr_); + return true; + } + return false; + } + }; + + /////////////////////////////////////////////////////////////////////////// + // Low level signed integer parser + /////////////////////////////////////////////////////////////////////////// + template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits> + struct extract_int + { + // check template parameter 'Radix' for validity + static_assert( + (Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16), + "Error Unsupported Radix"); + + template <typename Iterator> + inline static bool call(Iterator& first, Iterator const& last, T& attr) + { + if (first == last) + return false; + + typedef detail::extract_int< + T, Radix, MinDigits, MaxDigits> + extract_pos_type; + + typedef detail::extract_int< + T, Radix, MinDigits, MaxDigits, detail::negative_accumulator<Radix> > + extract_neg_type; + + Iterator save = first; + bool hit = extract_sign(first, last); + if (hit) + hit = extract_neg_type::parse(first, last, attr); + else + hit = extract_pos_type::parse(first, last, attr); + + if (!hit) + { + first = save; + return false; + } + return true; + } + + template <typename Iterator, typename Attribute> + inline static bool call(Iterator& first, Iterator const& last, Attribute& attr_) + { + // this case is called when Attribute is not T + T attr; + if (call(first, last, attr)) + { + traits::move_to(attr, attr_); + return true; + } + return false; + } + }; +}}} + +#endif diff --git a/boost/spirit/home/x3/support/numeric_utils/extract_real.hpp b/boost/spirit/home/x3/support/numeric_utils/extract_real.hpp new file mode 100644 index 0000000000..fb30f02306 --- /dev/null +++ b/boost/spirit/home/x3/support/numeric_utils/extract_real.hpp @@ -0,0 +1,271 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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(SPIRIT_EXTRACT_REAL_APRIL_18_2006_0901AM) +#define SPIRIT_EXTRACT_REAL_APRIL_18_2006_0901AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <cmath> +#include <boost/limits.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/spirit/home/x3/support/unused.hpp> +#include <boost/spirit/home/x3/support/numeric_utils/pow10.hpp> +#include <boost/spirit/home/x3/support/numeric_utils/sign.hpp> +#include <boost/spirit/home/x3/support/traits/move_to.hpp> +#include <boost/assert.hpp> + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +# pragma warning(push) +# pragma warning(disable: 4100) // 'p': unreferenced formal parameter +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost { namespace spirit { namespace x3 { namespace extension +{ + using x3::traits::pow10; + + template <typename T> + inline void + scale(int exp, T& n) + { + if (exp >= 0) + { + // $$$ Why is this failing for boost.math.concepts ? $$$ + //~ int nn = std::numeric_limits<T>::max_exponent10; + //~ BOOST_ASSERT(exp <= std::numeric_limits<T>::max_exponent10); + n *= pow10<T>(exp); + } + else + { + if (exp < std::numeric_limits<T>::min_exponent10) + { + n /= pow10<T>(-std::numeric_limits<T>::min_exponent10); + n /= pow10<T>(-exp + std::numeric_limits<T>::min_exponent10); + } + else + { + n /= pow10<T>(-exp); + } + } + } + + inline void + scale(int /*exp*/, unused_type /*n*/) + { + // no-op for unused_type + } + + template <typename T> + inline void + scale(int exp, int frac, T& n) + { + scale(exp - frac, n); + } + + inline void + scale(int /*exp*/, int /*frac*/, unused_type /*n*/) + { + // no-op for unused_type + } + + inline float + negate(bool neg, float n) + { + return neg ? x3::changesign(n) : n; + } + + inline double + negate(bool neg, double n) + { + return neg ? x3::changesign(n) : n; + } + + inline long double + negate(bool neg, long double n) + { + return neg ? x3::changesign(n) : n; + } + + template <typename T> + inline T + negate(bool neg, T const& n) + { + return neg ? -n : n; + } + + inline unused_type + negate(bool /*neg*/, unused_type n) + { + // no-op for unused_type + return n; + } + + template <typename T> + inline bool + is_equal_to_one(T const& value) + { + return value == 1.0; + } + + inline bool + is_equal_to_one(unused_type) + { + // no-op for unused_type + return false; + } +}}}} + +namespace boost { namespace spirit { namespace x3 +{ + template <typename T, typename RealPolicies> + struct extract_real + { + template <typename Iterator, typename Attribute> + static bool + parse(Iterator& first, Iterator const& last, Attribute& attr, + RealPolicies const& p) + { + if (first == last) + return false; + Iterator save = first; + + // Start by parsing the sign. neg will be true if + // we got a "-" sign, false otherwise. + bool neg = p.parse_sign(first, last); + + // Now attempt to parse an integer + T n = 0; + bool got_a_number = p.parse_n(first, last, n); + + // If we did not get a number it might be a NaN, Inf or a leading + // dot. + if (!got_a_number) + { + // Check whether the number to parse is a NaN or Inf + if (p.parse_nan(first, last, n) || + p.parse_inf(first, last, n)) + { + // If we got a negative sign, negate the number + traits::move_to(extension::negate(neg, n), attr); + return true; // got a NaN or Inf, return early + } + + // If we did not get a number and our policies do not + // allow a leading dot, fail and return early (no-match) + if (!p.allow_leading_dot) + { + first = save; + return false; + } + } + + bool e_hit = false; + int frac_digits = 0; + + // Try to parse the dot ('.' decimal point) + if (p.parse_dot(first, last)) + { + // We got the decimal point. Now we will try to parse + // the fraction if it is there. If not, it defaults + // to zero (0) only if we already got a number. + Iterator savef = first; + if (p.parse_frac_n(first, last, n)) + { + // Optimization note: don't compute frac_digits if T is + // an unused_type. This should be optimized away by the compiler. + if (!is_same<T, unused_type>::value) + frac_digits = + static_cast<int>(std::distance(savef, first)); + } + else if (!got_a_number || !p.allow_trailing_dot) + { + // We did not get a fraction. If we still haven't got a + // number and our policies do not allow a trailing dot, + // return no-match. + first = save; + return false; + } + + // Now, let's see if we can parse the exponent prefix + e_hit = p.parse_exp(first, last); + } + else + { + // No dot and no number! Return no-match. + if (!got_a_number) + { + first = save; + return false; + } + + // If we must expect a dot and we didn't see an exponent + // prefix, return no-match. + e_hit = p.parse_exp(first, last); + if (p.expect_dot && !e_hit) + { + first = save; + return false; + } + } + + if (e_hit) + { + // We got the exponent prefix. Now we will try to parse the + // actual exponent. It is an error if it is not there. + int exp = 0; + if (p.parse_exp_n(first, last, exp)) + { + // Got the exponent value. Scale the number by + // exp-frac_digits. + extension::scale(exp, frac_digits, n); + } + else + { + // Oops, no exponent, return no-match. + first = save; + return false; + } + } + else if (frac_digits) + { + // No exponent found. Scale the number by -frac_digits. + extension::scale(-frac_digits, n); + } + else if (extension::is_equal_to_one(n)) + { + // There is a chance of having to parse one of the 1.0#... + // styles some implementations use for representing NaN or Inf. + + // Check whether the number to parse is a NaN or Inf + if (p.parse_nan(first, last, n) || + p.parse_inf(first, last, n)) + { + // If we got a negative sign, negate the number + traits::move_to(extension::negate(neg, n), attr); + return true; // got a NaN or Inf, return immediately + } + } + + // If we got a negative sign, negate the number + traits::move_to(extension::negate(neg, n), attr); + + // Success!!! + return true; + } + }; + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +# pragma warning(pop) +#endif + +}}} + +#endif diff --git a/boost/spirit/home/x3/support/numeric_utils/pow10.hpp b/boost/spirit/home/x3/support/numeric_utils/pow10.hpp new file mode 100644 index 0000000000..f51d29fba8 --- /dev/null +++ b/boost/spirit/home/x3/support/numeric_utils/pow10.hpp @@ -0,0 +1,116 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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_POW10_DECEMBER_26_2008_1118AM) +#define BOOST_SPIRIT_X3_POW10_DECEMBER_26_2008_1118AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/config/no_tr1/cmath.hpp> +#include <boost/limits.hpp> +#include <boost/spirit/home/x3/support/unused.hpp> +#include <boost/spirit/home/x3/support/traits/numeric_traits.hpp> + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +# pragma warning(push) +# pragma warning(disable: 4244) // conversion from 'double' to 'float', possible loss of data +#endif + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + namespace detail + { + template <typename T, typename Enable = void> + struct pow10_helper + { + static T call(unsigned dim) + { + using namespace std; // allow for ADL to find the correct overload + return pow(T(10), T(dim)); + } + }; + + template <> + struct pow10_helper<unused_type> + { + static unused_type call(unused_type) + { + return unused; + } + }; + +#if (DBL_MAX_10_EXP == 308) // for IEEE-754 + template <> + struct pow10_helper<double> + { + static double call(unsigned dim) + { + static double const exponents[] = + { + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, + 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, + 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, + 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39, + 1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49, + 1e50, 1e51, 1e52, 1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59, + 1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69, + 1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79, + 1e80, 1e81, 1e82, 1e83, 1e84, 1e85, 1e86, 1e87, 1e88, 1e89, + 1e90, 1e91, 1e92, 1e93, 1e94, 1e95, 1e96, 1e97, 1e98, 1e99, + 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109, + 1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119, + 1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129, + 1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139, + 1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149, + 1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159, + 1e160, 1e161, 1e162, 1e163, 1e164, 1e165, 1e166, 1e167, 1e168, 1e169, + 1e170, 1e171, 1e172, 1e173, 1e174, 1e175, 1e176, 1e177, 1e178, 1e179, + 1e180, 1e181, 1e182, 1e183, 1e184, 1e185, 1e186, 1e187, 1e188, 1e189, + 1e190, 1e191, 1e192, 1e193, 1e194, 1e195, 1e196, 1e197, 1e198, 1e199, + 1e200, 1e201, 1e202, 1e203, 1e204, 1e205, 1e206, 1e207, 1e208, 1e209, + 1e210, 1e211, 1e212, 1e213, 1e214, 1e215, 1e216, 1e217, 1e218, 1e219, + 1e220, 1e221, 1e222, 1e223, 1e224, 1e225, 1e226, 1e227, 1e228, 1e229, + 1e230, 1e231, 1e232, 1e233, 1e234, 1e235, 1e236, 1e237, 1e238, 1e239, + 1e240, 1e241, 1e242, 1e243, 1e244, 1e245, 1e246, 1e247, 1e248, 1e249, + 1e250, 1e251, 1e252, 1e253, 1e254, 1e255, 1e256, 1e257, 1e258, 1e259, + 1e260, 1e261, 1e262, 1e263, 1e264, 1e265, 1e266, 1e267, 1e268, 1e269, + 1e270, 1e271, 1e272, 1e273, 1e274, 1e275, 1e276, 1e277, 1e278, 1e279, + 1e280, 1e281, 1e282, 1e283, 1e284, 1e285, 1e286, 1e287, 1e288, 1e289, + 1e290, 1e291, 1e292, 1e293, 1e294, 1e295, 1e296, 1e297, 1e298, 1e299, + 1e300, 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307, 1e308, + }; + BOOST_ASSERT(dim < sizeof(exponents)/sizeof(double)); + return exponents[dim]; + } + }; + + template <> + struct pow10_helper<float> + { + static float call(unsigned dim) + { + return pow10_helper<double>::call(dim); + } + }; +#endif // for IEEE-754 + } + + template <typename T> + inline T pow10(unsigned dim) + { + return detail::pow10_helper<T>::call(dim); + } +}}}} + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +# pragma warning(pop) +#endif + +#endif diff --git a/boost/spirit/home/x3/support/numeric_utils/sign.hpp b/boost/spirit/home/x3/support/numeric_utils/sign.hpp new file mode 100644 index 0000000000..fe2feceeed --- /dev/null +++ b/boost/spirit/home/x3/support/numeric_utils/sign.hpp @@ -0,0 +1,48 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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(SPIRIT_SIGN_MAR_11_2009_0734PM) +#define SPIRIT_SIGN_MAR_11_2009_0734PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/config/no_tr1/cmath.hpp> +#include <boost/math/special_functions/fpclassify.hpp> +#include <boost/math/special_functions/sign.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template<typename T> + inline bool (signbit)(T x) + { + return (boost::math::signbit)(x) ? true : false; + } + + // This routine has been taken and adapted from Johan Rade's fp_traits + // library + template<typename T> + inline T (changesign)(T x) + { +#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY) + return -x; +#else + typedef typename math::detail::fp_traits<T>::type traits_type; + + typename traits_type::bits a; + traits_type::get_bits(x, a); + a ^= traits_type::sign; + traits_type::set_bits(x, a); + return x; +#endif + } + +}}} + +#endif diff --git a/boost/spirit/home/x3/support/subcontext.hpp b/boost/spirit/home/x3/support/subcontext.hpp new file mode 100644 index 0000000000..7614fcbcae --- /dev/null +++ b/boost/spirit/home/x3/support/subcontext.hpp @@ -0,0 +1,89 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2013 Agustín Bergé + http://spirit.sourceforge.net/ + + 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_SUBCONTEXT_APR_15_2013_0840AM) +#define BOOST_SPIRIT_X3_SUBCONTEXT_APR_15_2013_0840AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/fusion/support/pair.hpp> +#include <boost/spirit/home/x3/support/context.hpp> +#include <boost/spirit/home/x3/support/unused.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename... T> + struct subcontext; + + template <> + struct subcontext<> + { + template <typename Context> + subcontext(Context const& /*context*/) + {} + + template <typename ID_, typename Unused = void> + struct get_result + { + typedef unused_type type; + }; + + template <typename ID_> + unused_type + get(ID_) const + { + return unused; + } + }; + + template <typename T> + struct subcontext<T> + : context<typename T::first_type, typename T::second_type> + { + typedef context< + typename T::first_type, typename T::second_type + > context_type; + + template <typename Context> + subcontext(Context const& context) + : context_type(x3::get<typename T::first_type>(context)) + {} + + using context_type::get; + }; + + template <typename T, typename... Tail> + struct subcontext<T, Tail...> + : subcontext<Tail...> + , context< + typename T::first_type, typename T::second_type + , subcontext<Tail...> + > + { + typedef subcontext<Tail...> base_type; + typedef context< + typename T::first_type, typename T::second_type + , base_type + > context_type; + + template <typename Context> + subcontext(Context const& context) + : base_type(context) + , context_type( + x3::get<typename T::first_type>(context) + , *static_cast<base_type*>(this)) + {} + + using context_type::get; + }; + +}}} + +#endif diff --git a/boost/spirit/home/x3/support/traits/attribute_category.hpp b/boost/spirit/home/x3/support/traits/attribute_category.hpp new file mode 100644 index 0000000000..a003327de2 --- /dev/null +++ b/boost/spirit/home/x3/support/traits/attribute_category.hpp @@ -0,0 +1,82 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + http://spirit.sourceforge.net/ + + 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_ATTRIBUTE_CATEGORY_JAN_4_2012_1150AM) +#define BOOST_SPIRIT_X3_ATTRIBUTE_CATEGORY_JAN_4_2012_1150AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/mpl/identity.hpp> +#include <boost/mpl/logical.hpp> +#include <boost/mpl/eval_if.hpp> +#include <boost/fusion/include/copy.hpp> +#include <boost/fusion/include/is_sequence.hpp> +#include <boost/fusion/support/category_of.hpp> +#include <boost/spirit/home/x3/support/traits/is_variant.hpp> +#include <boost/spirit/home/x3/support/traits/container_traits.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + struct unused_type; +}}} + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + struct unused_attribute {}; + struct plain_attribute {}; + struct container_attribute {}; + struct tuple_attribute {}; + struct associative_attribute {}; + struct variant_attribute {}; + struct optional_attribute {}; + + template <typename T, typename Enable = void> + struct attribute_category + : mpl::identity<plain_attribute> {}; + + template <> + struct attribute_category<unused_type> + : mpl::identity<unused_attribute> {}; + + template <> + struct attribute_category<unused_type const> + : mpl::identity<unused_attribute> {}; + + template <typename T> + struct attribute_category< T + , typename enable_if< + typename mpl::eval_if< + fusion::traits::is_sequence<T> + , fusion::traits::is_associative<T> + , mpl::false_ + >::type >::type > + : mpl::identity<associative_attribute> {}; + + template <typename T> + struct attribute_category< T + , typename enable_if< + mpl::and_< + fusion::traits::is_sequence<T> + , mpl::not_<fusion::traits::is_associative<T> > + > >::type > + : mpl::identity<tuple_attribute> {}; + + template <typename T> + struct attribute_category<T, + typename enable_if<traits::is_variant<T>>::type> + : mpl::identity<variant_attribute> {}; + + template <typename T> + struct attribute_category<T, + typename enable_if<traits::is_container<T>>::type> + : mpl::identity<container_attribute> {}; + +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/traits/attribute_of.hpp b/boost/spirit/home/x3/support/traits/attribute_of.hpp new file mode 100644 index 0000000000..71f70b0273 --- /dev/null +++ b/boost/spirit/home/x3/support/traits/attribute_of.hpp @@ -0,0 +1,59 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2013 Agustin Berge + http://spirit.sourceforge.net/ + + 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_ATTRIBUTE_OF_JAN_7_2012_0914AM) +#define BOOST_SPIRIT_X3_ATTRIBUTE_OF_JAN_7_2012_0914AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/utility/sfinae.hpp> +#include <boost/mpl/identity.hpp> +#include <boost/utility/enable_if.hpp> + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + /////////////////////////////////////////////////////////////////////////// + // Get the attribute type of a component. By default, this gets the + // Component's attribute_type typedef or instantiates a nested attribute + // metafunction. Components may specialize this if such an attribute_type + // is not readily available (e.g. expensive to compute at compile time). + /////////////////////////////////////////////////////////////////////////// + template <typename Component, typename Context, typename Enable = void> + struct attribute_of; + + namespace detail + { + template <typename Component, typename Context, typename Enable = void> + struct default_attribute_of; + + template <typename Component, typename Context> + struct default_attribute_of<Component, Context, + typename disable_if_substitution_failure< + typename Component::attribute_type>::type> + : mpl::identity<typename Component::attribute_type> {}; + + template <typename Component, typename Context> + struct default_attribute_of<Component, Context, + typename disable_if_substitution_failure< + typename Component::template attribute<Context>::type>::type> + : Component::template attribute<Context> {}; + + template <typename Component, typename Context> + struct default_attribute_of<Component, Context, + typename enable_if_c<Component::is_pass_through_unary>::type> + : attribute_of<typename Component::subject_type, Context>{}; + } + + template <typename Component, typename Context, typename Enable> + struct attribute_of : detail::default_attribute_of<Component, Context> {}; + +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/traits/attribute_type.hpp b/boost/spirit/home/x3/support/traits/attribute_type.hpp new file mode 100644 index 0000000000..55e788b41c --- /dev/null +++ b/boost/spirit/home/x3/support/traits/attribute_type.hpp @@ -0,0 +1,30 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + http://spirit.sourceforge.net/ + + 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_ATTRIBUTE_TYPE_JAN_5_2012_0358PM) +#define BOOST_SPIRIT_X3_ATTRIBUTE_TYPE_JAN_5_2012_0358PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/mpl/identity.hpp> + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + /////////////////////////////////////////////////////////////////////////// + // Retrieve the attribute type to use from the given type + // + // This is needed to extract the correct attribute type from proxy classes + // as utilized in FUSION_ADAPT_ADT et. al. + /////////////////////////////////////////////////////////////////////////// + template <typename Attribute, typename Enable = void> + struct attribute_type : mpl::identity<Attribute> {}; + +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/traits/container_traits.hpp b/boost/spirit/home/x3/support/traits/container_traits.hpp new file mode 100644 index 0000000000..c382b7bfaa --- /dev/null +++ b/boost/spirit/home/x3/support/traits/container_traits.hpp @@ -0,0 +1,333 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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_CONTAINER_FEBRUARY_06_2007_1001AM) +#define BOOST_SPIRIT_X3_CONTAINER_FEBRUARY_06_2007_1001AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/fusion/support/category_of.hpp> +#include <boost/spirit/home/x3/support/unused.hpp> +#include <boost/detail/iterator.hpp> +#include <boost/fusion/include/deque.hpp> +#include <boost/mpl/has_xxx.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/mpl/identity.hpp> +#include <vector> +#include <string> + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + /////////////////////////////////////////////////////////////////////////// + // This file contains some container utils for stl containers. + /////////////////////////////////////////////////////////////////////////// + + namespace detail + { + BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type) + BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator) + BOOST_MPL_HAS_XXX_TRAIT_DEF(size_type) + BOOST_MPL_HAS_XXX_TRAIT_DEF(reference) + } + + template <typename T, typename Enable = void> + struct is_container + : mpl::bool_< + detail::has_value_type<T>::value && + detail::has_iterator<T>::value && + detail::has_size_type<T>::value && + detail::has_reference<T>::value> + {}; + + /////////////////////////////////////////////////////////////////////////// + namespace detail + { + template <typename T> + struct remove_value_const : mpl::identity<T> {}; + + template <typename T> + struct remove_value_const<T const> : remove_value_const<T> {}; + + template <typename F, typename S> + struct remove_value_const<std::pair<F, S>> + { + typedef typename remove_value_const<F>::type first_type; + typedef typename remove_value_const<S>::type second_type; + typedef std::pair<first_type, second_type> type; + }; + } + + /////////////////////////////////////////////////////////////////////// + template <typename Container, typename Enable = void> + struct container_value + : detail::remove_value_const<typename Container::value_type> + {}; + + template <typename Container> + struct container_value<Container const> : container_value<Container> {}; + + // There is no single container value for fusion maps, but because output + // of this metafunc is used to check wheter parser's attribute can be + // saved to container, we simply return whole fusion::map as is + // so that check can be done in traits::is_substitute specialisation + template <typename T> + struct container_value<T + , typename enable_if<typename mpl::eval_if < + fusion::traits::is_sequence<T> + , fusion::traits::is_associative<T> + , mpl::false_ >::type >::type> + : mpl::identity<T> {}; + + template <> + struct container_value<unused_type> : mpl::identity<unused_type> {}; + + /////////////////////////////////////////////////////////////////////////// + template <typename Container, typename Enable = void> + struct container_iterator + : mpl::identity<typename Container::iterator> {}; + + template <typename Container> + struct container_iterator<Container const> + : mpl::identity<typename Container::const_iterator> {}; + + template <> + struct container_iterator<unused_type> + : mpl::identity<unused_type const*> {}; + + template <> + struct container_iterator<unused_type const> + : mpl::identity<unused_type const*> {}; + + /////////////////////////////////////////////////////////////////////////// + template <typename Container, typename T> + bool push_back(Container& c, T&& val); + + template <typename Container, typename Enable = void> + struct push_back_container + { + template <typename T> + static bool call(Container& c, T&& val) + { + c.insert(c.end(), std::move(val)); + return true; + } + }; + + template <typename Container, typename T> + inline bool push_back(Container& c, T&& val) + { + return push_back_container<Container>::call(c, std::move(val)); + } + + template <typename Container> + inline bool push_back(Container&, unused_type) + { + return true; + } + + template <typename T> + inline bool push_back(unused_type, T const&) + { + return true; + } + + inline bool push_back(unused_type, unused_type) + { + return true; + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Container, typename Iterator> + bool append(Container& c, Iterator first, Iterator last); + + template <typename Container, typename Enable = void> + struct append_container + { + // Not all containers have "reserve" + template <typename Container_> + static void reserve(Container_& c, std::size_t size) {} + + template <typename T> + static void reserve(std::vector<T>& c, std::size_t size) + { + c.reserve(size); + } + + template <typename Iterator> + static bool call(Container& c, Iterator first, Iterator last) + { + reserve(c, c.size() + std::distance(first, last)); + c.insert(c.end(), first, last); + return true; + } + }; + + template <typename Container, typename Iterator> + inline bool append(Container& c, Iterator first, Iterator last) + { + return append_container<Container>::call(c, first, last); + } + + template <typename Iterator> + inline bool append(unused_type, Iterator first, Iterator last) + { + return true; + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Container, typename Enable = void> + struct is_empty_container + { + static bool call(Container const& c) + { + return c.empty(); + } + }; + + template <typename Container> + inline bool is_empty(Container const& c) + { + return is_empty_container<Container>::call(c); + } + + inline bool is_empty(unused_type) + { + return true; + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Container, typename Enable = void> + struct begin_container + { + static typename container_iterator<Container>::type call(Container& c) + { + return c.begin(); + } + }; + + template <typename Container> + inline typename container_iterator<Container>::type + begin(Container& c) + { + return begin_container<Container>::call(c); + } + + inline unused_type const* + begin(unused_type) + { + return &unused; + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Container, typename Enable = void> + struct end_container + { + static typename container_iterator<Container>::type call(Container& c) + { + return c.end(); + } + }; + + template <typename Container> + inline typename container_iterator<Container>::type + end(Container& c) + { + return end_container<Container>::call(c); + } + + inline unused_type const* + end(unused_type) + { + return &unused; + } + + + /////////////////////////////////////////////////////////////////////////// + template <typename Iterator, typename Enable = void> + struct deref_iterator + { + typedef typename boost::detail::iterator_traits<Iterator>::reference type; + static type call(Iterator& it) + { + return *it; + } + }; + + template <typename Iterator> + typename deref_iterator<Iterator>::type + deref(Iterator& it) + { + return deref_iterator<Iterator>::call(it); + } + + inline unused_type + deref(unused_type const*) + { + return unused; + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Iterator, typename Enable = void> + struct next_iterator + { + static void call(Iterator& it) + { + ++it; + } + }; + + template <typename Iterator> + void next(Iterator& it) + { + next_iterator<Iterator>::call(it); + } + + inline void next(unused_type const*) + { + // do nothing + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Iterator, typename Enable = void> + struct compare_iterators + { + static bool call(Iterator const& it1, Iterator const& it2) + { + return it1 == it2; + } + }; + + template <typename Iterator> + bool compare(Iterator& it1, Iterator& it2) + { + return compare_iterators<Iterator>::call(it1, it2); + } + + inline bool compare(unused_type const*, unused_type const*) + { + return false; + } + + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct build_container : mpl::identity<std::vector<T>> {}; + + template <typename T> + struct build_container<boost::fusion::deque<T> > : build_container<T> {}; + + template <> + struct build_container<unused_type> : mpl::identity<unused_type> {}; + + template <> + struct build_container<char> : mpl::identity<std::string> {}; + +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/traits/handles_container.hpp b/boost/spirit/home/x3/support/traits/handles_container.hpp new file mode 100644 index 0000000000..3fe05aef87 --- /dev/null +++ b/boost/spirit/home/x3/support/traits/handles_container.hpp @@ -0,0 +1,31 @@ +/*============================================================================= + Copyright (c) 2001-2011 Hartmut Kaiser + Copyright (c) 2013 Agustin Berge + + 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_HANDLES_CONTAINER_DEC_18_2010_0920AM) +#define BOOST_SPIRIT_X3_HANDLES_CONTAINER_DEC_18_2010_0920AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/mpl/bool.hpp> + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + /////////////////////////////////////////////////////////////////////////// + // Whether a component handles container attributes intrinsically + // (or whether container attributes need to be split up separately). + // By default, this gets the Component's handles_container nested value. + // Components may specialize this if such a handles_container is not + // readily available (e.g. expensive to compute at compile time). + /////////////////////////////////////////////////////////////////////////// + template <typename Component, typename Context, typename Enable = void> + struct handles_container : mpl::bool_<Component::handles_container> {}; + +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/traits/has_attribute.hpp b/boost/spirit/home/x3/support/traits/has_attribute.hpp new file mode 100644 index 0000000000..c8b1f8a347 --- /dev/null +++ b/boost/spirit/home/x3/support/traits/has_attribute.hpp @@ -0,0 +1,63 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2013 Agustin Berge + http://spirit.sourceforge.net/ + + 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_HAS_ATTRIBUTE_JUN_6_2012_1714PM) +#define BOOST_SPIRIT_X3_HAS_ATTRIBUTE_JUN_6_2012_1714PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/traits/attribute_of.hpp> +#include <boost/spirit/home/x3/support/utility/sfinae.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/mpl/not.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/utility/enable_if.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + struct unused_type; +}}} + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + /////////////////////////////////////////////////////////////////////////// + // Whether a component has an attribute. By default, this compares the + // component attribute against unused_type. If the component provides a + // nested constant expression has_attribute as a hint, that value is used + // instead. Components may specialize this. + /////////////////////////////////////////////////////////////////////////// + template <typename Component, typename Context, typename Enable = void> + struct has_attribute; + + namespace detail + { + template <typename Component, typename Context, typename Enable = void> + struct default_has_attribute + : mpl::not_<is_same<unused_type, + typename attribute_of<Component, Context>::type>> {}; + + template <typename Component, typename Context> + struct default_has_attribute<Component, Context, + typename disable_if_substitution_failure< + mpl::bool_<Component::has_attribute>>::type> + : mpl::bool_<Component::has_attribute> {}; + + template <typename Component, typename Context> + struct default_has_attribute<Component, Context, + typename enable_if_c<Component::is_pass_through_unary>::type> + : has_attribute<typename Component::subject_type, Context> {}; + } + + template <typename Component, typename Context, typename Enable> + struct has_attribute : detail::default_has_attribute<Component, Context> {}; + +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/traits/is_parser.hpp b/boost/spirit/home/x3/support/traits/is_parser.hpp new file mode 100644 index 0000000000..cfbe8f74b4 --- /dev/null +++ b/boost/spirit/home/x3/support/traits/is_parser.hpp @@ -0,0 +1,37 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2014 Agustin Berge + + 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_IS_PARSER_MAY_20_2013_0235PM) +#define BOOST_SPIRIT_X3_IS_PARSER_MAY_20_2013_0235PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/mpl/bool.hpp> +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/support/utility/sfinae.hpp> + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + /////////////////////////////////////////////////////////////////////////// + // is_parser<T>: metafunction that evaluates to mpl::true_ if a type T + // can be used as a parser, mpl::false_ otherwise + /////////////////////////////////////////////////////////////////////////// + template <typename T, typename Enable = void> + struct is_parser + : mpl::false_ + {}; + + template <typename T> + struct is_parser<T, typename disable_if_substitution_failure< + typename extension::as_parser<T>::type>::type> + : mpl::true_ + {}; +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/traits/is_substitute.hpp b/boost/spirit/home/x3/support/traits/is_substitute.hpp new file mode 100644 index 0000000000..9e023371ce --- /dev/null +++ b/boost/spirit/home/x3/support/traits/is_substitute.hpp @@ -0,0 +1,164 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + http://spirit.sourceforge.net/ + + 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_IS_SUBSTITUTE_JAN_9_2012_1049PM) +#define BOOST_SPIRIT_X3_IS_SUBSTITUTE_JAN_9_2012_1049PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/traits/container_traits.hpp> +#include <boost/fusion/include/is_sequence.hpp> +#include <boost/fusion/include/map.hpp> +#include <boost/fusion/include/value_at_key.hpp> +#include <boost/fusion/adapted/mpl.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/mpl/equal.hpp> +#include <boost/mpl/apply.hpp> +#include <boost/mpl/filter_view.hpp> +#include <boost/mpl/size.hpp> +#include <boost/mpl/logical.hpp> +#include <boost/mpl/at.hpp> +#include <boost/mpl/count_if.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/optional/optional.hpp> +#include <boost/type_traits/is_same.hpp> + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + /////////////////////////////////////////////////////////////////////////// + // Find out if T can be a (strong) substitute for Attribute + /////////////////////////////////////////////////////////////////////////// + template <typename T, typename Attribute, typename Enable = void> + struct is_substitute; + + template <typename Variant, typename Attribute> + struct variant_has_substitute; + + namespace detail + { + template <typename T, typename Attribute> + struct value_type_is_substitute + : is_substitute< + typename container_value<T>::type + , typename container_value<Attribute>::type> + {}; + + template <typename T, typename Attribute, typename Enable = void> + struct is_substitute_impl : is_same<T, Attribute> {}; + + template <typename T, typename Attribute> + struct is_substitute_impl<T, Attribute, + typename enable_if< + mpl::and_< + fusion::traits::is_sequence<T>, + fusion::traits::is_sequence<Attribute>, + mpl::equal<T, Attribute, is_substitute<mpl::_1, mpl::_2>> + > + >::type> + : mpl::true_ {}; + + template <typename T, typename Attribute> + struct is_substitute_impl<T, Attribute, + typename enable_if< + mpl::and_< + is_container<T>, + is_container<Attribute>, + value_type_is_substitute<T, Attribute> + > + >::type> + : mpl::true_ {}; + + template <typename T, typename Attribute> + struct is_substitute_impl<T, Attribute, + typename enable_if< + is_variant<Attribute> + >::type> + : mpl::or_< + is_same<T, Attribute> + , variant_has_substitute<Attribute, T> + > + {}; + } + + template <typename T, typename Attribute, typename Enable /*= void*/> + struct is_substitute + : detail::is_substitute_impl<T, Attribute> {}; + + // for reference T + template <typename T, typename Attribute, typename Enable> + struct is_substitute<T&, Attribute, Enable> + : is_substitute<T, Attribute, Enable> {}; + + // for reference Attribute + template <typename T, typename Attribute, typename Enable> + struct is_substitute<T, Attribute&, Enable> + : is_substitute<T, Attribute, Enable> {}; + + // 2 element mpl tuple is compatible with fusion::map if: + // - it's first element type is existing key in map + // - it second element type is compatible to type stored at the key in map + template <typename T, typename Attribute> + struct is_substitute<T, Attribute + , typename enable_if< + typename mpl::eval_if< + mpl::and_<fusion::traits::is_sequence<T> + , fusion::traits::is_sequence<Attribute>> + , mpl::and_<traits::has_size<T, 2> + , fusion::traits::is_associative<Attribute>> + , mpl::false_>::type>::type> + + { + // checking that "p_key >> p_value" parser can + // store it's result in fusion::map attribute + typedef typename mpl::at_c<T, 0>::type p_key; + typedef typename mpl::at_c<T, 1>::type p_value; + + // for simple p_key type we just check that + // such key can be found in attr and that value under that key + // matches p_value + template <typename Key, typename Value, typename Map> + struct has_kv_in_map + : mpl::eval_if< + fusion::result_of::has_key<Map, Key> + , mpl::apply< + is_substitute< + fusion::result_of::value_at_key<mpl::_1, Key> + , Value> + , Map> + , mpl::false_> + {}; + + // if p_key is variant over multiple types (as a result of + // "(key1|key2|key3) >> p_value" parser) check that all + // keys are found in fusion::map attribute and that values + // under these keys match p_value + template <typename Variant> + struct variant_kv + : mpl::equal_to< + mpl::size< typename Variant::types> + , mpl::size< mpl::filter_view<typename Variant::types + , has_kv_in_map<mpl::_1, p_value, Attribute>>> + > + {}; + + typedef typename + mpl::eval_if< + is_variant<p_key> + , variant_kv<p_key> + , has_kv_in_map<p_key, p_value, Attribute> + >::type + type; + }; + + template <typename T, typename Attribute> + struct is_substitute<optional<T>, optional<Attribute>> + : is_substitute<T, Attribute> {}; +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/traits/is_variant.hpp b/boost/spirit/home/x3/support/traits/is_variant.hpp new file mode 100644 index 0000000000..829a673c3f --- /dev/null +++ b/boost/spirit/home/x3/support/traits/is_variant.hpp @@ -0,0 +1,45 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + http://spirit.sourceforge.net/ + + 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_IS_VARIANT_JAN_10_2012_0823AM) +#define BOOST_SPIRIT_X3_IS_VARIANT_JAN_10_2012_0823AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/variant.hpp> +#include <boost/mpl/has_xxx.hpp> +#include <boost/mpl/bool.hpp> + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + namespace detail + { + // By declaring a nested struct in your class/struct, you tell + // spirit that it is regarded as a variant type. The minimum + // required interface for such a variant is that it has constructors + // for various types supported by your variant and a typedef 'types' + // which is an mpl sequence of the contained types. + // + // This is an intrusive interface. For a non-intrusive interface, + // use the is_variant trait. + BOOST_MPL_HAS_XXX_TRAIT_DEF(adapted_variant_tag) + } + + template <typename T, typename Enable = void> + struct is_variant + : detail::has_adapted_variant_tag<T> + {}; + + template <BOOST_VARIANT_ENUM_PARAMS(typename T)> + struct is_variant<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>> + : mpl::true_ + {}; +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/traits/make_attribute.hpp b/boost/spirit/home/x3/support/traits/make_attribute.hpp new file mode 100644 index 0000000000..cf3baeedaf --- /dev/null +++ b/boost/spirit/home/x3/support/traits/make_attribute.hpp @@ -0,0 +1,86 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2001-2012 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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_MAKE_ATTRIBUTE_JAN_8_2012_0721PM) +#define BOOST_SPIRIT_X3_MAKE_ATTRIBUTE_JAN_8_2012_0721PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/mpl/if.hpp> +#include <boost/type_traits/remove_const.hpp> +#include <boost/type_traits/add_reference.hpp> +#include <boost/spirit/home/x3/support/unused.hpp> + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + template <typename Attribute> + struct make_attribute_base + { + static Attribute call(unused_type) + { + // synthesize the attribute/parameter + return Attribute(); + } + + template <typename T> + static T& call(T& value) + { + return value; // just pass the one provided + } + }; + + template <typename Attribute, typename ActualAttribute> + struct make_attribute : make_attribute_base<Attribute> + { + typedef ActualAttribute& type; + typedef ActualAttribute value_type; + }; + + template <typename Attribute> + struct make_attribute<Attribute, unused_type> + : make_attribute_base<Attribute> + { + typedef typename remove_const<Attribute>::type attribute_type; + typedef attribute_type type; + typedef attribute_type value_type; + }; + + template <typename Attribute, typename ActualAttribute> + struct make_attribute<Attribute&, ActualAttribute> + : make_attribute<Attribute, ActualAttribute> {}; + + template <typename Attribute, typename ActualAttribute> + struct make_attribute<Attribute const&, ActualAttribute> + : make_attribute<Attribute const, ActualAttribute> {}; + + template <typename ActualAttribute> + struct make_attribute<unused_type, ActualAttribute> + { + typedef unused_type type; + typedef unused_type value_type; + static unused_type call(unused_type) + { + return unused; + } + }; + + template <> + struct make_attribute<unused_type, unused_type> + { + typedef unused_type type; + typedef unused_type value_type; + static unused_type call(unused_type) + { + return unused; + } + }; +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/traits/move_to.hpp b/boost/spirit/home/x3/support/traits/move_to.hpp new file mode 100644 index 0000000000..ecd7c6f202 --- /dev/null +++ b/boost/spirit/home/x3/support/traits/move_to.hpp @@ -0,0 +1,211 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2013 Agustin Berge + http://spirit.sourceforge.net/ + + 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_MOVE_TO_JAN_17_2013_0859PM) +#define BOOST_SPIRIT_X3_MOVE_TO_JAN_17_2013_0859PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/traits/attribute_category.hpp> +#include <boost/spirit/home/x3/support/traits/tuple_traits.hpp> +#include <boost/spirit/home/x3/support/traits/variant_has_substitute.hpp> +#include <boost/fusion/include/is_sequence.hpp> +#include <boost/fusion/include/front.hpp> +#include <boost/fusion/include/size.hpp> +#include <boost/fusion/include/move.hpp> +#include <boost/fusion/include/is_sequence.hpp> +#include <boost/range/iterator_range.hpp> +#include <utility> + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + template <typename Source, typename Dest> + void move_to(Source&& src, Dest& dest); + + template <typename Dest> + inline void move_to(unused_type, Dest&) {} + + template <typename Source> + inline void move_to(Source&, unused_type) {} + + inline void move_to(unused_type, unused_type) {} + + template <typename Iterator, typename Dest> + void + move_to(Iterator first, Iterator last, Dest& dest); + + template <typename Iterator> + inline void + move_to(Iterator, Iterator, unused_type) {} + + namespace detail + { + template <typename Source, typename Dest> + inline void + move_to(Source&&, Dest&, unused_attribute) {} + + template <typename Source, typename Dest> + inline void + move_to_plain(Source&& src, Dest& dest, mpl::false_) // src is not a single-element tuple + { + dest = std::move(src); + } + + template <typename Source, typename Dest> + inline void + move_to_plain(Source&& src, Dest& dest, mpl::true_) // src is a single-element tuple + { + dest = std::move(fusion::front(src)); + } + + template <typename Source, typename Dest> + inline void + move_to(Source&& src, Dest& dest, plain_attribute) + { + typename mpl::and_< + fusion::traits::is_sequence<Source>, + is_size_one_sequence<Source> > + is_single_element_sequence; + + move_to_plain(std::move(src), dest, is_single_element_sequence); + } + + template <typename Source, typename Dest> + inline typename enable_if<is_container<Source>>::type + move_to(Source&& src, Dest& dest, container_attribute) + { + traits::move_to(src.begin(), src.end(), dest); + } + + template <typename Source, typename Dest> + inline typename enable_if< + mpl::and_< + is_same_size_sequence<Dest, Source>, + mpl::not_<is_size_one_sequence<Dest> > > + >::type + move_to(Source&& src, Dest& dest, tuple_attribute) + { + fusion::move(std::move(src), dest); + } + + template <typename Source, typename Dest> + inline typename enable_if< + is_size_one_sequence<Dest> + >::type + move_to(Source&& src, Dest& dest, tuple_attribute) + { + traits::move_to(src, fusion::front(dest)); + } + + template <typename Source, typename Dest> + inline void + move_to(Source&& src, Dest& dest, variant_attribute, mpl::false_) + { + dest = std::move(src); + } + + template <typename Source, typename Dest> + inline void + move_to_variant_from_single_element_sequence(Source&& src, Dest& dest, mpl::false_) + { + // dest is a variant, src is a single element fusion sequence that the variant + // cannot directly hold. We'll try to unwrap the single element fusion sequence. + + // Make sure that the Dest variant can really hold Source + static_assert(variant_has_substitute<Dest, typename fusion::result_of::front<Source>::type>::value, + "Error! The destination variant (Dest) cannot hold the source type (Source)"); + + dest = std::move(fusion::front(src)); + } + + template <typename Source, typename Dest> + inline void + move_to_variant_from_single_element_sequence(Source&& src, Dest& dest, mpl::true_) + { + // dest is a variant, src is a single element fusion sequence that the variant + // *can* directly hold. + dest = std::move(src); + } + + template <typename Source, typename Dest> + inline void + move_to(Source&& src, Dest& dest, variant_attribute, mpl::true_) + { + move_to_variant_from_single_element_sequence(src, dest, variant_has_substitute<Dest, Source>()); + } + + template <typename Source, typename Dest> + inline void + move_to(Source&& src, Dest& dest, variant_attribute tag) + { + move_to(src, dest, tag, is_size_one_sequence<Source>()); + } + + template <typename Iterator> + inline void + move_to(Iterator, Iterator, unused_type, unused_attribute) {} + + template <typename Iterator, typename Dest> + inline void + move_to(Iterator first, Iterator last, Dest& dest, container_attribute) + { + if (is_empty(dest)) + dest = Dest(first, last); + else + append(dest, first, last); + } + + template <typename Iterator> + inline void + move_to(Iterator first, Iterator last, boost::iterator_range<Iterator>& rng, container_attribute) + { + rng = {first, last}; + } + } + + template <typename Source, typename Dest> + inline void + move_to(Source&& src, Dest& dest) + { + detail::move_to(std::move(src), dest + , typename attribute_category<Dest>::type()); + } + + template <typename T> + inline void move_to(T& src, T& dest) + { + if (&src != &dest) + dest = std::move(src); + } + + template <typename T> + inline void move_to(T const& src, T& dest) + { + if (&src != &dest) + dest = std::move(src); + } + + template <typename T> + inline void move_to(T&& src, T& dest) + { + if (&src != &dest) + dest = std::move(src); + } + + template <typename Iterator, typename Dest> + inline void + move_to(Iterator first, Iterator last, Dest& dest) + { + // $$$ Use std::move_iterator when iterator is not a const-iterator $$$ + detail::move_to(first, last, dest, typename attribute_category<Dest>::type()); + } +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/traits/numeric_traits.hpp b/boost/spirit/home/x3/support/traits/numeric_traits.hpp new file mode 100644 index 0000000000..3cdbdaec63 --- /dev/null +++ b/boost/spirit/home/x3/support/traits/numeric_traits.hpp @@ -0,0 +1,128 @@ +/*============================================================================= + 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_X3_NUMERIC_TRAITS_JAN_07_2011_0722AM) +#define BOOST_SPIRIT_X3_NUMERIC_TRAITS_JAN_07_2011_0722AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/config.hpp> +#include <boost/integer_traits.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/utility/enable_if.hpp> + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + /////////////////////////////////////////////////////////////////////////// + // Determine if T is a boolean type + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct is_bool : mpl::false_ {}; + + template <typename T> + struct is_bool<T const> : is_bool<T> {}; + + template <> + struct is_bool<bool> : mpl::true_ {}; + + /////////////////////////////////////////////////////////////////////////// + // Determine if T is a signed integer type + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct is_int : mpl::false_ {}; + + template <typename T> + struct is_int<T const> : is_int<T> {}; + + template <> + struct is_int<short> : mpl::true_ {}; + + template <> + struct is_int<int> : mpl::true_ {}; + + template <> + struct is_int<long> : mpl::true_ {}; + +#ifdef BOOST_HAS_LONG_LONG + template <> + struct is_int<boost::long_long_type> : mpl::true_ {}; +#endif + + /////////////////////////////////////////////////////////////////////////// + // Determine if T is an unsigned integer type + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct is_uint : mpl::false_ {}; + + template <typename T> + struct is_uint<T const> : is_uint<T> {}; + +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) + template <> + struct is_uint<unsigned short> : mpl::true_ {}; +#endif + + template <> + struct is_uint<unsigned int> : mpl::true_ {}; + + template <> + struct is_uint<unsigned long> : mpl::true_ {}; + +#ifdef BOOST_HAS_LONG_LONG + template <> + struct is_uint<boost::ulong_long_type> : mpl::true_ {}; +#endif + + /////////////////////////////////////////////////////////////////////////// + // Determine if T is a floating point type + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct is_real : mpl::false_ {}; + + template <typename T> + struct is_real<T const> : is_uint<T> {}; + + template <> + struct is_real<float> : mpl::true_ {}; + + template <> + struct is_real<double> : mpl::true_ {}; + + template <> + struct is_real<long double> : mpl::true_ {}; + + /////////////////////////////////////////////////////////////////////////// + // customization points for numeric operations + /////////////////////////////////////////////////////////////////////////// + template <typename T, typename Enable = void> + struct absolute_value; + + template <typename T, typename Enable = void> + struct is_negative; + + template <typename T, typename Enable = void> + struct is_zero; + + template <typename T, typename Enable = void> + struct pow10_helper; + + template <typename T, typename Enable = void> + struct is_nan; + + template <typename T, typename Enable = void> + struct is_infinite; + + template <typename T, typename Enable = void> + struct check_overflow : mpl::false_ {}; + + template <typename T> + struct check_overflow<T, typename enable_if_c<integer_traits<T>::is_integral>::type> + : mpl::true_ {}; +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/traits/optional_traits.hpp b/boost/spirit/home/x3/support/traits/optional_traits.hpp new file mode 100644 index 0000000000..65568b0265 --- /dev/null +++ b/boost/spirit/home/x3/support/traits/optional_traits.hpp @@ -0,0 +1,78 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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_OPTIONAL_TRAITS_FEBRUARY_06_2007_1001AM) +#define BOOST_SPIRIT_X3_OPTIONAL_TRAITS_FEBRUARY_06_2007_1001AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/unused.hpp> +#include <boost/optional/optional.hpp> +#include <boost/mpl/identity.hpp> + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + /////////////////////////////////////////////////////////////////////////// + template <typename T, typename Enable = void> + struct is_optional + : mpl::false_ + {}; + + template <typename T> + struct is_optional<boost::optional<T>> + : mpl::true_ + {}; + + /////////////////////////////////////////////////////////////////////////// + // build_optional + // + // Build a boost::optional from T. Return unused_type if T is unused_type. + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct build_optional + { + typedef boost::optional<T> type; + }; + + template <typename T> + struct build_optional<boost::optional<T> > + { + typedef boost::optional<T> type; + }; + + template <> + struct build_optional<unused_type> + { + typedef unused_type type; + }; + + /////////////////////////////////////////////////////////////////////////// + // optional_value + // + // Get the optional's value_type. Handles unused_type as well. + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct optional_value : mpl::identity<T> {}; + + template <typename T> + struct optional_value<boost::optional<T> > + : mpl::identity<T> {}; + + template <> + struct optional_value<unused_type> + : mpl::identity<unused_type> {}; + + template <> + struct optional_value<unused_type const> + : mpl::identity<unused_type> {}; + +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/traits/print_attribute.hpp b/boost/spirit/home/x3/support/traits/print_attribute.hpp new file mode 100644 index 0000000000..47bffce1a1 --- /dev/null +++ b/boost/spirit/home/x3/support/traits/print_attribute.hpp @@ -0,0 +1,150 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + 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_X3_PRINT_ATTRIBUTE_JANUARY_20_2013_0814AM) +#define BOOST_SPIRIT_X3_PRINT_ATTRIBUTE_JANUARY_20_2013_0814AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/variant.hpp> +#include <boost/optional/optional.hpp> +#include <boost/fusion/include/is_sequence.hpp> +#include <boost/fusion/include/for_each.hpp> +#include <boost/spirit/home/x3/support/traits/attribute_category.hpp> +#include <boost/spirit/home/x3/support/traits/is_variant.hpp> + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + template <typename Out, typename T> + void print_attribute(Out& out, T const& val); + + template <typename Out> + inline void print_attribute(Out&, unused_type) {} + + /////////////////////////////////////////////////////////////////////////// + namespace detail + { + template <typename Out> + struct print_fusion_sequence + { + print_fusion_sequence(Out& out) + : out(out), is_first(true) {} + + typedef void result_type; + + template <typename T> + void operator()(T const& val) const + { + if (is_first) + is_first = false; + else + out << ", "; + x3::traits::print_attribute(out, val); + } + + Out& out; + mutable bool is_first; + }; + + // print elements in a variant + template <typename Out> + struct print_visitor : static_visitor<> + { + print_visitor(Out& out) : out(out) {} + + template <typename T> + void operator()(T const& val) const + { + x3::traits::print_attribute(out, val); + } + + Out& out; + }; + } + + template <typename Out, typename T, typename Enable = void> + struct print_attribute_debug + { + // for plain data types + template <typename T_> + static void call(Out& out, T_ const& val, unused_attribute) + { + out << "unused"; + } + + // for plain data types + template <typename T_> + static void call(Out& out, T_ const& val, plain_attribute) + { + out << val; + } + + // for fusion data types + template <typename T_> + static void call(Out& out, T_ const& val, tuple_attribute) + { + out << '['; + fusion::for_each(val, detail::print_fusion_sequence<Out>(out)); + out << ']'; + } + + // stl container + template <typename T_> + static void call(Out& out, T_ const& val, container_attribute) + { + out << '['; + if (!traits::is_empty(val)) + { + bool first = true; + typename container_iterator<T_ const>::type iend = traits::end(val); + for (typename container_iterator<T_ const>::type i = traits::begin(val); + !traits::compare(i, iend); traits::next(i)) + { + if (!first) + out << ", "; + first = false; + x3::traits::print_attribute(out, traits::deref(i)); + } + } + out << ']'; + } + + // for variant types + template <typename T_> + static void call(Out& out, T_ const& val, variant_attribute) + { + apply_visitor(detail::print_visitor<Out>(out), val); + } + + // for optional types + template <typename T_> + static void call(Out& out, T_ const& val, optional_attribute) + { + if (val) + x3::traits::print_attribute(out, *val); + else + out << "[empty]"; + } + + // main entry point + static void call(Out& out, T const& val) + { + call(out, val, typename attribute_category<T>::type()); + } + }; + + /////////////////////////////////////////////////////////////////////////// + template <typename Out, typename T> + inline void print_attribute(Out& out, T const& val) + { + print_attribute_debug<Out, T>::call(out, val); + } +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/traits/print_token.hpp b/boost/spirit/home/x3/support/traits/print_token.hpp new file mode 100644 index 0000000000..f1429f4776 --- /dev/null +++ b/boost/spirit/home/x3/support/traits/print_token.hpp @@ -0,0 +1,79 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + 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_X3_PRINT_TOKEN_JANUARY_20_2013_0814AM) +#define BOOST_SPIRIT_X3_PRINT_TOKEN_JANUARY_20_2013_0814AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/mpl/if.hpp> +#include <boost/mpl/and.hpp> +#include <boost/type_traits/is_convertible.hpp> +#include <cctype> + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + /////////////////////////////////////////////////////////////////////////// + // generate debug output for lookahead token (character) stream + namespace detail + { + struct token_printer_debug_for_chars + { + template<typename Out, typename Char> + static void print(Out& o, Char c) + { + using namespace std; // allow for ADL to find the proper iscntrl + + switch (c) + { + case '\a': o << "\\a"; break; + case '\b': o << "\\b"; break; + case '\f': o << "\\f"; break; + case '\n': o << "\\n"; break; + case '\r': o << "\\r"; break; + case '\t': o << "\\t"; break; + case '\v': o << "\\v"; break; + default: + if (c >= 0 && c < 127 && iscntrl(c)) + o << "\\" << std::oct << int(c); + else + o << Char(c); + } + } + }; + + // for token types where the comparison with char constants wouldn't work + struct token_printer_debug + { + template<typename Out, typename T> + static void print(Out& o, T const& val) + { + o << val; + } + }; + } + + template <typename T, typename Enable = void> + struct token_printer_debug + : mpl::if_< + mpl::and_< + is_convertible<T, char>, is_convertible<char, T> > + , detail::token_printer_debug_for_chars + , detail::token_printer_debug>::type + {}; + + template <typename Out, typename T> + inline void print_token(Out& out, T const& val) + { + // allow to customize the token printer routine + token_printer_debug<T>::print(out, val); + } +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/traits/string_traits.hpp b/boost/spirit/home/x3/support/traits/string_traits.hpp new file mode 100644 index 0000000000..46ee356cdc --- /dev/null +++ b/boost/spirit/home/x3/support/traits/string_traits.hpp @@ -0,0 +1,291 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + Copyright (c) 2010 Bryce Lelbach + + 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_STRING_TRAITS_OCTOBER_2008_1252PM) +#define BOOST_SPIRIT_X3_STRING_TRAITS_OCTOBER_2008_1252PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <string> +#include <boost/mpl/bool.hpp> +#include <boost/mpl/identity.hpp> + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + /////////////////////////////////////////////////////////////////////////// + // Determine if T is a character type + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct is_char : mpl::false_ {}; + + template <typename T> + struct is_char<T const> : is_char<T> {}; + + template <> + struct is_char<char> : mpl::true_ {}; + + template <> + struct is_char<wchar_t> : mpl::true_ {}; + + /////////////////////////////////////////////////////////////////////////// + // Determine if T is a string + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct is_string : mpl::false_ {}; + + template <typename T> + struct is_string<T const> : is_string<T> {}; + + template <> + struct is_string<char const*> : mpl::true_ {}; + + template <> + struct is_string<wchar_t const*> : mpl::true_ {}; + + template <> + struct is_string<char*> : mpl::true_ {}; + + template <> + struct is_string<wchar_t*> : mpl::true_ {}; + + template <std::size_t N> + struct is_string<char[N]> : mpl::true_ {}; + + template <std::size_t N> + struct is_string<wchar_t[N]> : mpl::true_ {}; + + template <std::size_t N> + struct is_string<char const[N]> : mpl::true_ {}; + + template <std::size_t N> + struct is_string<wchar_t const[N]> : mpl::true_ {}; + + template <std::size_t N> + struct is_string<char(&)[N]> : mpl::true_ {}; + + template <std::size_t N> + struct is_string<wchar_t(&)[N]> : mpl::true_ {}; + + template <std::size_t N> + struct is_string<char const(&)[N]> : mpl::true_ {}; + + template <std::size_t N> + struct is_string<wchar_t const(&)[N]> : mpl::true_ {}; + + template <typename T, typename Traits, typename Allocator> + struct is_string<std::basic_string<T, Traits, Allocator> > : mpl::true_ {}; + + /////////////////////////////////////////////////////////////////////////// + // Get the underlying char type of a string + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct char_type_of; + + template <typename T> + struct char_type_of<T const> : char_type_of<T> {}; + + template <> + struct char_type_of<char> : mpl::identity<char> {}; + + template <> + struct char_type_of<wchar_t> : mpl::identity<wchar_t> {}; + + template <> + struct char_type_of<char const*> : mpl::identity<char const> {}; + + template <> + struct char_type_of<wchar_t const*> : mpl::identity<wchar_t const> {}; + + template <> + struct char_type_of<char*> : mpl::identity<char> {}; + + template <> + struct char_type_of<wchar_t*> : mpl::identity<wchar_t> {}; + + template <std::size_t N> + struct char_type_of<char[N]> : mpl::identity<char> {}; + + template <std::size_t N> + struct char_type_of<wchar_t[N]> : mpl::identity<wchar_t> {}; + + template <std::size_t N> + struct char_type_of<char const[N]> : mpl::identity<char const> {}; + + template <std::size_t N> + struct char_type_of<wchar_t const[N]> : mpl::identity<wchar_t const> {}; + + template <std::size_t N> + struct char_type_of<char(&)[N]> : mpl::identity<char> {}; + + template <std::size_t N> + struct char_type_of<wchar_t(&)[N]> : mpl::identity<wchar_t> {}; + + template <std::size_t N> + struct char_type_of<char const(&)[N]> : mpl::identity<char const> {}; + + template <std::size_t N> + struct char_type_of<wchar_t const(&)[N]> : mpl::identity<wchar_t const> {}; + + template <typename T, typename Traits, typename Allocator> + struct char_type_of<std::basic_string<T, Traits, Allocator> > + : mpl::identity<T> {}; + + /////////////////////////////////////////////////////////////////////////// + // Get the C string from a string + /////////////////////////////////////////////////////////////////////////// + template <typename String> + struct extract_c_string; + + template <typename String> + struct extract_c_string + { + typedef typename char_type_of<String>::type char_type; + + template <typename T> + static T const* call (T* str) + { + return (T const*)str; + } + + template <typename T> + static T const* call (T const* str) + { + return str; + } + }; + + // Forwarder that strips const + template <typename T> + struct extract_c_string<T const> + { + typedef typename extract_c_string<T>::char_type char_type; + + static typename extract_c_string<T>::char_type const* call (T const str) + { + return extract_c_string<T>::call(str); + } + }; + + // Forwarder that strips references + template <typename T> + struct extract_c_string<T&> + { + typedef typename extract_c_string<T>::char_type char_type; + + static typename extract_c_string<T>::char_type const* call (T& str) + { + return extract_c_string<T>::call(str); + } + }; + + // Forwarder that strips const references + template <typename T> + struct extract_c_string<T const&> + { + typedef typename extract_c_string<T>::char_type char_type; + + static typename extract_c_string<T>::char_type const* call (T const& str) + { + return extract_c_string<T>::call(str); + } + }; + + template <typename T, typename Traits, typename Allocator> + struct extract_c_string<std::basic_string<T, Traits, Allocator> > + { + typedef T char_type; + + typedef std::basic_string<T, Traits, Allocator> string; + + static T const* call (string const& str) + { + return str.c_str(); + } + }; + + template <typename T> + typename extract_c_string<T*>::char_type const* + get_c_string(T* str) + { + return extract_c_string<T*>::call(str); + } + + template <typename T> + typename extract_c_string<T const*>::char_type const* + get_c_string(T const* str) + { + return extract_c_string<T const*>::call(str); + } + + template <typename String> + typename extract_c_string<String>::char_type const* + get_c_string(String& str) + { + return extract_c_string<String>::call(str); + } + + template <typename String> + typename extract_c_string<String>::char_type const* + get_c_string(String const& str) + { + return extract_c_string<String>::call(str); + } + + /////////////////////////////////////////////////////////////////////////// + // Get the begin/end iterators from a string + /////////////////////////////////////////////////////////////////////////// + + // Implementation for C-style strings. + + template <typename T> + inline T const* get_string_begin(T const* str) { return str; } + + template <typename T> + inline T* get_string_begin(T* str) { return str; } + + template <typename T> + inline T const* get_string_end(T const* str) + { + T const* last = str; + while (*last) + last++; + return last; + } + + template <typename T> + inline T* get_string_end(T* str) + { + T* last = str; + while (*last) + last++; + return last; + } + + // Implementation for containers (includes basic_string). + template <typename T, typename Str> + inline typename Str::const_iterator get_string_begin(Str const& str) + { return str.begin(); } + + template <typename T, typename Str> + inline typename Str::iterator + get_string_begin(Str& str) + { return str.begin(); } + + template <typename T, typename Str> + inline typename Str::const_iterator get_string_end(Str const& str) + { return str.end(); } + + template <typename T, typename Str> + inline typename Str::iterator + get_string_end(Str& str) + { return str.end(); } +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/traits/transform_attribute.hpp b/boost/spirit/home/x3/support/traits/transform_attribute.hpp new file mode 100644 index 0000000000..24268520d7 --- /dev/null +++ b/boost/spirit/home/x3/support/traits/transform_attribute.hpp @@ -0,0 +1,48 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2001-2012 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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_ATTRIBUTE_TRANSFORM_JAN_8_2012_0721PM) +#define BOOST_SPIRIT_X3_ATTRIBUTE_TRANSFORM_JAN_8_2012_0721PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/mpl/identity.hpp> + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + /////////////////////////////////////////////////////////////////////////// + // transform_attribute + // + // Sometimes the user needs to transform the attribute types for certain + // attributes. This template can be used as a customization point, where + // the user is able specify specific transformation rules for any attribute + // type. + /////////////////////////////////////////////////////////////////////////// + template <typename Exposed, typename Transformed, typename Tag + , typename Enable = void> + struct transform_attribute; + + /////////////////////////////////////////////////////////////////////////// + template <typename Tag, typename Transformed, typename Exposed> + typename transform_attribute<Exposed, Transformed, Tag>::type + pre_transform(Exposed& attr) + { + return transform_attribute<Exposed, Transformed, Tag>::pre(attr); + } + + template <typename Tag, typename Transformed, typename Exposed> + typename transform_attribute<Exposed, Transformed, Tag>::type + pre_transform(Exposed const& attr) + { + return transform_attribute<Exposed const, Transformed, Tag>::pre(attr); + } +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/traits/tuple_traits.hpp b/boost/spirit/home/x3/support/traits/tuple_traits.hpp new file mode 100644 index 0000000000..17bfd4e1cb --- /dev/null +++ b/boost/spirit/home/x3/support/traits/tuple_traits.hpp @@ -0,0 +1,52 @@ +/*============================================================================= + Copyright (c) 2001-2014 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_X3_TUPLE_TRAITS_JANUARY_2012_1132PM) +#define BOOST_SPIRIT_X3_TUPLE_TRAITS_JANUARY_2012_1132PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/fusion/include/is_sequence.hpp> +#include <boost/fusion/include/size.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/mpl/and.hpp> + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + template <typename A, typename B> + struct has_same_size + : mpl::bool_<( + fusion::result_of::size<A>::value == + fusion::result_of::size<B>::value + )> + {}; + + template <typename T, std::size_t N> + struct has_size + : mpl::bool_<(fusion::result_of::size<T>::value == N)> + {}; + + template <typename A, typename B> + struct is_same_size_sequence + : mpl::and_< + fusion::traits::is_sequence<A> + , fusion::traits::is_sequence<B> + , has_same_size<A, B> + > + {}; + + template <typename Seq> + struct is_size_one_sequence + : mpl::and_< + fusion::traits::is_sequence<Seq> + , has_size<Seq, 1> + > + {}; +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/traits/value_traits.hpp b/boost/spirit/home/x3/support/traits/value_traits.hpp new file mode 100644 index 0000000000..5f004c957c --- /dev/null +++ b/boost/spirit/home/x3/support/traits/value_traits.hpp @@ -0,0 +1,30 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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_VALUE_TRAITS_MAY_07_2013_0203PM) +#define BOOST_SPIRIT_X3_VALUE_TRAITS_MAY_07_2013_0203PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/utility/value_init.hpp> + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + template <typename T, typename Enable = void> + struct value_initialize + { + static T call() + { + return boost::value_initialized<T>(); + } + }; +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/traits/variant_find_substitute.hpp b/boost/spirit/home/x3/support/traits/variant_find_substitute.hpp new file mode 100644 index 0000000000..4de7b7d5e3 --- /dev/null +++ b/boost/spirit/home/x3/support/traits/variant_find_substitute.hpp @@ -0,0 +1,56 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + http://spirit.sourceforge.net/ + + 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_VARIANT_FIND_SUBSTITUTE_APR_18_2014_930AM) +#define BOOST_SPIRIT_X3_VARIANT_FIND_SUBSTITUTE_APR_18_2014_930AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/traits/is_substitute.hpp> + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + template <typename Variant, typename Attribute> + struct variant_find_substitute + { + // Get the type from the variant that can be a substitute for Attribute. + // If none is found, just return Attribute + + typedef Variant variant_type; + typedef typename variant_type::types types; + typedef typename mpl::end<types>::type end; + + typedef typename + mpl::find_if<types, is_same<mpl::_1, Attribute> >::type + iter_1; + + typedef typename + mpl::eval_if< + is_same<iter_1, end>, + mpl::find_if<types, traits::is_substitute<mpl::_1, Attribute> >, + mpl::identity<iter_1> + >::type + iter; + + typedef typename + mpl::eval_if< + is_same<iter, end>, + mpl::identity<Attribute>, + mpl::deref<iter> + >::type + type; + }; + + template <typename Variant> + struct variant_find_substitute<Variant, Variant> + : mpl::identity<Variant> {}; + +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/traits/variant_has_substitute.hpp b/boost/spirit/home/x3/support/traits/variant_has_substitute.hpp new file mode 100644 index 0000000000..d0dfb49b8d --- /dev/null +++ b/boost/spirit/home/x3/support/traits/variant_has_substitute.hpp @@ -0,0 +1,56 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + http://spirit.sourceforge.net/ + + 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_VARIANT_HAS_SUBSTITUTE_APR_18_2014_925AM) +#define BOOST_SPIRIT_X3_VARIANT_HAS_SUBSTITUTE_APR_18_2014_925AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/traits/is_substitute.hpp> + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + template <typename Variant, typename Attribute> + struct variant_has_substitute_impl + { + // Find a type from the variant that can be a substitute for Attribute. + // return true_ if one is found, else false_ + + typedef Variant variant_type; + typedef typename variant_type::types types; + typedef typename mpl::end<types>::type end; + + typedef typename + mpl::find_if<types, is_same<mpl::_1, Attribute>>::type + iter_1; + + typedef typename + mpl::eval_if< + is_same<iter_1, end>, + mpl::find_if<types, traits::is_substitute<mpl::_1, Attribute>>, + mpl::identity<iter_1> + >::type + iter; + + typedef mpl::not_<is_same<iter, end>> type; + }; + + template <typename Variant, typename Attribute> + struct variant_has_substitute + : variant_has_substitute_impl<Variant, Attribute>::type {}; + + template <typename Attribute> + struct variant_has_substitute<unused_type, Attribute> : mpl::true_ {}; + + template <typename Attribute> + struct variant_has_substitute<unused_type const, Attribute> : mpl::true_ {}; + +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/unused.hpp b/boost/spirit/home/x3/support/unused.hpp new file mode 100644 index 0000000000..cf42d13098 --- /dev/null +++ b/boost/spirit/home/x3/support/unused.hpp @@ -0,0 +1,93 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + 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_X3_UNUSED_APRIL_16_2006_0616PM) +#define BOOST_SPIRIT_X3_UNUSED_APRIL_16_2006_0616PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <ostream> +#include <istream> +#include <boost/mpl/identity.hpp> + +#if defined(BOOST_MSVC) +# pragma warning(push) +# pragma warning(disable: 4522) // multiple assignment operators specified warning +#endif + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { namespace x3 +{ + struct unused_type + { + unused_type() + { + } + + template <typename T> + unused_type(T const&) + { + } + + template <typename T> + unused_type const& + operator=(T const&) const + { + return *this; + } + + template <typename T> + unused_type& + operator=(T const&) + { + return *this; + } + + unused_type const& + operator=(unused_type const&) const + { + return *this; + } + + unused_type& + operator=(unused_type const&) + { + return *this; + } + + // unused_type can also masquerade as an empty context (see context.hpp) + + template <typename ID> + struct get_result : mpl::identity<unused_type> {}; + + template <typename ID> + unused_type get(ID) const + { + return unused_type(); + } + }; + + unused_type const unused = unused_type(); + + inline std::ostream& operator<<(std::ostream& out, unused_type const&) + { + return out; + } + + inline std::istream& operator>>(std::istream& in, unused_type&) + { + return in; + } +}}} + +#if defined(BOOST_MSVC) +# pragma warning(pop) +#endif + +#endif diff --git a/boost/spirit/home/x3/support/utility/detail/testing.hpp b/boost/spirit/home/x3/support/utility/detail/testing.hpp new file mode 100644 index 0000000000..1423d9fc7b --- /dev/null +++ b/boost/spirit/home/x3/support/utility/detail/testing.hpp @@ -0,0 +1,16 @@ +/*============================================================================= + Copyright (c) 2014 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_X3_DETAIL_TESTING_JUNE_05_2014_00422PM) +#define BOOST_SPIRIT_X3_DETAIL_TESTING_JUNE_05_2014_00422PM + +namespace boost { namespace spirit { namespace x3 { namespace testing +{ + + +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/utility/error_reporting.hpp b/boost/spirit/home/x3/support/utility/error_reporting.hpp new file mode 100644 index 0000000000..9e65f2149b --- /dev/null +++ b/boost/spirit/home/x3/support/utility/error_reporting.hpp @@ -0,0 +1,241 @@ +/*============================================================================= + Copyright (c) 2014 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_X3_ERROR_REPORTING_MAY_19_2014_00405PM) +#define BOOST_SPIRIT_X3_ERROR_REPORTING_MAY_19_2014_00405PM + +#include <boost/filesystem/path.hpp> +#include <boost/spirit/home/x3/support/ast/position_tagged.hpp> +#include <ostream> + +// Clang-style error handling utilities + +namespace boost { namespace spirit { namespace x3 +{ + template <typename Iterator> + class error_handler + { + public: + + typedef Iterator iterator_type; + + error_handler( + Iterator first, Iterator last, std::ostream& err_out + , std::string file = "", int tabs = 4) + : err_out(err_out) + , file(file) + , tabs(tabs) + , pos_cache(first, last) {} + + typedef void result_type; + + void operator()(Iterator err_pos, std::string const& error_message) const; + void operator()(Iterator err_first, Iterator err_last, std::string const& error_message) const; + void operator()(position_tagged pos, std::string const& message) const + { + auto where = pos_cache.position_of(pos); + (*this)( + where.begin() + , where.end() + , message + ); + } + + template <typename AST> + void tag(AST& ast, Iterator first, Iterator last) + { + return pos_cache.annotate(ast, first, last); + } +// +// void operator()( +// Iterator first +// , Iterator last +// , Iterator err_op +// , Iterator err_first +// , Iterator err_last +// , std::string const& error_message +// ) const; + + private: + + void print_file_line(std::size_t line) const; + void print_line(Iterator& line_start, Iterator last) const; + void print_indicator(Iterator& line_start, Iterator last, char ind) const; + void skip_whitespace(Iterator& err_pos, Iterator last) const; + void skip_non_whitespace(Iterator& err_pos, Iterator last) const; + Iterator get_line_start(Iterator first, Iterator pos) const; + std::size_t position(Iterator i) const; + + std::ostream& err_out; + std::string file; + int tabs; + position_cache<std::vector<Iterator>> pos_cache; + }; + + template <typename Iterator> + void error_handler<Iterator>::print_file_line(std::size_t line) const + { + namespace fs = boost::filesystem; + + if (file != "") + err_out << "In file " << fs::path(file).generic_string() << ", "; + else + err_out << "In "; + + err_out << "line " << line << ':' << std::endl; + } + + template <typename Iterator> + void error_handler<Iterator>::print_line(Iterator& start, Iterator last) const + { + for (; start != last; ++start) + { + auto c = *start; + if (c == '\r' || c == '\n') + break; + else + err_out << c; + } + err_out << std::endl; + } + + template <typename Iterator> + void error_handler<Iterator>::print_indicator(Iterator& start, Iterator last, char ind) const + { + for (; start != last; ++start) + { + auto c = *start; + if (c == '\r' || c == '\n') + break; + else if (c == '\t') + for (int i = 0; i < tabs; ++i) + err_out << ind; + else + err_out << ind; + } + } + + template <typename Iterator> + void error_handler<Iterator>::skip_whitespace(Iterator& err_pos, Iterator last) const + { + // make sure err_pos does not point to white space + while (err_pos != last) + { + char c = *err_pos; + if (std::isspace(c)) + ++err_pos; + else + break; + } + } + + template <typename Iterator> + void error_handler<Iterator>::skip_non_whitespace(Iterator& err_pos, Iterator last) const + { + // make sure err_pos does not point to white space + while (err_pos != last) + { + char c = *err_pos; + if (std::isspace(c)) + break; + else + ++err_pos; + } + } + + template <class Iterator> + inline Iterator error_handler<Iterator>::get_line_start(Iterator first, Iterator pos) const + { + Iterator latest = first; + for (Iterator i = first; i != pos; ++i) + if (*i == '\r' || *i == '\n') + latest = i; + return latest; + } + + template <typename Iterator> + std::size_t error_handler<Iterator>::position(Iterator i) const + { + // $$$ asumes iterator is similar to line_pos_iterator $$$ + return i.position(); + } + + template <typename Iterator> + void error_handler<Iterator>::operator()( + Iterator err_pos, std::string const& error_message) const + { + Iterator first = pos_cache.first(); + Iterator last = pos_cache.last(); + + // make sure err_pos does not point to white space + skip_whitespace(err_pos, last); + + print_file_line(position(err_pos)); + err_out << error_message << std::endl; + + Iterator start = get_line_start(first, err_pos); + if (start != first) + ++start; + Iterator i = start; + print_line(i, last); + print_indicator(start, err_pos, '_'); + err_out << "^_" << std::endl; + } + + template <typename Iterator> + void error_handler<Iterator>::operator()( + Iterator err_first, Iterator err_last, std::string const& error_message) const + { + Iterator first = pos_cache.first(); + Iterator last = pos_cache.last(); + + // make sure err_pos does not point to white space + skip_whitespace(err_first, last); + + print_file_line(position(err_first)); + err_out << error_message << std::endl; + + Iterator start = get_line_start(first, err_first); + if (start != first) + ++start; + Iterator i = start; + print_line(i, last); + print_indicator(start, err_first, ' '); + print_indicator(start, err_last, '~'); + err_out << " <<-- Here" << std::endl; + } +// +// template <typename Iterator> +// void error_handler<Iterator>::operator()( +// Iterator first +// , Iterator last +// , Iterator err_op +// , Iterator err_first +// , Iterator err_last +// , std::string const& error_message +// ) const +// { +// // make sure err_pos does not point to white space +// skip_whitespace(err_first, last); +// +// print_file_line(position(err_pos)); +// err_out << error_message << std::endl; +// +// Iterator start = get_line_start(first, err_first); +// if (start != first) +// ++start; +// Iterator i = start; +// print_line(i, last); +// print_indicator(start, err_first, ' '); +// print_indicator(start, err_op, '~'); +// err_out << '^'; +// print_indicator(++start, err_last, '~'); +// err_out << " <<-- Here" << std::endl; +// } + +}}} + +#endif diff --git a/boost/spirit/home/x3/support/utility/integer_sequence.hpp b/boost/spirit/home/x3/support/utility/integer_sequence.hpp new file mode 100644 index 0000000000..1f0bace72b --- /dev/null +++ b/boost/spirit/home/x3/support/utility/integer_sequence.hpp @@ -0,0 +1,94 @@ +/*////////////////////////////////////////////////////////////////////////////// + Copyright (c) 2014 Jamboree + + 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) +//////////////////////////////////////////////////////////////////////////////*/ +#ifndef BOOST_SPIRIT_X3_INTEGER_SEQUENCE_HPP_INCLUDED +#define BOOST_SPIRIT_X3_INTEGER_SEQUENCE_HPP_INCLUDED + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <cstddef> +#include <boost/type_traits/integral_constant.hpp> + +// This is a standard (c++1y) compatible integer_sequence implementation, +// it's needed for now, and it could be replaced with std::integer_sequence +// once the new standard is available everywhere. + +namespace boost { namespace spirit { namespace x3 +{ + template <typename T, T... Ns> + struct integer_sequence + { + typedef T value_type; + + static constexpr std::size_t size() noexcept + { + return sizeof...(Ns); + } + }; +}}} + +namespace boost { namespace spirit { namespace x3 { namespace detail +{ + template <typename T, typename S1, typename S2, T N> + struct accum_integer_sequence; + + template <typename T, T... N1, T... N2, T N> + struct accum_integer_sequence<T, integer_sequence<T, N1...>, integer_sequence<T, N2...>, N> + { + typedef integer_sequence<T, N1..., (N + N2)...> type; + }; + + template <typename N> + struct make_integer_sequence_impl + { + typedef typename N::value_type T; + static T const n = N::value; + static T const m = n / 2; + typedef typename + make_integer_sequence_impl<integral_constant<T, m>>::type + part1; + typedef typename + make_integer_sequence_impl<integral_constant<T, n - m>>::type + part2; + typedef typename + accum_integer_sequence<T, part1, part2, m>::type + type; + }; + + template <typename T> + struct make_integer_sequence_impl<integral_constant<T, 0>> + { + typedef integer_sequence<T> type; + }; + + template <typename T> + struct make_integer_sequence_impl<integral_constant<T, 1>> + { + typedef integer_sequence<T, 0> type; + }; +}}}} + +namespace boost { namespace spirit { namespace x3 +{ + template <std::size_t... Ns> + using index_sequence = integer_sequence<std::size_t, Ns...>; + + template <typename T, T N> + using make_integer_sequence = typename detail::make_integer_sequence_impl< + integral_constant<T, N>>::type; + + template <std::size_t N> + using make_index_sequence = make_integer_sequence<std::size_t, N>; + + template <typename... T> + using index_sequence_for = make_index_sequence<sizeof...(T)>; +}}} + + +#endif + diff --git a/boost/spirit/home/x3/support/utility/is_callable.hpp b/boost/spirit/home/x3/support/utility/is_callable.hpp new file mode 100644 index 0000000000..17f86822b8 --- /dev/null +++ b/boost/spirit/home/x3/support/utility/is_callable.hpp @@ -0,0 +1,45 @@ +/*////////////////////////////////////////////////////////////////////////////// + Copyright (c) 2014 Jamboree + + 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) +//////////////////////////////////////////////////////////////////////////////*/ +#ifndef BOOST_SPIRIT_X3_IS_CALLABLE_HPP_INCLUDED +#define BOOST_SPIRIT_X3_IS_CALLABLE_HPP_INCLUDED + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/utility/result_of.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/spirit/home/x3/support/utility/sfinae.hpp> + + +namespace boost { namespace spirit { namespace x3 { namespace detail +{ + template <typename Sig, typename Enable = void> + struct is_callable_impl + : mpl::false_ + {}; + + template <typename F, typename... A> + struct is_callable_impl<F(A...), typename disable_if_substitution_failure< + typename result_of<F(A...)>::type>::type> + : mpl::true_ + {}; +}}}} + +namespace boost { namespace spirit { namespace x3 +{ + template <typename Sig> + struct is_callable; + + template <typename F, typename... A> + struct is_callable<F(A...)> + : detail::is_callable_impl<F(A...)> + {}; +}}} + + +#endif diff --git a/boost/spirit/home/x3/support/utility/lambda_visitor.hpp b/boost/spirit/home/x3/support/utility/lambda_visitor.hpp new file mode 100644 index 0000000000..83e1d2f046 --- /dev/null +++ b/boost/spirit/home/x3/support/utility/lambda_visitor.hpp @@ -0,0 +1,49 @@ +/*============================================================================= + Copyright (c) 2014 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_X3_LAMBDA_VISITOR_MAY_19_2014_1116AM) +#define BOOST_SPIRIT_X3_LAMBDA_VISITOR_MAY_19_2014_1116AM + +namespace boost { namespace spirit { namespace x3 +{ + template <typename RT, typename... Lambdas> + struct lambda_visitor; + + template <typename RT, typename F, typename... Lambdas> + struct lambda_visitor<RT, F, Lambdas...> : F, lambda_visitor<RT, Lambdas...> + { + typedef lambda_visitor<RT , Lambdas...> base_type; + using F::operator(); + using base_type::operator(); + lambda_visitor(F f, Lambdas... lambdas) + : F(f), base_type(lambdas...) + {} + }; + + template <typename RT, typename F> + struct lambda_visitor<RT, F> : F + { + typedef RT result_type; + using F::operator(); + lambda_visitor(F f) + : F(f) + {} + }; + + template <typename RT> + struct lambda_visitor<RT> + { + typedef RT result_type; + }; + + template <typename RT, typename... Lambdas> + lambda_visitor<RT, Lambdas...> make_lambda_visitor(Lambdas... lambdas) + { + return { lambdas... }; + } +}}} + +#endif diff --git a/boost/spirit/home/x3/support/utility/sfinae.hpp b/boost/spirit/home/x3/support/utility/sfinae.hpp new file mode 100644 index 0000000000..6cefa95961 --- /dev/null +++ b/boost/spirit/home/x3/support/utility/sfinae.hpp @@ -0,0 +1,29 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2013 Agustin Berge + + 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_SFINAE_MAY_20_2013_0840AM) +#define BOOST_SPIRIT_X3_SFINAE_MAY_20_2013_0840AM + +#if defined(_MSC_VER) +#pragma once +#endif + +namespace boost { namespace spirit { namespace x3 +{ + template <typename Expr, typename T = void> + struct disable_if_substitution_failure + { + typedef T type; + }; + template <typename Expr, typename T> + struct lazy_disable_if_substitution_failure + { + typedef typename T::type type; + }; +}}} + +#endif diff --git a/boost/spirit/home/x3/support/utility/testing.hpp b/boost/spirit/home/x3/support/utility/testing.hpp new file mode 100644 index 0000000000..fced46bef8 --- /dev/null +++ b/boost/spirit/home/x3/support/utility/testing.hpp @@ -0,0 +1,69 @@ +/*============================================================================= + Copyright (c) 2014 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_X3_TESTING_JUNE_05_2014_00422PM) +#define BOOST_SPIRIT_X3_TESTING_JUNE_05_2014_00422PM + +namespace boost { namespace spirit { namespace x3 { namespace testing +{ + //////////////////////////////////////////////////////////////////////////// + // + // Test utility + // + // The test function accepts a file loaded in memory. The 'test_file' + // range param points to the data contained in the file. This file + // contains two parts. + // + // 1) The source input for testing + // 2) The expected result. + // + // The first part of the file is sent to the generator function + // 'gen' which returns a string. This generated string is then compared + // to the contents of the second (expected result) part. + // + // The second part is demarcated by the string parameter 'demarcation' + // which defaults to "<**expected**>". The expected template may include + // embedded regular expressions marked-up within re_prefix and re_suffix + // parameter tags. For example, given the default RE markup ("<%" and + // "%>"), this template: + // + // <%[0-9]+%> + // + // will match any integer in the source input being tested. The function + // will return the first non-matching position. The flag full_match + // indicates a full match. It is possible for returned pos to be + // at the end of in (in.end()) while still returning full_match == + // false. In that case, we have a partial match. + // + // Here's an example of a test file: + // + // Hello World, I am Joel. This is a test. + // + // <**expected**> + // Hello World, I am <%[a-zA-Z]+%>. This is a test. + // + //////////////////////////////////////////////////////////////////////////// + + template <typename Iterator> + struct test_result + { + Iterator pos; + bool full_match; + }; + + template <typename Range, typename F> + test_result<typename Range::const_iterator> + test( + Range test_file + , F gen + , char const* demarcation = "<**expected**>" + , char const* re_prefix = "<%" + , char const* re_suffix = "%>" + ); + +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/utility/unrefcv.hpp b/boost/spirit/home/x3/support/utility/unrefcv.hpp new file mode 100644 index 0000000000..fa4d448178 --- /dev/null +++ b/boost/spirit/home/x3/support/utility/unrefcv.hpp @@ -0,0 +1,29 @@ +/*////////////////////////////////////////////////////////////////////////////// + Copyright (c) 2014 Jamboree + + 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) +//////////////////////////////////////////////////////////////////////////////*/ +#ifndef BOOST_SPIRIT_X3_UNREFCV_HPP_INCLUDED +#define BOOST_SPIRIT_X3_UNREFCV_HPP_INCLUDED + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> + + +namespace boost { namespace spirit { namespace x3 +{ + template <typename T> + struct unrefcv : remove_cv<typename remove_reference<T>::type> {}; + + template <typename T> + using unrefcv_t = typename unrefcv<T>::type; +}}} + + +#endif + diff --git a/boost/spirit/home/x3/support/utility/utf8.hpp b/boost/spirit/home/x3/support/utility/utf8.hpp new file mode 100644 index 0000000000..93b5a22077 --- /dev/null +++ b/boost/spirit/home/x3/support/utility/utf8.hpp @@ -0,0 +1,72 @@ +/*============================================================================= + Copyright (c) 2001-2014 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_X3_UC_TYPES_NOVEMBER_23_2008_0840PM) +#define BOOST_SPIRIT_X3_UC_TYPES_NOVEMBER_23_2008_0840PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/cstdint.hpp> +#include <boost/foreach.hpp> +#include <boost/regex/pending/unicode_iterator.hpp> +#include <boost/type_traits/make_unsigned.hpp> +#include <string> + +namespace boost { namespace spirit { namespace x3 +{ + typedef ::boost::uint32_t ucs4_char; + typedef char utf8_char; + typedef std::basic_string<ucs4_char> ucs4_string; + typedef std::basic_string<utf8_char> utf8_string; + + template <typename Char> + inline utf8_string to_utf8(Char value) + { + // always store as UTF8 + utf8_string result; + typedef std::back_insert_iterator<utf8_string> insert_iter; + insert_iter out_iter(result); + utf8_output_iterator<insert_iter> utf8_iter(out_iter); + typedef typename make_unsigned<Char>::type UChar; + *utf8_iter = (UChar)value; + return result; + } + + template <typename Char> + inline utf8_string to_utf8(Char const* str) + { + // always store as UTF8 + utf8_string result; + typedef std::back_insert_iterator<utf8_string> insert_iter; + insert_iter out_iter(result); + utf8_output_iterator<insert_iter> utf8_iter(out_iter); + typedef typename make_unsigned<Char>::type UChar; + while (*str) + *utf8_iter++ = (UChar)*str++; + return result; + } + + template <typename Char, typename Traits, typename Allocator> + inline utf8_string + to_utf8(std::basic_string<Char, Traits, Allocator> const& str) + { + // always store as UTF8 + utf8_string result; + typedef std::back_insert_iterator<utf8_string> insert_iter; + insert_iter out_iter(result); + utf8_output_iterator<insert_iter> utf8_iter(out_iter); + typedef typename make_unsigned<Char>::type UChar; + BOOST_FOREACH(Char ch, str) + { + *utf8_iter++ = (UChar)ch; + } + return result; + } +}}} + +#endif |