diff options
Diffstat (limited to 'boost/spirit/home/x3')
106 files changed, 12037 insertions, 0 deletions
diff --git a/boost/spirit/home/x3/auxiliary.hpp b/boost/spirit/home/x3/auxiliary.hpp new file mode 100644 index 0000000000..afa89b2883 --- /dev/null +++ b/boost/spirit/home/x3/auxiliary.hpp @@ -0,0 +1,24 @@ +/*============================================================================= + 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_AUXILIARY_FEBRUARY_03_2007_0355PM) +#define BOOST_SPIRIT_X3_AUXILIARY_FEBRUARY_03_2007_0355PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/auxiliary/any_parser.hpp> +#include <boost/spirit/home/x3/auxiliary/eps.hpp> +#include <boost/spirit/home/x3/auxiliary/guard.hpp> +//~ #include <boost/spirit/home/x3/auxiliary/lazy.hpp> +#include <boost/spirit/home/x3/auxiliary/eol.hpp> +#include <boost/spirit/home/x3/auxiliary/eoi.hpp> +#include <boost/spirit/home/x3/auxiliary/attr.hpp> +//~ #include <boost/spirit/home/x3/auxiliary/attr_cast.hpp> + +#endif diff --git a/boost/spirit/home/x3/auxiliary/any_parser.hpp b/boost/spirit/home/x3/auxiliary/any_parser.hpp new file mode 100644 index 0000000000..0e257c04b1 --- /dev/null +++ b/boost/spirit/home/x3/auxiliary/any_parser.hpp @@ -0,0 +1,155 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2013-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_AUXILIARY_ANY_PARSER_APR_09_2014_1145PM) +#define BOOST_SPIRIT_X3_AUXILIARY_ANY_PARSER_APR_09_2014_1145PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/support/context.hpp> +#include <boost/spirit/home/x3/support/subcontext.hpp> +#include <boost/spirit/home/x3/support/unused.hpp> +#include <boost/spirit/home/x3/support/traits/container_traits.hpp> +#include <boost/spirit/home/x3/support/traits/has_attribute.hpp> +#include <boost/spirit/home/x3/support/traits/move_to.hpp> +#include <boost/spirit/home/x3/support/traits/is_parser.hpp> +#include <memory> +#include <string> + +namespace boost { namespace spirit { namespace x3 +{ + template < + typename Iterator + , typename Attribute = unused_type + , typename Context = subcontext<>> + struct any_parser : parser<any_parser<Iterator, Attribute, Context>> + { + typedef Attribute attribute_type; + + static bool const has_attribute = + !is_same<unused_type, attribute_type>::value; + static bool const handles_container = + traits::is_container<Attribute>::value; + + public: + any_parser() + : _content(nullptr) {} + + template <typename Expr, + typename Enable = typename enable_if<traits::is_parser<Expr>>::type> + any_parser(Expr const& expr) + : _content(new holder<Expr>(expr)) {} + + any_parser(any_parser const& other) + : _content(other._content ? other._content->clone() : nullptr) {} + + any_parser(any_parser&& other) = default; + + any_parser& operator=(any_parser const& other) + { + _content.reset(other._content ? other._content->clone() : nullptr); + return *this; + } + + any_parser& operator=(any_parser&& other) = default; + + template <typename Iterator_, typename Context_> + bool parse(Iterator_& first, Iterator_ const& last + , Context_ const& context, unused_type, Attribute& attr) const + { + BOOST_STATIC_ASSERT_MSG( + (is_same<Iterator, Iterator_>::value) + , "Incompatible iterator used" + ); + + BOOST_ASSERT_MSG( + (_content != nullptr) + , "Invalid use of uninitialized any_parser" + ); + + return _content->parse(first, last, context, attr); + } + + template <typename Iterator_, typename Context_, typename Attribute_> + bool parse(Iterator_& first, Iterator_ const& last + , Context_ const& context, unused_type, Attribute_& attr_) const + { + Attribute attr; + if (parse(first, last, context, unused, attr)) + { + traits::move_to(attr, attr_); + return true; + } + return false; + } + + std::string get_info() const + { + return _content ? _content->get_info() : ""; + } + + private: + + struct placeholder + { + virtual placeholder* clone() const = 0; + + virtual bool parse(Iterator& first, Iterator const& last + , Context const& context, Attribute& attr) const = 0; + + virtual std::string get_info() const = 0; + + virtual ~placeholder() {} + }; + + template <typename Expr> + struct holder : placeholder + { + typedef typename extension::as_parser<Expr>::value_type parser_type; + + explicit holder(Expr const& p) + : _parser(as_parser(p)) {} + + holder* clone() const override + { + return new holder(*this); + } + + bool parse(Iterator& first, Iterator const& last + , Context const& context, Attribute& attr) const override + { + return _parser.parse(first, last, context, unused, attr); + } + + std::string get_info() const override + { + return x3::what(_parser); + } + + parser_type _parser; + }; + + private: + std::unique_ptr<placeholder> _content; + }; + + template <typename Iterator, typename Attribute, typename Context> + struct get_info<any_parser<Iterator, Attribute, Context>> + { + typedef std::string result_type; + std::string operator()( + any_parser<Iterator, Attribute, Context> const& p) const + { + return p.get_info(); + } + }; +}}} + +#endif diff --git a/boost/spirit/home/x3/auxiliary/attr.hpp b/boost/spirit/home/x3/auxiliary/attr.hpp new file mode 100644 index 0000000000..364cca0bee --- /dev/null +++ b/boost/spirit/home/x3/auxiliary/attr.hpp @@ -0,0 +1,135 @@ +/*============================================================================= + Copyright (c) 2001-2011 Hartmut Kaiser + 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) +==============================================================================*/ +#ifndef BOOST_SPIRIT_X3_ATTR_JUL_23_2008_0956AM +#define BOOST_SPIRIT_X3_ATTR_JUL_23_2008_0956AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/support/unused.hpp> +#include <boost/spirit/home/x3/support/traits/container_traits.hpp> +#include <boost/spirit/home/x3/support/traits/move_to.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <algorithm> +#include <cstddef> +#include <string> +#include <utility> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename Value> + struct attr_parser : parser<attr_parser<Value>> + { + typedef Value attribute_type; + + static bool const has_attribute = + !is_same<unused_type, attribute_type>::value; + static bool const handles_container = + traits::is_container<attribute_type>::value; + + attr_parser(Value const& value) + : value_(value) {} + attr_parser(Value&& value) + : value_(std::move(value)) {} + + template <typename Iterator, typename Context + , typename RuleContext, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, RuleContext&, Attribute& attr_) const + { + // $$$ Change to copy_to once we have it $$$ + traits::move_to(value_, attr_); + return true; + } + + Value value_; + + private: + // silence MSVC warning C4512: assignment operator could not be generated + attr_parser& operator= (attr_parser const&); + }; + + template <typename Value, std::size_t N> + struct attr_parser<Value[N]> : parser<attr_parser<Value[N]>> + { + typedef Value attribute_type[N]; + + static bool const has_attribute = + !is_same<unused_type, attribute_type>::value; + static bool const handles_container = true; + + attr_parser(Value const (&value)[N]) + { + std::copy(value + 0, value + N, value_ + 0); + } + + attr_parser(Value (&&value)[N]) + { + std::move(value + 0, value + N, value_ + 0); + } + + template <typename Iterator, typename Context + , typename RuleContext, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, RuleContext&, Attribute& attr_) const + { + // $$$ Change to copy_to once we have it $$$ + traits::move_to(value_ + 0, value_ + N, attr_); + return true; + } + + Value value_[N]; + + private: + // silence MSVC warning C4512: assignment operator could not be generated + attr_parser& operator= (attr_parser const&); + }; + + template <typename Value> + struct get_info<attr_parser<Value>> + { + typedef std::string result_type; + std::string operator()(attr_parser<Value> const& /*p*/) const + { + return "attr"; + } + }; + + struct attr_gen + { + template <typename Value> + attr_parser<typename remove_cv< + typename remove_reference<Value>::type>::type> + operator()(Value&& value) const + { + return {std::forward<Value>(value)}; + } + + template <typename Value, std::size_t N> + attr_parser<typename remove_cv<Value>::type[N]> + operator()(Value (&value)[N]) const + { + return {value}; + } + template <typename Value, std::size_t N> + attr_parser<typename remove_cv<Value>::type[N]> + operator()(Value (&&value)[N]) const + { + return {value}; + } + }; + + attr_gen const attr = attr_gen(); +}}} + +#endif diff --git a/boost/spirit/home/x3/auxiliary/eoi.hpp b/boost/spirit/home/x3/auxiliary/eoi.hpp new file mode 100644 index 0000000000..55bd51cfc4 --- /dev/null +++ b/boost/spirit/home/x3/auxiliary/eoi.hpp @@ -0,0 +1,45 @@ +/*============================================================================= + 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_EOI_MARCH_23_2007_0454PM) +#define BOOST_SPIRIT_X3_EOI_MARCH_23_2007_0454PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/core/skip_over.hpp> +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/support/unused.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + struct eoi_parser : parser<eoi_parser> + { + typedef unused_type attribute_type; + static bool const has_attribute = false; + + template <typename Iterator, typename Context, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, unused_type, Attribute&) const + { + x3::skip_over(first, last, context); + return first == last; + } + }; + + template<> + struct get_info<eoi_parser> + { + typedef std::string result_type; + result_type operator()(eoi_parser const &) const { return "eoi"; } + }; + + eoi_parser const eoi = eoi_parser(); +}}} + +#endif diff --git a/boost/spirit/home/x3/auxiliary/eol.hpp b/boost/spirit/home/x3/auxiliary/eol.hpp new file mode 100644 index 0000000000..3d191b4269 --- /dev/null +++ b/boost/spirit/home/x3/auxiliary/eol.hpp @@ -0,0 +1,59 @@ +/*============================================================================= + 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_EOL_MARCH_23_2007_0454PM) +#define BOOST_SPIRIT_X3_EOL_MARCH_23_2007_0454PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/core/skip_over.hpp> +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/support/unused.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + struct eol_parser : parser<eol_parser> + { + typedef unused_type attribute_type; + static bool const has_attribute = false; + + template <typename Iterator, typename Context, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, unused_type, Attribute& /*attr*/) const + { + x3::skip_over(first, last, context); + Iterator iter = first; + bool matched = false; + if (iter != last && *iter == '\r') // CR + { + matched = true; + ++iter; + } + if (iter != last && *iter == '\n') // LF + { + matched = true; + ++iter; + } + + if (matched) first = iter; + return matched; + } + }; + + template<> + struct get_info<eol_parser> + { + typedef std::string result_type; + result_type operator()(eol_parser const &) const { return "eol"; } + }; + + eol_parser const eol = eol_parser(); +}}} + +#endif diff --git a/boost/spirit/home/x3/auxiliary/eps.hpp b/boost/spirit/home/x3/auxiliary/eps.hpp new file mode 100644 index 0000000000..ab4d307931 --- /dev/null +++ b/boost/spirit/home/x3/auxiliary/eps.hpp @@ -0,0 +1,92 @@ +/*============================================================================= + 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_EPS_MARCH_23_2007_0454PM) +#define BOOST_SPIRIT_X3_EPS_MARCH_23_2007_0454PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/core/skip_over.hpp> +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/support/unused.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + struct rule_context_tag; + + struct semantic_predicate : parser<semantic_predicate> + { + typedef unused_type attribute_type; + static bool const has_attribute = false; + + semantic_predicate(bool predicate) + : predicate(predicate) {} + + template <typename Iterator, typename Context, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, unused_type, Attribute&) const + { + x3::skip_over(first, last, context); + return predicate; + } + + bool predicate; + }; + + template <typename F> + struct lazy_semantic_predicate : parser<lazy_semantic_predicate<F>> + { + typedef unused_type attribute_type; + static bool const has_attribute = false; + + lazy_semantic_predicate(F f) + : f(f) {} + + template <typename Iterator, typename Context, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, unused_type, Attribute& attr) const + { + x3::skip_over(first, last, context); + return f(x3::get<rule_context_tag>(context)); + } + + F f; + }; + + struct eps_parser : parser<eps_parser> + { + typedef unused_type attribute_type; + static bool const has_attribute = false; + + template <typename Iterator, typename Context + , typename RuleContext, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, RuleContext&, Attribute&) const + { + x3::skip_over(first, last, context); + return true; + } + + semantic_predicate + operator()(bool predicate) const + { + return semantic_predicate(predicate); + } + + template <typename F> + lazy_semantic_predicate<F> + operator()(F f) const + { + return lazy_semantic_predicate<F>(f); + } + }; + + eps_parser const eps = eps_parser(); +}}} + +#endif diff --git a/boost/spirit/home/x3/auxiliary/guard.hpp b/boost/spirit/home/x3/auxiliary/guard.hpp new file mode 100644 index 0000000000..6fd63c822c --- /dev/null +++ b/boost/spirit/home/x3/auxiliary/guard.hpp @@ -0,0 +1,73 @@ +/*============================================================================= + 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_GUARD_FERBRUARY_02_2013_0649PM) +#define BOOST_SPIRIT_X3_GUARD_FERBRUARY_02_2013_0649PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/context.hpp> +#include <boost/spirit/home/x3/directive/expect.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + enum class error_handler_result + { + fail + , retry + , accept + , rethrow + }; + + template <typename Subject, typename Handler> + struct guard : unary_parser<Subject, guard<Subject, Handler>> + { + typedef unary_parser<Subject, guard<Subject, Handler>> base_type; + static bool const is_pass_through_unary = true; + + guard(Subject const& subject, Handler handler) + : base_type(subject), handler(handler) {} + + template <typename Iterator, typename Context + , typename RuleContext, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, RuleContext& rcontext, Attribute& attr) const + { + for (;;) + { + try + { + Iterator i = first; + bool r = this->subject.parse(i, last, context, rcontext, attr); + if (r) + first = i; + return r; + } + catch (expectation_failure<Iterator> const& x) + { + switch (handler(first, last, x, context)) + { + case error_handler_result::fail: + return false; + case error_handler_result::retry: + continue; + case error_handler_result::accept: + return true; + case error_handler_result::rethrow: + throw; + } + } + } + return false; + } + + Handler handler; + }; +}}} + +#endif diff --git a/boost/spirit/home/x3/char.hpp b/boost/spirit/home/x3/char.hpp new file mode 100644 index 0000000000..19d26de3a2 --- /dev/null +++ b/boost/spirit/home/x3/char.hpp @@ -0,0 +1,23 @@ +/*============================================================================= + 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_CHAR_FEBRUARY_02_2007_0921AM) +#define BOOST_SPIRIT_X3_CHAR_FEBRUARY_02_2007_0921AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/char/char_parser.hpp> +#include <boost/spirit/home/x3/char/negated_char_parser.hpp> +#include <boost/spirit/home/x3/char/char.hpp> +#include <boost/spirit/home/x3/char/char_class.hpp> + +#if defined(BOOST_SPIRIT_X3_UNICODE) +#include <boost/spirit/home/x3/char/unicode.hpp> +#endif + +#endif diff --git a/boost/spirit/home/x3/char/any_char.hpp b/boost/spirit/home/x3/char/any_char.hpp new file mode 100644 index 0000000000..7ff769b8b2 --- /dev/null +++ b/boost/spirit/home/x3/char/any_char.hpp @@ -0,0 +1,41 @@ +/*============================================================================= + 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_ANY_CHAR_APRIL_16_2006_1051AM) +#define BOOST_SPIRIT_X3_ANY_CHAR_APRIL_16_2006_1051AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/char/literal_char.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename Encoding> + struct any_char : char_parser<any_char<Encoding>> + { + typedef typename Encoding::char_type char_type; + typedef Encoding encoding; + typedef char_type attribute_type; + static bool const has_attribute = true; + + template <typename Char, typename Context> + bool test(Char ch_, Context const&) const + { + return ((sizeof(Char) <= sizeof(char_type)) || encoding::ischar(ch_)); + } + + template <typename Char> + literal_char<Encoding> + operator()(Char ch) const + { + return literal_char<Encoding>(ch); + } + }; +}}} + +#endif diff --git a/boost/spirit/home/x3/char/char.hpp b/boost/spirit/home/x3/char/char.hpp new file mode 100644 index 0000000000..9452dcd86d --- /dev/null +++ b/boost/spirit/home/x3/char/char.hpp @@ -0,0 +1,88 @@ +/*============================================================================= + 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_CHAR_APRIL_16_2006_1051AM) +#define BOOST_SPIRIT_X3_CHAR_APRIL_16_2006_1051AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/char/any_char.hpp> +#include <boost/spirit/home/support/char_encoding/ascii.hpp> +#include <boost/spirit/home/support/char_encoding/standard.hpp> +#include <boost/spirit/home/support/char_encoding/standard_wide.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + namespace standard + { + typedef any_char<char_encoding::standard> char_type; + char_type const char_ = char_type(); + } + + using standard::char_type; + using standard::char_; + + namespace standard_wide + { + typedef any_char<char_encoding::standard_wide> char_type; + char_type const char_ = char_type(); + } + + namespace ascii + { + typedef any_char<char_encoding::ascii> char_type; + char_type const char_ = char_type(); + } + + namespace extension + { + template <> + struct as_parser<char> + { + typedef literal_char< + char_encoding::standard, unused_type> + type; + + typedef type value_type; + + static type call(char ch) + { + return type(ch); + } + }; + + template <> + struct as_parser<wchar_t> + { + typedef literal_char< + char_encoding::standard_wide, unused_type> + type; + + typedef type value_type; + + static type call(wchar_t ch) + { + return type(ch); + } + }; + } + + inline literal_char<char_encoding::standard, unused_type> + lit(char ch) + { + return literal_char<char_encoding::standard, unused_type>(ch); + } + + inline literal_char<char_encoding::standard_wide, unused_type> + lit(wchar_t ch) + { + return literal_char<char_encoding::standard_wide, unused_type>(ch); + } +}}} + +#endif diff --git a/boost/spirit/home/x3/char/char_class.hpp b/boost/spirit/home/x3/char/char_class.hpp new file mode 100644 index 0000000000..18b7131c0f --- /dev/null +++ b/boost/spirit/home/x3/char/char_class.hpp @@ -0,0 +1,148 @@ +/*============================================================================= + 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_CHAR_CLASS_APRIL_16_2006_1051AM) +#define BOOST_SPIRIT_X3_CHAR_CLASS_APRIL_16_2006_1051AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/char/char_parser.hpp> +#include <boost/spirit/home/x3/char/detail/cast_char.hpp> +#include <boost/spirit/home/support/char_encoding/standard.hpp> +#include <boost/spirit/home/support/char_encoding/standard_wide.hpp> +#include <boost/spirit/home/support/char_encoding/ascii.hpp> +#include <boost/spirit/home/support/char_encoding/iso8859_1.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + /////////////////////////////////////////////////////////////////////////// + struct char_tag {}; + struct alnum_tag {}; + struct alpha_tag {}; + struct blank_tag {}; + struct cntrl_tag {}; + struct digit_tag {}; + struct graph_tag {}; + struct print_tag {}; + struct punct_tag {}; + struct space_tag {}; + struct xdigit_tag {}; + struct lower_tag {}; + struct upper_tag {}; + + /////////////////////////////////////////////////////////////////////////// + template <typename Encoding> + struct char_class_base + { + typedef typename Encoding::char_type char_type; + +#define BOOST_SPIRIT_X3_CLASSIFY(name) \ + template <typename Char> \ + static bool \ + is(name##_tag, Char ch) \ + { \ + return Encoding::is##name \ + BOOST_PREVENT_MACRO_SUBSTITUTION \ + (detail::cast_char<char_type>(ch)); \ + } \ + /***/ + + BOOST_SPIRIT_X3_CLASSIFY(char) + BOOST_SPIRIT_X3_CLASSIFY(alnum) + BOOST_SPIRIT_X3_CLASSIFY(alpha) + BOOST_SPIRIT_X3_CLASSIFY(digit) + BOOST_SPIRIT_X3_CLASSIFY(xdigit) + BOOST_SPIRIT_X3_CLASSIFY(cntrl) + BOOST_SPIRIT_X3_CLASSIFY(graph) + BOOST_SPIRIT_X3_CLASSIFY(lower) + BOOST_SPIRIT_X3_CLASSIFY(print) + BOOST_SPIRIT_X3_CLASSIFY(punct) + BOOST_SPIRIT_X3_CLASSIFY(space) + BOOST_SPIRIT_X3_CLASSIFY(blank) + BOOST_SPIRIT_X3_CLASSIFY(upper) + +#undef BOOST_SPIRIT_X3_CLASSIFY + }; + + template <typename Encoding, typename Tag> + struct char_class + : char_parser<char_class<Encoding, Tag>> + { + typedef Encoding encoding; + typedef Tag tag; + typedef typename Encoding::char_type char_type; + typedef char_type attribute_type; + static bool const has_attribute = true; + + template <typename Char, typename Context> + bool test(Char ch, Context const&) const + { + return ((sizeof(Char) <= sizeof(char_type)) || encoding::ischar(ch)) + && char_class_base<Encoding>::is(tag(), ch); + } + }; + +#define BOOST_SPIRIT_X3_CHAR_CLASS(encoding, name) \ + typedef char_class<char_encoding::encoding, name##_tag> name##_type; \ + name##_type const name = name##_type(); \ + /***/ + +#define BOOST_SPIRIT_X3_CHAR_CLASSES(encoding) \ + namespace encoding \ + { \ + BOOST_SPIRIT_X3_CHAR_CLASS(encoding, alnum) \ + BOOST_SPIRIT_X3_CHAR_CLASS(encoding, alpha) \ + BOOST_SPIRIT_X3_CHAR_CLASS(encoding, digit) \ + BOOST_SPIRIT_X3_CHAR_CLASS(encoding, xdigit) \ + BOOST_SPIRIT_X3_CHAR_CLASS(encoding, cntrl) \ + BOOST_SPIRIT_X3_CHAR_CLASS(encoding, graph) \ + BOOST_SPIRIT_X3_CHAR_CLASS(encoding, lower) \ + BOOST_SPIRIT_X3_CHAR_CLASS(encoding, print) \ + BOOST_SPIRIT_X3_CHAR_CLASS(encoding, punct) \ + BOOST_SPIRIT_X3_CHAR_CLASS(encoding, space) \ + BOOST_SPIRIT_X3_CHAR_CLASS(encoding, blank) \ + BOOST_SPIRIT_X3_CHAR_CLASS(encoding, upper) \ + } \ + /***/ + + BOOST_SPIRIT_X3_CHAR_CLASSES(standard) + BOOST_SPIRIT_X3_CHAR_CLASSES(standard_wide) + BOOST_SPIRIT_X3_CHAR_CLASSES(ascii) + BOOST_SPIRIT_X3_CHAR_CLASSES(iso8859_1) + +#undef BOOST_SPIRIT_X3_CHAR_CLASS +#undef BOOST_SPIRIT_X3_CHAR_CLASSES + + using standard::alnum_type; + using standard::alpha_type; + using standard::digit_type; + using standard::xdigit_type; + using standard::cntrl_type; + using standard::graph_type; + using standard::lower_type; + using standard::print_type; + using standard::punct_type; + using standard::space_type; + using standard::blank_type; + using standard::upper_type; + + using standard::alnum; + using standard::alpha; + using standard::digit; + using standard::xdigit; + using standard::cntrl; + using standard::graph; + using standard::lower; + using standard::print; + using standard::punct; + using standard::space; + using standard::blank; + using standard::upper; +}}} + +#endif diff --git a/boost/spirit/home/x3/char/char_parser.hpp b/boost/spirit/home/x3/char/char_parser.hpp new file mode 100644 index 0000000000..6943804369 --- /dev/null +++ b/boost/spirit/home/x3/char/char_parser.hpp @@ -0,0 +1,44 @@ +/*============================================================================= + 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_CHAR_PARSER_APR_16_2006_0906AM) +#define BOOST_SPIRIT_X3_CHAR_PARSER_APR_16_2006_0906AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/core/skip_over.hpp> +#include <boost/spirit/home/x3/support/traits/move_to.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + /////////////////////////////////////////////////////////////////////////// + // The base char_parser + /////////////////////////////////////////////////////////////////////////// + template <typename Derived> + struct char_parser : parser<Derived> + { + template <typename Iterator, typename Context, typename Attribute> + bool parse( + Iterator& first, Iterator const& last + , Context const& context, unused_type, Attribute& attr) const + { + x3::skip_over(first, last, context); + + if (first != last && this->derived().test(*first, context)) + { + x3::traits::move_to(*first, attr); + ++first; + return true; + } + return false; + } + }; +}}} + +#endif diff --git a/boost/spirit/home/x3/char/detail/cast_char.hpp b/boost/spirit/home/x3/char/detail/cast_char.hpp new file mode 100644 index 0000000000..03bda27a29 --- /dev/null +++ b/boost/spirit/home/x3/char/detail/cast_char.hpp @@ -0,0 +1,58 @@ +/*============================================================================= + 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_CAST_CHAR_NOVEMBER_10_2006_0907AM) +#define BOOST_SPIRIT_X3_CAST_CHAR_NOVEMBER_10_2006_0907AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/type_traits/is_signed.hpp> +#include <boost/type_traits/make_unsigned.hpp> +#include <boost/type_traits/make_signed.hpp> + +namespace boost { namespace spirit { namespace x3 { namespace detail +{ + // Here's the thing... typical encodings (except ASCII) deal with unsigned + // integers > 127 (ASCII uses only 127). Yet, most char and wchar_t are signed. + // Thus, a char with value > 127 is negative (e.g. char 233 is -23). When you + // cast this to an unsigned int with 32 bits, you get 4294967273! + // + // The trick is to cast to an unsigned version of the source char first + // before casting to the target. {P.S. Don't worry about the code, the + // optimizer will optimize the if-else branches} + + template <typename TargetChar, typename SourceChar> + TargetChar cast_char(SourceChar ch) + { + if (is_signed<TargetChar>::value != is_signed<SourceChar>::value) + { + if (is_signed<SourceChar>::value) + { + // source is signed, target is unsigned + typedef typename make_unsigned<SourceChar>::type USourceChar; + return TargetChar(USourceChar(ch)); + } + else + { + // source is unsigned, target is signed + typedef typename make_signed<SourceChar>::type SSourceChar; + return TargetChar(SSourceChar(ch)); + } + } + else + { + // source and target has same signedness + return TargetChar(ch); // just cast + } + } +}}}} + +#endif + + diff --git a/boost/spirit/home/x3/char/literal_char.hpp b/boost/spirit/home/x3/char/literal_char.hpp new file mode 100644 index 0000000000..94b2a239a6 --- /dev/null +++ b/boost/spirit/home/x3/char/literal_char.hpp @@ -0,0 +1,54 @@ +/*============================================================================= + 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_LITERAL_CHAR_APRIL_16_2006_1051AM) +#define BOOST_SPIRIT_X3_LITERAL_CHAR_APRIL_16_2006_1051AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/char/char_parser.hpp> +#include <boost/spirit/home/x3/support/utility/utf8.hpp> +#include <boost/type_traits/is_same.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename Encoding, typename Attribute = typename Encoding::char_type> + struct literal_char : char_parser<literal_char<Encoding, Attribute>> + { + typedef typename Encoding::char_type char_type; + typedef Encoding encoding; + typedef Attribute attribute_type; + static bool const has_attribute = + !is_same<unused_type, attribute_type>::value; + + template <typename Char> + literal_char(Char ch) + : ch(static_cast<char_type>(ch)) {} + + template <typename Char, typename Context> + bool test(Char ch_, Context const&) const + { + return ((sizeof(Char) <= sizeof(char_type)) || encoding::ischar(ch_)) + && ch == char_type(ch_); + } + + char_type ch; + }; + + template <typename Encoding, typename Attribute> + struct get_info<literal_char<Encoding, Attribute>> + { + typedef std::string result_type; + std::string operator()(literal_char<Encoding, Attribute> const& p) const + { + return '\'' + to_utf8(Encoding::toucs4(p.ch)) + '\''; + } + }; +}}} + +#endif diff --git a/boost/spirit/home/x3/char/negated_char_parser.hpp b/boost/spirit/home/x3/char/negated_char_parser.hpp new file mode 100644 index 0000000000..392d712759 --- /dev/null +++ b/boost/spirit/home/x3/char/negated_char_parser.hpp @@ -0,0 +1,65 @@ +/*============================================================================= + 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_NEGATED_CHAR_PARSER_APR_16_2006_0906AM) +#define BOOST_SPIRIT_X3_NEGATED_CHAR_PARSER_APR_16_2006_0906AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/traits/attribute_of.hpp> +#include <boost/spirit/home/x3/support/traits/has_attribute.hpp> +#include <boost/spirit/home/x3/char/char_parser.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + /////////////////////////////////////////////////////////////////////////// + // negated_char_parser handles ~cp expressions (cp is a char_parser) + /////////////////////////////////////////////////////////////////////////// + template <typename Positive> + struct negated_char_parser : + char_parser<negated_char_parser<Positive>> + { + negated_char_parser(Positive const& positive) + : positive(positive) {} + + template <typename CharParam, typename Context> + bool test(CharParam ch, Context const& context) const + { + return !positive.test(ch, context); + } + + Positive positive; + }; + + template <typename Positive> + inline negated_char_parser<Positive> + operator~(char_parser<Positive> const& cp) + { + return negated_char_parser<Positive>(cp.derived()); + } + + template <typename Positive> + inline Positive const& + operator~(negated_char_parser<Positive> const& cp) + { + return cp.positive; + } +}}} + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + template <typename Positive, typename Context> + struct attribute_of<x3::negated_char_parser<Positive>, Context> + : attribute_of<Positive, Context> {}; + + template <typename Positive, typename Context> + struct has_attribute<x3::negated_char_parser<Positive>, Context> + : has_attribute<Positive, Context> {}; +}}}} + +#endif diff --git a/boost/spirit/home/x3/char/unicode.hpp b/boost/spirit/home/x3/char/unicode.hpp new file mode 100644 index 0000000000..6954c40e40 --- /dev/null +++ b/boost/spirit/home/x3/char/unicode.hpp @@ -0,0 +1,617 @@ +/*============================================================================= + 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_UNICODE_JAN_20_2012_1218AM) +#define BOOST_SPIRIT_X3_UNICODE_JAN_20_2012_1218AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/char/char_parser.hpp> +#include <boost/spirit/home/x3/char/char.hpp> +#include <boost/spirit/home/x3/char/detail/cast_char.hpp> +#include <boost/spirit/home/support/char_encoding/unicode.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + /////////////////////////////////////////////////////////////////////////// + // Unicode Major Categories + /////////////////////////////////////////////////////////////////////////// + struct char_tag; + struct alnum_tag; + struct alpha_tag; + struct blank_tag; + struct cntrl_tag; + struct digit_tag; + struct graph_tag; + struct print_tag; + struct punct_tag; + struct space_tag; + struct xdigit_tag; + struct lower_tag; + struct upper_tag; + + /////////////////////////////////////////////////////////////////////////// + // Unicode Major Categories + /////////////////////////////////////////////////////////////////////////// + struct letter_tag {}; + struct mark_tag {}; + struct number_tag {}; + struct separator_tag {}; + struct other_tag {}; + struct punctuation_tag {}; + struct symbol_tag {}; + + /////////////////////////////////////////////////////////////////////////// + // Unicode General Categories + /////////////////////////////////////////////////////////////////////////// + struct uppercase_letter_tag {}; + struct lowercase_letter_tag {}; + struct titlecase_letter_tag {}; + struct modifier_letter_tag {}; + struct other_letter_tag {}; + + struct nonspacing_mark_tag {}; + struct enclosing_mark_tag {}; + struct spacing_mark_tag {}; + + struct decimal_number_tag {}; + struct letter_number_tag {}; + struct other_number_tag {}; + + struct space_separator_tag {}; + struct line_separator_tag {}; + struct paragraph_separator_tag {}; + + struct control_tag {}; + struct format_tag {}; + struct private_use_tag {}; + struct surrogate_tag {}; + struct unassigned_tag {}; + + struct dash_punctuation_tag {}; + struct open_punctuation_tag {}; + struct close_punctuation_tag {}; + struct connector_punctuation_tag {}; + struct other_punctuation_tag {}; + struct initial_punctuation_tag {}; + struct final_punctuation_tag {}; + + struct math_symbol_tag {}; + struct currency_symbol_tag {}; + struct modifier_symbol_tag {}; + struct other_symbol_tag {}; + + /////////////////////////////////////////////////////////////////////////// + // Unicode Derived Categories + /////////////////////////////////////////////////////////////////////////// + struct alphabetic_tag {}; + struct uppercase_tag {}; + struct lowercase_tag {}; + struct white_space_tag {}; + struct hex_digit_tag {}; + struct noncharacter_code_point_tag {}; + struct default_ignorable_code_point_tag {}; + + /////////////////////////////////////////////////////////////////////////// + // Unicode Scripts + /////////////////////////////////////////////////////////////////////////// + struct arabic_tag {}; + struct imperial_aramaic_tag {}; + struct armenian_tag {}; + struct avestan_tag {}; + struct balinese_tag {}; + struct bamum_tag {}; + struct bengali_tag {}; + struct bopomofo_tag {}; + struct braille_tag {}; + struct buginese_tag {}; + struct buhid_tag {}; + struct canadian_aboriginal_tag {}; + struct carian_tag {}; + struct cham_tag {}; + struct cherokee_tag {}; + struct coptic_tag {}; + struct cypriot_tag {}; + struct cyrillic_tag {}; + struct devanagari_tag {}; + struct deseret_tag {}; + struct egyptian_hieroglyphs_tag {}; + struct ethiopic_tag {}; + struct georgian_tag {}; + struct glagolitic_tag {}; + struct gothic_tag {}; + struct greek_tag {}; + struct gujarati_tag {}; + struct gurmukhi_tag {}; + struct hangul_tag {}; + struct han_tag {}; + struct hanunoo_tag {}; + struct hebrew_tag {}; + struct hiragana_tag {}; + struct katakana_or_hiragana_tag {}; + struct old_italic_tag {}; + struct javanese_tag {}; + struct kayah_li_tag {}; + struct katakana_tag {}; + struct kharoshthi_tag {}; + struct khmer_tag {}; + struct kannada_tag {}; + struct kaithi_tag {}; + struct tai_tham_tag {}; + struct lao_tag {}; + struct latin_tag {}; + struct lepcha_tag {}; + struct limbu_tag {}; + struct linear_b_tag {}; + struct lisu_tag {}; + struct lycian_tag {}; + struct lydian_tag {}; + struct malayalam_tag {}; + struct mongolian_tag {}; + struct meetei_mayek_tag {}; + struct myanmar_tag {}; + struct nko_tag {}; + struct ogham_tag {}; + struct ol_chiki_tag {}; + struct old_turkic_tag {}; + struct oriya_tag {}; + struct osmanya_tag {}; + struct phags_pa_tag {}; + struct inscriptional_pahlavi_tag {}; + struct phoenician_tag {}; + struct inscriptional_parthian_tag {}; + struct rejang_tag {}; + struct runic_tag {}; + struct samaritan_tag {}; + struct old_south_arabian_tag {}; + struct saurashtra_tag {}; + struct shavian_tag {}; + struct sinhala_tag {}; + struct sundanese_tag {}; + struct syloti_nagri_tag {}; + struct syriac_tag {}; + struct tagbanwa_tag {}; + struct tai_le_tag {}; + struct new_tai_lue_tag {}; + struct tamil_tag {}; + struct tai_viet_tag {}; + struct telugu_tag {}; + struct tifinagh_tag {}; + struct tagalog_tag {}; + struct thaana_tag {}; + struct thai_tag {}; + struct tibetan_tag {}; + struct ugaritic_tag {}; + struct vai_tag {}; + struct old_persian_tag {}; + struct cuneiform_tag {}; + struct yi_tag {}; + struct inherited_tag {}; + struct common_tag {}; + struct unknown_tag {}; + + /////////////////////////////////////////////////////////////////////////// + struct unicode_char_class_base + { + typedef char_encoding::unicode encoding; + typedef char_encoding::unicode::char_type char_type; + +#define BOOST_SPIRIT_X3_BASIC_CLASSIFY(name) \ + template <typename Char> \ + static bool \ + is(name##_tag, Char ch) \ + { \ + return encoding::is ##name \ + BOOST_PREVENT_MACRO_SUBSTITUTION \ + (detail::cast_char<char_type>(ch)); \ + } \ + /***/ + +#define BOOST_SPIRIT_X3_CLASSIFY(name) \ + template <typename Char> \ + static bool \ + is(name##_tag, Char ch) \ + { \ + return encoding::is_##name \ + BOOST_PREVENT_MACRO_SUBSTITUTION \ + (detail::cast_char<char_type>(ch)); \ + } \ + /***/ + + + /////////////////////////////////////////////////////////////////////////// + // Unicode Major Categories + /////////////////////////////////////////////////////////////////////////// + BOOST_SPIRIT_X3_BASIC_CLASSIFY(char) + BOOST_SPIRIT_X3_BASIC_CLASSIFY(alnum) + BOOST_SPIRIT_X3_BASIC_CLASSIFY(alpha) + BOOST_SPIRIT_X3_BASIC_CLASSIFY(digit) + BOOST_SPIRIT_X3_BASIC_CLASSIFY(xdigit) + BOOST_SPIRIT_X3_BASIC_CLASSIFY(cntrl) + BOOST_SPIRIT_X3_BASIC_CLASSIFY(graph) + BOOST_SPIRIT_X3_BASIC_CLASSIFY(lower) + BOOST_SPIRIT_X3_BASIC_CLASSIFY(print) + BOOST_SPIRIT_X3_BASIC_CLASSIFY(punct) + BOOST_SPIRIT_X3_BASIC_CLASSIFY(space) + BOOST_SPIRIT_X3_BASIC_CLASSIFY(blank) + BOOST_SPIRIT_X3_BASIC_CLASSIFY(upper) + + /////////////////////////////////////////////////////////////////////////// + // Unicode Major Categories + /////////////////////////////////////////////////////////////////////////// + BOOST_SPIRIT_X3_CLASSIFY(letter) + BOOST_SPIRIT_X3_CLASSIFY(mark) + BOOST_SPIRIT_X3_CLASSIFY(number) + BOOST_SPIRIT_X3_CLASSIFY(separator) + BOOST_SPIRIT_X3_CLASSIFY(other) + BOOST_SPIRIT_X3_CLASSIFY(punctuation) + BOOST_SPIRIT_X3_CLASSIFY(symbol) + + /////////////////////////////////////////////////////////////////////////// + // Unicode General Categories + /////////////////////////////////////////////////////////////////////////// + BOOST_SPIRIT_X3_CLASSIFY(uppercase_letter) + BOOST_SPIRIT_X3_CLASSIFY(lowercase_letter) + BOOST_SPIRIT_X3_CLASSIFY(titlecase_letter) + BOOST_SPIRIT_X3_CLASSIFY(modifier_letter) + BOOST_SPIRIT_X3_CLASSIFY(other_letter) + + BOOST_SPIRIT_X3_CLASSIFY(nonspacing_mark) + BOOST_SPIRIT_X3_CLASSIFY(enclosing_mark) + BOOST_SPIRIT_X3_CLASSIFY(spacing_mark) + + BOOST_SPIRIT_X3_CLASSIFY(decimal_number) + BOOST_SPIRIT_X3_CLASSIFY(letter_number) + BOOST_SPIRIT_X3_CLASSIFY(other_number) + + BOOST_SPIRIT_X3_CLASSIFY(space_separator) + BOOST_SPIRIT_X3_CLASSIFY(line_separator) + BOOST_SPIRIT_X3_CLASSIFY(paragraph_separator) + + BOOST_SPIRIT_X3_CLASSIFY(control) + BOOST_SPIRIT_X3_CLASSIFY(format) + BOOST_SPIRIT_X3_CLASSIFY(private_use) + BOOST_SPIRIT_X3_CLASSIFY(surrogate) + BOOST_SPIRIT_X3_CLASSIFY(unassigned) + + BOOST_SPIRIT_X3_CLASSIFY(dash_punctuation) + BOOST_SPIRIT_X3_CLASSIFY(open_punctuation) + BOOST_SPIRIT_X3_CLASSIFY(close_punctuation) + BOOST_SPIRIT_X3_CLASSIFY(connector_punctuation) + BOOST_SPIRIT_X3_CLASSIFY(other_punctuation) + BOOST_SPIRIT_X3_CLASSIFY(initial_punctuation) + BOOST_SPIRIT_X3_CLASSIFY(final_punctuation) + + BOOST_SPIRIT_X3_CLASSIFY(math_symbol) + BOOST_SPIRIT_X3_CLASSIFY(currency_symbol) + BOOST_SPIRIT_X3_CLASSIFY(modifier_symbol) + BOOST_SPIRIT_X3_CLASSIFY(other_symbol) + + /////////////////////////////////////////////////////////////////////////// + // Unicode Derived Categories + /////////////////////////////////////////////////////////////////////////// + BOOST_SPIRIT_X3_CLASSIFY(alphabetic) + BOOST_SPIRIT_X3_CLASSIFY(uppercase) + BOOST_SPIRIT_X3_CLASSIFY(lowercase) + BOOST_SPIRIT_X3_CLASSIFY(white_space) + BOOST_SPIRIT_X3_CLASSIFY(hex_digit) + BOOST_SPIRIT_X3_CLASSIFY(noncharacter_code_point) + BOOST_SPIRIT_X3_CLASSIFY(default_ignorable_code_point) + + /////////////////////////////////////////////////////////////////////////// + // Unicode Scripts + /////////////////////////////////////////////////////////////////////////// + BOOST_SPIRIT_X3_CLASSIFY(arabic) + BOOST_SPIRIT_X3_CLASSIFY(imperial_aramaic) + BOOST_SPIRIT_X3_CLASSIFY(armenian) + BOOST_SPIRIT_X3_CLASSIFY(avestan) + BOOST_SPIRIT_X3_CLASSIFY(balinese) + BOOST_SPIRIT_X3_CLASSIFY(bamum) + BOOST_SPIRIT_X3_CLASSIFY(bengali) + BOOST_SPIRIT_X3_CLASSIFY(bopomofo) + BOOST_SPIRIT_X3_CLASSIFY(braille) + BOOST_SPIRIT_X3_CLASSIFY(buginese) + BOOST_SPIRIT_X3_CLASSIFY(buhid) + BOOST_SPIRIT_X3_CLASSIFY(canadian_aboriginal) + BOOST_SPIRIT_X3_CLASSIFY(carian) + BOOST_SPIRIT_X3_CLASSIFY(cham) + BOOST_SPIRIT_X3_CLASSIFY(cherokee) + BOOST_SPIRIT_X3_CLASSIFY(coptic) + BOOST_SPIRIT_X3_CLASSIFY(cypriot) + BOOST_SPIRIT_X3_CLASSIFY(cyrillic) + BOOST_SPIRIT_X3_CLASSIFY(devanagari) + BOOST_SPIRIT_X3_CLASSIFY(deseret) + BOOST_SPIRIT_X3_CLASSIFY(egyptian_hieroglyphs) + BOOST_SPIRIT_X3_CLASSIFY(ethiopic) + BOOST_SPIRIT_X3_CLASSIFY(georgian) + BOOST_SPIRIT_X3_CLASSIFY(glagolitic) + BOOST_SPIRIT_X3_CLASSIFY(gothic) + BOOST_SPIRIT_X3_CLASSIFY(greek) + BOOST_SPIRIT_X3_CLASSIFY(gujarati) + BOOST_SPIRIT_X3_CLASSIFY(gurmukhi) + BOOST_SPIRIT_X3_CLASSIFY(hangul) + BOOST_SPIRIT_X3_CLASSIFY(han) + BOOST_SPIRIT_X3_CLASSIFY(hanunoo) + BOOST_SPIRIT_X3_CLASSIFY(hebrew) + BOOST_SPIRIT_X3_CLASSIFY(hiragana) + BOOST_SPIRIT_X3_CLASSIFY(katakana_or_hiragana) + BOOST_SPIRIT_X3_CLASSIFY(old_italic) + BOOST_SPIRIT_X3_CLASSIFY(javanese) + BOOST_SPIRIT_X3_CLASSIFY(kayah_li) + BOOST_SPIRIT_X3_CLASSIFY(katakana) + BOOST_SPIRIT_X3_CLASSIFY(kharoshthi) + BOOST_SPIRIT_X3_CLASSIFY(khmer) + BOOST_SPIRIT_X3_CLASSIFY(kannada) + BOOST_SPIRIT_X3_CLASSIFY(kaithi) + BOOST_SPIRIT_X3_CLASSIFY(tai_tham) + BOOST_SPIRIT_X3_CLASSIFY(lao) + BOOST_SPIRIT_X3_CLASSIFY(latin) + BOOST_SPIRIT_X3_CLASSIFY(lepcha) + BOOST_SPIRIT_X3_CLASSIFY(limbu) + BOOST_SPIRIT_X3_CLASSIFY(linear_b) + BOOST_SPIRIT_X3_CLASSIFY(lisu) + BOOST_SPIRIT_X3_CLASSIFY(lycian) + BOOST_SPIRIT_X3_CLASSIFY(lydian) + BOOST_SPIRIT_X3_CLASSIFY(malayalam) + BOOST_SPIRIT_X3_CLASSIFY(mongolian) + BOOST_SPIRIT_X3_CLASSIFY(meetei_mayek) + BOOST_SPIRIT_X3_CLASSIFY(myanmar) + BOOST_SPIRIT_X3_CLASSIFY(nko) + BOOST_SPIRIT_X3_CLASSIFY(ogham) + BOOST_SPIRIT_X3_CLASSIFY(ol_chiki) + BOOST_SPIRIT_X3_CLASSIFY(old_turkic) + BOOST_SPIRIT_X3_CLASSIFY(oriya) + BOOST_SPIRIT_X3_CLASSIFY(osmanya) + BOOST_SPIRIT_X3_CLASSIFY(phags_pa) + BOOST_SPIRIT_X3_CLASSIFY(inscriptional_pahlavi) + BOOST_SPIRIT_X3_CLASSIFY(phoenician) + BOOST_SPIRIT_X3_CLASSIFY(inscriptional_parthian) + BOOST_SPIRIT_X3_CLASSIFY(rejang) + BOOST_SPIRIT_X3_CLASSIFY(runic) + BOOST_SPIRIT_X3_CLASSIFY(samaritan) + BOOST_SPIRIT_X3_CLASSIFY(old_south_arabian) + BOOST_SPIRIT_X3_CLASSIFY(saurashtra) + BOOST_SPIRIT_X3_CLASSIFY(shavian) + BOOST_SPIRIT_X3_CLASSIFY(sinhala) + BOOST_SPIRIT_X3_CLASSIFY(sundanese) + BOOST_SPIRIT_X3_CLASSIFY(syloti_nagri) + BOOST_SPIRIT_X3_CLASSIFY(syriac) + BOOST_SPIRIT_X3_CLASSIFY(tagbanwa) + BOOST_SPIRIT_X3_CLASSIFY(tai_le) + BOOST_SPIRIT_X3_CLASSIFY(new_tai_lue) + BOOST_SPIRIT_X3_CLASSIFY(tamil) + BOOST_SPIRIT_X3_CLASSIFY(tai_viet) + BOOST_SPIRIT_X3_CLASSIFY(telugu) + BOOST_SPIRIT_X3_CLASSIFY(tifinagh) + BOOST_SPIRIT_X3_CLASSIFY(tagalog) + BOOST_SPIRIT_X3_CLASSIFY(thaana) + BOOST_SPIRIT_X3_CLASSIFY(thai) + BOOST_SPIRIT_X3_CLASSIFY(tibetan) + BOOST_SPIRIT_X3_CLASSIFY(ugaritic) + BOOST_SPIRIT_X3_CLASSIFY(vai) + BOOST_SPIRIT_X3_CLASSIFY(old_persian) + BOOST_SPIRIT_X3_CLASSIFY(cuneiform) + BOOST_SPIRIT_X3_CLASSIFY(yi) + BOOST_SPIRIT_X3_CLASSIFY(inherited) + BOOST_SPIRIT_X3_CLASSIFY(common) + BOOST_SPIRIT_X3_CLASSIFY(unknown) + +#undef BOOST_SPIRIT_X3_BASIC_CLASSIFY +#undef BOOST_SPIRIT_X3_CLASSIFY + }; + + template <typename Tag> + struct unicode_char_class + : char_parser<unicode_char_class<Tag>> + { + typedef char_encoding::unicode encoding; + typedef Tag tag; + typedef typename encoding::char_type char_type; + typedef char_type attribute_type; + static bool const has_attribute = true; + + template <typename Char, typename Context> + bool test(Char ch, Context const&) const + { + return ((sizeof(Char) <= sizeof(char_type)) || encoding::ischar(ch)) + && unicode_char_class_base::is(tag(), ch); + } + }; + +#define BOOST_SPIRIT_X3_CHAR_CLASS(name) \ + typedef unicode_char_class<name##_tag> name##_type; \ + name##_type const name = name##_type(); \ + /***/ + + namespace unicode + { + typedef any_char<char_encoding::unicode> char_type; + char_type const char_ = char_type(); + + /////////////////////////////////////////////////////////////////////////// + // Unicode Major Categories + /////////////////////////////////////////////////////////////////////////// + BOOST_SPIRIT_X3_CHAR_CLASS(alnum) + BOOST_SPIRIT_X3_CHAR_CLASS(alpha) + BOOST_SPIRIT_X3_CHAR_CLASS(digit) + BOOST_SPIRIT_X3_CHAR_CLASS(xdigit) + BOOST_SPIRIT_X3_CHAR_CLASS(cntrl) + BOOST_SPIRIT_X3_CHAR_CLASS(graph) + BOOST_SPIRIT_X3_CHAR_CLASS(lower) + BOOST_SPIRIT_X3_CHAR_CLASS(print) + BOOST_SPIRIT_X3_CHAR_CLASS(punct) + BOOST_SPIRIT_X3_CHAR_CLASS(space) + BOOST_SPIRIT_X3_CHAR_CLASS(blank) + BOOST_SPIRIT_X3_CHAR_CLASS(upper) + + /////////////////////////////////////////////////////////////////////////// + // Unicode Major Categories + /////////////////////////////////////////////////////////////////////////// + BOOST_SPIRIT_X3_CHAR_CLASS(letter) + BOOST_SPIRIT_X3_CHAR_CLASS(mark) + BOOST_SPIRIT_X3_CHAR_CLASS(number) + BOOST_SPIRIT_X3_CHAR_CLASS(separator) + BOOST_SPIRIT_X3_CHAR_CLASS(other) + BOOST_SPIRIT_X3_CHAR_CLASS(punctuation) + BOOST_SPIRIT_X3_CHAR_CLASS(symbol) + + /////////////////////////////////////////////////////////////////////////// + // Unicode General Categories + /////////////////////////////////////////////////////////////////////////// + BOOST_SPIRIT_X3_CHAR_CLASS(uppercase_letter) + BOOST_SPIRIT_X3_CHAR_CLASS(lowercase_letter) + BOOST_SPIRIT_X3_CHAR_CLASS(titlecase_letter) + BOOST_SPIRIT_X3_CHAR_CLASS(modifier_letter) + BOOST_SPIRIT_X3_CHAR_CLASS(other_letter) + + BOOST_SPIRIT_X3_CHAR_CLASS(nonspacing_mark) + BOOST_SPIRIT_X3_CHAR_CLASS(enclosing_mark) + BOOST_SPIRIT_X3_CHAR_CLASS(spacing_mark) + + BOOST_SPIRIT_X3_CHAR_CLASS(decimal_number) + BOOST_SPIRIT_X3_CHAR_CLASS(letter_number) + BOOST_SPIRIT_X3_CHAR_CLASS(other_number) + + BOOST_SPIRIT_X3_CHAR_CLASS(space_separator) + BOOST_SPIRIT_X3_CHAR_CLASS(line_separator) + BOOST_SPIRIT_X3_CHAR_CLASS(paragraph_separator) + + BOOST_SPIRIT_X3_CHAR_CLASS(control) + BOOST_SPIRIT_X3_CHAR_CLASS(format) + BOOST_SPIRIT_X3_CHAR_CLASS(private_use) + BOOST_SPIRIT_X3_CHAR_CLASS(surrogate) + BOOST_SPIRIT_X3_CHAR_CLASS(unassigned) + + BOOST_SPIRIT_X3_CHAR_CLASS(dash_punctuation) + BOOST_SPIRIT_X3_CHAR_CLASS(open_punctuation) + BOOST_SPIRIT_X3_CHAR_CLASS(close_punctuation) + BOOST_SPIRIT_X3_CHAR_CLASS(connector_punctuation) + BOOST_SPIRIT_X3_CHAR_CLASS(other_punctuation) + BOOST_SPIRIT_X3_CHAR_CLASS(initial_punctuation) + BOOST_SPIRIT_X3_CHAR_CLASS(final_punctuation) + + BOOST_SPIRIT_X3_CHAR_CLASS(math_symbol) + BOOST_SPIRIT_X3_CHAR_CLASS(currency_symbol) + BOOST_SPIRIT_X3_CHAR_CLASS(modifier_symbol) + BOOST_SPIRIT_X3_CHAR_CLASS(other_symbol) + + /////////////////////////////////////////////////////////////////////////// + // Unicode Derived Categories + /////////////////////////////////////////////////////////////////////////// + BOOST_SPIRIT_X3_CHAR_CLASS(alphabetic) + BOOST_SPIRIT_X3_CHAR_CLASS(uppercase) + BOOST_SPIRIT_X3_CHAR_CLASS(lowercase) + BOOST_SPIRIT_X3_CHAR_CLASS(white_space) + BOOST_SPIRIT_X3_CHAR_CLASS(hex_digit) + BOOST_SPIRIT_X3_CHAR_CLASS(noncharacter_code_point) + BOOST_SPIRIT_X3_CHAR_CLASS(default_ignorable_code_point) + + /////////////////////////////////////////////////////////////////////////// + // Unicode Scripts + /////////////////////////////////////////////////////////////////////////// + BOOST_SPIRIT_X3_CHAR_CLASS(arabic) + BOOST_SPIRIT_X3_CHAR_CLASS(imperial_aramaic) + BOOST_SPIRIT_X3_CHAR_CLASS(armenian) + BOOST_SPIRIT_X3_CHAR_CLASS(avestan) + BOOST_SPIRIT_X3_CHAR_CLASS(balinese) + BOOST_SPIRIT_X3_CHAR_CLASS(bamum) + BOOST_SPIRIT_X3_CHAR_CLASS(bengali) + BOOST_SPIRIT_X3_CHAR_CLASS(bopomofo) + BOOST_SPIRIT_X3_CHAR_CLASS(braille) + BOOST_SPIRIT_X3_CHAR_CLASS(buginese) + BOOST_SPIRIT_X3_CHAR_CLASS(buhid) + BOOST_SPIRIT_X3_CHAR_CLASS(canadian_aboriginal) + BOOST_SPIRIT_X3_CHAR_CLASS(carian) + BOOST_SPIRIT_X3_CHAR_CLASS(cham) + BOOST_SPIRIT_X3_CHAR_CLASS(cherokee) + BOOST_SPIRIT_X3_CHAR_CLASS(coptic) + BOOST_SPIRIT_X3_CHAR_CLASS(cypriot) + BOOST_SPIRIT_X3_CHAR_CLASS(cyrillic) + BOOST_SPIRIT_X3_CHAR_CLASS(devanagari) + BOOST_SPIRIT_X3_CHAR_CLASS(deseret) + BOOST_SPIRIT_X3_CHAR_CLASS(egyptian_hieroglyphs) + BOOST_SPIRIT_X3_CHAR_CLASS(ethiopic) + BOOST_SPIRIT_X3_CHAR_CLASS(georgian) + BOOST_SPIRIT_X3_CHAR_CLASS(glagolitic) + BOOST_SPIRIT_X3_CHAR_CLASS(gothic) + BOOST_SPIRIT_X3_CHAR_CLASS(greek) + BOOST_SPIRIT_X3_CHAR_CLASS(gujarati) + BOOST_SPIRIT_X3_CHAR_CLASS(gurmukhi) + BOOST_SPIRIT_X3_CHAR_CLASS(hangul) + BOOST_SPIRIT_X3_CHAR_CLASS(han) + BOOST_SPIRIT_X3_CHAR_CLASS(hanunoo) + BOOST_SPIRIT_X3_CHAR_CLASS(hebrew) + BOOST_SPIRIT_X3_CHAR_CLASS(hiragana) + BOOST_SPIRIT_X3_CHAR_CLASS(katakana_or_hiragana) + BOOST_SPIRIT_X3_CHAR_CLASS(old_italic) + BOOST_SPIRIT_X3_CHAR_CLASS(javanese) + BOOST_SPIRIT_X3_CHAR_CLASS(kayah_li) + BOOST_SPIRIT_X3_CHAR_CLASS(katakana) + BOOST_SPIRIT_X3_CHAR_CLASS(kharoshthi) + BOOST_SPIRIT_X3_CHAR_CLASS(khmer) + BOOST_SPIRIT_X3_CHAR_CLASS(kannada) + BOOST_SPIRIT_X3_CHAR_CLASS(kaithi) + BOOST_SPIRIT_X3_CHAR_CLASS(tai_tham) + BOOST_SPIRIT_X3_CHAR_CLASS(lao) + BOOST_SPIRIT_X3_CHAR_CLASS(latin) + BOOST_SPIRIT_X3_CHAR_CLASS(lepcha) + BOOST_SPIRIT_X3_CHAR_CLASS(limbu) + BOOST_SPIRIT_X3_CHAR_CLASS(linear_b) + BOOST_SPIRIT_X3_CHAR_CLASS(lisu) + BOOST_SPIRIT_X3_CHAR_CLASS(lycian) + BOOST_SPIRIT_X3_CHAR_CLASS(lydian) + BOOST_SPIRIT_X3_CHAR_CLASS(malayalam) + BOOST_SPIRIT_X3_CHAR_CLASS(mongolian) + BOOST_SPIRIT_X3_CHAR_CLASS(meetei_mayek) + BOOST_SPIRIT_X3_CHAR_CLASS(myanmar) + BOOST_SPIRIT_X3_CHAR_CLASS(nko) + BOOST_SPIRIT_X3_CHAR_CLASS(ogham) + BOOST_SPIRIT_X3_CHAR_CLASS(ol_chiki) + BOOST_SPIRIT_X3_CHAR_CLASS(old_turkic) + BOOST_SPIRIT_X3_CHAR_CLASS(oriya) + BOOST_SPIRIT_X3_CHAR_CLASS(osmanya) + BOOST_SPIRIT_X3_CHAR_CLASS(phags_pa) + BOOST_SPIRIT_X3_CHAR_CLASS(inscriptional_pahlavi) + BOOST_SPIRIT_X3_CHAR_CLASS(phoenician) + BOOST_SPIRIT_X3_CHAR_CLASS(inscriptional_parthian) + BOOST_SPIRIT_X3_CHAR_CLASS(rejang) + BOOST_SPIRIT_X3_CHAR_CLASS(runic) + BOOST_SPIRIT_X3_CHAR_CLASS(samaritan) + BOOST_SPIRIT_X3_CHAR_CLASS(old_south_arabian) + BOOST_SPIRIT_X3_CHAR_CLASS(saurashtra) + BOOST_SPIRIT_X3_CHAR_CLASS(shavian) + BOOST_SPIRIT_X3_CHAR_CLASS(sinhala) + BOOST_SPIRIT_X3_CHAR_CLASS(sundanese) + BOOST_SPIRIT_X3_CHAR_CLASS(syloti_nagri) + BOOST_SPIRIT_X3_CHAR_CLASS(syriac) + BOOST_SPIRIT_X3_CHAR_CLASS(tagbanwa) + BOOST_SPIRIT_X3_CHAR_CLASS(tai_le) + BOOST_SPIRIT_X3_CHAR_CLASS(new_tai_lue) + BOOST_SPIRIT_X3_CHAR_CLASS(tamil) + BOOST_SPIRIT_X3_CHAR_CLASS(tai_viet) + BOOST_SPIRIT_X3_CHAR_CLASS(telugu) + BOOST_SPIRIT_X3_CHAR_CLASS(tifinagh) + BOOST_SPIRIT_X3_CHAR_CLASS(tagalog) + BOOST_SPIRIT_X3_CHAR_CLASS(thaana) + BOOST_SPIRIT_X3_CHAR_CLASS(thai) + BOOST_SPIRIT_X3_CHAR_CLASS(tibetan) + BOOST_SPIRIT_X3_CHAR_CLASS(ugaritic) + BOOST_SPIRIT_X3_CHAR_CLASS(vai) + BOOST_SPIRIT_X3_CHAR_CLASS(old_persian) + BOOST_SPIRIT_X3_CHAR_CLASS(cuneiform) + BOOST_SPIRIT_X3_CHAR_CLASS(yi) + BOOST_SPIRIT_X3_CHAR_CLASS(inherited) + BOOST_SPIRIT_X3_CHAR_CLASS(common) + BOOST_SPIRIT_X3_CHAR_CLASS(unknown) + } + +#undef BOOST_SPIRIT_X3_CHAR_CLASS + +}}} + +#endif diff --git a/boost/spirit/home/x3/core.hpp b/boost/spirit/home/x3/core.hpp new file mode 100644 index 0000000000..a4f875e38a --- /dev/null +++ b/boost/spirit/home/x3/core.hpp @@ -0,0 +1,20 @@ +/*============================================================================= + 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_CORE_APRIL_04_2012_0318PM) +#define BOOST_SPIRIT_X3_CORE_APRIL_04_2012_0318PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/core/parse.hpp> +//~ #include <boost/spirit/home/x3/core/parse_attr.hpp> +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/core/skip_over.hpp> +#include <boost/spirit/home/x3/core/action.hpp> + +#endif diff --git a/boost/spirit/home/x3/core/action.hpp b/boost/spirit/home/x3/core/action.hpp new file mode 100644 index 0000000000..890933fff1 --- /dev/null +++ b/boost/spirit/home/x3/core/action.hpp @@ -0,0 +1,120 @@ +/*============================================================================= + Copyright (arg) 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(SPIRIT_ACTION_JANUARY_07_2007_1128AM) +#define SPIRIT_ACTION_JANUARY_07_2007_1128AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/context.hpp> +#include <boost/spirit/home/x3/support/traits/attribute_of.hpp> +#include <boost/spirit/home/x3/support/traits/make_attribute.hpp> +#include <boost/spirit/home/x3/core/call.hpp> +#include <boost/spirit/home/x3/nonterminal/detail/transform_attribute.hpp> +#include <boost/range/iterator_range.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + struct raw_attribute_type; + struct parse_pass_context_tag; + + template <typename Context> + inline bool& _pass(Context const& context) + { + return x3::get<parse_pass_context_tag>(context); + } + + template <typename Subject, typename Action> + struct action : unary_parser<Subject, action<Subject, Action>> + { + typedef unary_parser<Subject, action<Subject, Action>> base_type; + static bool const is_pass_through_unary = true; + static bool const has_action = true; + + action(Subject const& subject, Action f) + : base_type(subject), f(f) {} + + template <typename Iterator, typename Context, typename RuleContext, typename Attribute> + bool call_action( + Iterator& first, Iterator const& last + , Context const& context, RuleContext& rcontext, Attribute& attr) const + { + bool pass = true; + auto action_context = make_context<parse_pass_context_tag>(pass, context); + call(f, first, last, action_context, rcontext, attr); + return pass; + } + + template <typename Iterator, typename Context + , typename RuleContext, typename Attribute> + bool parse_main(Iterator& first, Iterator const& last + , Context const& context, RuleContext& rcontext, Attribute& attr) const + { + Iterator save = first; + if (this->subject.parse(first, last, context, rcontext, attr)) + { + if (call_action(first, last, context, rcontext, attr)) + return true; + + // reset iterators if semantic action failed the match + // retrospectively + first = save; + } + return false; + } + + // attr==raw_attribute_type, action wants iterator_range (see raw.hpp) + template <typename Iterator, typename Context, typename RuleContext> + bool parse_main(Iterator& first, Iterator const& last + , Context const& context, RuleContext& rcontext, raw_attribute_type&) const + { + boost::iterator_range<Iterator> rng; + // synthesize the attribute since one is not supplied + return parse_main(first, last, context, rcontext, rng); + } + + // attr==unused, action wants attribute + template <typename Iterator, typename Context, typename RuleContext> + bool parse(Iterator& first, Iterator const& last + , Context const& context, RuleContext& rcontext, unused_type) const + { + typedef typename + traits::attribute_of<action<Subject, Action>, Context>::type + attribute_type; + typedef traits::make_attribute<attribute_type, unused_type> make_attribute; + typedef traits::transform_attribute< + typename make_attribute::type, attribute_type, parser_id> + transform; + + // synthesize the attribute since one is not supplied + typename make_attribute::type made_attr = make_attribute::call(unused_type()); + typename transform::type attr = transform::pre(made_attr); + return parse_main(first, last, context, rcontext, attr); + } + + // main parse function + template <typename Iterator, typename Context + , typename RuleContext, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, RuleContext& rcontext, Attribute& attr) const + { + return parse_main(first, last, context, rcontext, attr); + } + + Action f; + }; + + template <typename P, typename Action> + inline action<typename extension::as_parser<P>::value_type, Action> + operator/(P const& p, Action f) + { + return {as_parser(p), f}; + } +}}} + +#endif diff --git a/boost/spirit/home/x3/core/call.hpp b/boost/spirit/home/x3/core/call.hpp new file mode 100644 index 0000000000..a4139751df --- /dev/null +++ b/boost/spirit/home/x3/core/call.hpp @@ -0,0 +1,79 @@ +/*============================================================================= + 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(SPIRIT_CALL_CONTEXT_MAY_26_2014_0234PM) +#define SPIRIT_CALL_CONTEXT_MAY_26_2014_0234PM + +#include <type_traits> + +#include <boost/spirit/home/x3/support/context.hpp> +#include <boost/spirit/home/x3/support/utility/is_callable.hpp> +#include <boost/range/iterator_range.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + //////////////////////////////////////////////////////////////////////////// + struct rule_val_context_tag; + + template <typename Context> + inline auto _val(Context const& context) + -> decltype(x3::get<rule_val_context_tag>(context)) + { + return x3::get<rule_val_context_tag>(context); + } + + //////////////////////////////////////////////////////////////////////////// + struct where_context_tag; + + template <typename Context> + inline auto _where(Context const& context) + -> decltype(x3::get<where_context_tag>(context)) + { + return x3::get<where_context_tag>(context); + } + + //////////////////////////////////////////////////////////////////////////// + struct attr_context_tag; + + template <typename Context> + inline auto _attr(Context const& context) + -> decltype(x3::get<attr_context_tag>(context)) + { + return x3::get<attr_context_tag>(context); + } + + //////////////////////////////////////////////////////////////////////////// + namespace detail + { + template <typename F, typename Context> + auto call(F f, Context const& context, mpl::true_) + { + return f(context); + } + + template <typename F, typename Context> + auto call(F f, Context const& context, mpl::false_) + { + return f(); + } + } + + template < + typename F, typename Iterator + , typename Context, typename RuleContext, typename Attribute> + auto call( + F f, Iterator& first, Iterator const& last + , Context const& context, RuleContext& rcontext, Attribute& attr) + { + boost::iterator_range<Iterator> rng(first, last); + auto val_context = make_context<rule_val_context_tag>(rcontext, context); + auto where_context = make_context<where_context_tag>(rng, val_context); + auto attr_context = make_context<attr_context_tag>(attr, where_context); + return detail::call(f, attr_context, is_callable<F(decltype(attr_context) const&)>()); + } +}}} + +#endif diff --git a/boost/spirit/home/x3/core/detail/parse_into_container.hpp b/boost/spirit/home/x3/core/detail/parse_into_container.hpp new file mode 100644 index 0000000000..4b19115a67 --- /dev/null +++ b/boost/spirit/home/x3/core/detail/parse_into_container.hpp @@ -0,0 +1,248 @@ +/*============================================================================= + 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(SPIRIT_PARSE_INTO_CONTAINER_JAN_15_2013_0957PM) +#define SPIRIT_PARSE_INTO_CONTAINER_JAN_15_2013_0957PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <type_traits> + +#include <boost/spirit/home/x3/support/traits/container_traits.hpp> +#include <boost/spirit/home/x3/support/traits/value_traits.hpp> +#include <boost/spirit/home/x3/support/traits/attribute_of.hpp> +#include <boost/spirit/home/x3/support/traits/handles_container.hpp> +#include <boost/spirit/home/x3/support/traits/has_attribute.hpp> +#include <boost/spirit/home/x3/support/traits/is_substitute.hpp> +#include <boost/spirit/home/x3/support/traits/move_to.hpp> +#include <boost/mpl/and.hpp> +#include <boost/fusion/include/front.hpp> +#include <boost/fusion/include/back.hpp> +#include <boost/variant/apply_visitor.hpp> + +namespace boost { namespace spirit { namespace x3 { namespace detail +{ + template <typename Attribute, typename Value> + struct saver_visitor; + + // save to associative fusion container where Key is simple type + template <typename Key, typename Enable = void> + struct save_to_assoc_attr + { + template <typename Value, typename Attribute> + static void call(const Key, Value& value, Attribute& attr) + { + traits::move_to(value, fusion::at_key<Key>(attr)); + } + }; + + + // save to associative fusion container where Key + // is variant over possible keys + template <typename ...T> + struct save_to_assoc_attr<variant<T...> > + { + typedef variant<T...> variant_t; + + template <typename Value, typename Attribute> + static void call(const variant_t key, Value& value, Attribute& attr) + { + apply_visitor(saver_visitor<Attribute, Value>(attr, value), key); + } + }; + + template <typename Attribute, typename Value> + struct saver_visitor : boost::static_visitor<void> + { + saver_visitor(Attribute& attr, Value& value) + : attr(attr), value(value) {}; + + Attribute& attr; + Value& value; + + template <typename Key> + void operator()(Key) const + { + save_to_assoc_attr<Key>::call(Key(), value,attr); + } + }; + + + template <typename Parser> + struct parse_into_container_base_impl + { + private: + + // Parser has attribute (synthesize; Attribute is a container) + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + static bool call_synthesize( + Parser const& parser + , Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) + { + // synthesized attribute needs to be value initialized + typedef typename + traits::container_value<Attribute>::type + value_type; + value_type val = traits::value_initialize<value_type>::call(); + + if (!parser.parse(first, last, context, rcontext, val)) + return false; + + // push the parsed value into our attribute + traits::push_back(attr, val); + return true; + } + + // Parser has attribute (synthesize; Attribute is a single element fusion sequence) + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + static bool call_synthesize_into_fusion_seq(Parser const& parser + , Iterator& first, Iterator const& last, Context const& context + , RContext& rcontext, Attribute& attr, mpl::false_ /* is_associative */) + { + static_assert(traits::has_size<Attribute, 1>::value, + "Expecting a single element fusion sequence"); + return call_synthesize(parser, first, last, context, rcontext, + fusion::front(attr)); + } + + // Parser has attribute (synthesize; Attribute is fusion map sequence) + template <typename Iterator, typename Context, typename RContext, typename Attribute> + static bool call_synthesize_into_fusion_seq( + Parser const& parser + , Iterator& first, Iterator const& last, Context const& context + , RContext& rcontext, Attribute& attr, mpl::true_ /*is_associative*/) + { + using attribute_type = typename traits::attribute_of<Parser, Context>::type; + static_assert(traits::has_size<attribute_type, 2>::value, + "To parse directly into fusion map parser must produce 2 element attr"); + + // use type of first element of attribute as key + using key = typename std::remove_reference< + typename fusion::result_of::front<attribute_type>::type>::type; + + attribute_type attr_; + if (!parser.parse(first, last, context, rcontext, attr_)) + return false; + + save_to_assoc_attr<key>::call(fusion::front(attr_), fusion::back(attr_), attr); + return true; + } + + template <typename Iterator, typename Context, typename RContext, typename Attribute> + static bool call_synthesize_dispatch_by_seq(Parser const& parser + , Iterator& first, Iterator const& last, Context const& context + , RContext& rcontext, Attribute& attr, mpl::true_ /*is_sequence*/) + { + return call_synthesize_into_fusion_seq( + parser, first, last, context, rcontext, attr + , fusion::traits::is_associative<Attribute>()); + } + + template <typename Iterator, typename Context, typename RContext, typename Attribute> + static bool call_synthesize_dispatch_by_seq(Parser const& parser + , Iterator& first, Iterator const& last, Context const& context + , RContext& rcontext, Attribute& attr, mpl::false_ /*is_sequence*/) + { + return call_synthesize(parser, first, last, context, rcontext, attr); + } + + // Parser has attribute (synthesize) + template <typename Iterator, typename Context, typename RContext, typename Attribute> + static bool call(Parser const& parser + , Iterator& first, Iterator const& last, Context const& context + , RContext& rcontext, Attribute& attr, mpl::true_) + { + return call_synthesize_dispatch_by_seq(parser, first, last, context, rcontext, attr + , fusion::traits::is_sequence<Attribute>()); + } + + // Parser has no attribute (pass unused) + template <typename Iterator, typename Context, typename RContext, typename Attribute> + static bool call( + Parser const& parser + , Iterator& first, Iterator const& last, Context const& context + , RContext& rcontext, Attribute& attr, mpl::false_) + { + return parser.parse(first, last, context, rcontext, unused); + } + + + public: + + template <typename Iterator, typename Context, typename RContext, typename Attribute> + static bool call(Parser const& parser + , Iterator& first, Iterator const& last, Context const& context + , RContext& rcontext, Attribute& attr) + { + return call(parser, first, last, context, rcontext, attr + , mpl::bool_<traits::has_attribute<Parser, Context>::value>()); + } + }; + + template <typename Parser, typename Context, typename RContext, typename Enable = void> + struct parse_into_container_impl : parse_into_container_base_impl<Parser> {}; + + template <typename Parser, typename Container, typename RContext, typename Context> + struct parser_attr_is_substitute_for_container_value + : traits::is_substitute< + typename traits::attribute_of<Parser, Context>::type + , typename traits::container_value<Container>::type + > + {}; + + template <typename Parser, typename Context, typename RContext> + struct parse_into_container_impl<Parser, Context, RContext, + typename enable_if<traits::handles_container<Parser, Context>>::type> + { + template <typename Iterator, typename Attribute> + static bool call( + Parser const& parser + , Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr, mpl::true_) + { + return parse_into_container_base_impl<Parser>::call( + parser, first, last, context, rcontext, attr); + } + + template <typename Iterator, typename Attribute> + static bool call( + Parser const& parser + , Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr, mpl::false_) + { + return parser.parse(first, last, context, rcontext, attr); + } + + template <typename Iterator, typename Attribute> + static bool call(Parser const& parser + , Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) + { + return call(parser, first, last, context, rcontext, attr, + parser_attr_is_substitute_for_container_value< + Parser, Attribute, Context, RContext>()); + } + }; + + template <typename Parser, typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse_into_container( + Parser const& parser + , Iterator& first, Iterator const& last, Context const& context + , RContext& rcontext, Attribute& attr) + { + return parse_into_container_impl<Parser, Context, RContext>::call( + parser, first, last, context, rcontext, attr); + } + +}}}} + +#endif diff --git a/boost/spirit/home/x3/core/parse.hpp b/boost/spirit/home/x3/core/parse.hpp new file mode 100644 index 0000000000..ac36e3c7ea --- /dev/null +++ b/boost/spirit/home/x3/core/parse.hpp @@ -0,0 +1,190 @@ +/*============================================================================= + 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_PARSE_APRIL_16_2006_0442PM) +#define BOOST_SPIRIT_X3_PARSE_APRIL_16_2006_0442PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/context.hpp> +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/core/skip_over.hpp> +#include <boost/concept_check.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + /////////////////////////////////////////////////////////////////////////// + template <typename Iterator, typename Parser, typename Attribute> + inline bool + parse_main( + Iterator& first + , Iterator last + , Parser const& p + , Attribute& attr) + { + // Make sure the iterator is at least a forward_iterator. If you got a + // compilation error here, then you are using an input_iterator while + // calling this function. You need to supply at least a forward_iterator + // instead. + BOOST_CONCEPT_ASSERT((ForwardIterator<Iterator>)); + + // If you get an error no matching function for call to 'as_parser' + // here, then p is not a parser or there is no suitable conversion + // from p to a parser. + return as_parser(p).parse(first, last, unused, unused, attr); + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Iterator, typename Parser, typename Attribute> + inline bool + parse( + Iterator& first + , Iterator last + , Parser const& p + , Attribute& attr) + { + return parse_main(first, last, p, attr); + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Iterator, typename Parser, typename Attribute> + inline bool + parse( + Iterator const& first_ + , Iterator last + , Parser const& p + , Attribute& attr) + { + Iterator first = first_; + return parse_main(first, last, p, attr); + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Iterator, typename Parser> + inline bool + parse( + Iterator& first + , Iterator last + , Parser const& p) + { + return parse_main(first, last, p, unused); + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Iterator, typename Parser> + inline bool + parse( + Iterator const& first_ + , Iterator last + , Parser const& p) + { + Iterator first = first_; + return parse_main(first, last, p, unused); + } + + /////////////////////////////////////////////////////////////////////////// + enum class skip_flag + { + post_skip, // force post-skipping in phrase_parse() + dont_post_skip // inhibit post-skipping in phrase_parse() + }; + + /////////////////////////////////////////////////////////////////////////// + template <typename Iterator, typename Parser, typename Skipper, typename Attribute> + inline bool + phrase_parse_main( + Iterator& first + , Iterator last + , Parser const& p + , Skipper const& s + , Attribute& attr + , skip_flag post_skip = skip_flag::post_skip) + { + // Make sure the iterator is at least a forward_iterator. If you got a + // compilation error here, then you are using an input_iterator while + // calling this function. You need to supply at least a forward_iterator + // instead. + BOOST_CONCEPT_ASSERT((ForwardIterator<Iterator>)); + + // If you get an error no matching function for call to 'as_parser' + // here, for either p or s, then p or s is not a parser or there is + // no suitable conversion from p to a parser. + auto skipper_ctx = make_context<skipper_tag>(as_parser(s)); + bool r = as_parser(p).parse(first, last, skipper_ctx, unused, attr); + if (post_skip == skip_flag::post_skip) + x3::skip_over(first, last, skipper_ctx); + return r; + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Iterator, typename Parser, typename Skipper, typename Attribute> + inline bool + phrase_parse( + Iterator& first + , Iterator last + , Parser const& p + , Skipper const& s + , Attribute& attr + , skip_flag post_skip = skip_flag::post_skip) + { + return phrase_parse_main(first, last, p, s, attr, post_skip); + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Iterator, typename Parser, typename Skipper, typename Attribute> + inline bool + phrase_parse( + Iterator const& first_ + , Iterator last + , Parser const& p + , Skipper const& s + , Attribute& attr + , skip_flag post_skip = skip_flag::post_skip) + { + Iterator first = first_; + return phrase_parse_main(first, last, p, s, attr, post_skip); + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Iterator, typename Parser, typename Skipper> + inline bool + phrase_parse( + Iterator& first + , Iterator last + , Parser const& p + , Skipper const& s + , skip_flag post_skip = skip_flag::post_skip) + { + return phrase_parse_main(first, last, p, s, unused, post_skip); + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Iterator, typename Parser, typename Skipper> + inline bool + phrase_parse( + Iterator const& first_ + , Iterator last + , Parser const& p + , Skipper const& s + , skip_flag post_skip = skip_flag::post_skip) + { + Iterator first = first_; + return phrase_parse_main(first, last, p, s, unused, post_skip); + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Skipper> + struct phrase_parse_context + { + typedef decltype( + make_context<skipper_tag>(as_parser(std::declval<Skipper>()))) + type; + }; +}}} + +#endif diff --git a/boost/spirit/home/x3/core/parser.hpp b/boost/spirit/home/x3/core/parser.hpp new file mode 100644 index 0000000000..bc63a7438b --- /dev/null +++ b/boost/spirit/home/x3/core/parser.hpp @@ -0,0 +1,239 @@ +/*============================================================================= + 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_PARSER_OCTOBER_16_2008_0254PM) +#define BOOST_SPIRIT_X3_PARSER_OCTOBER_16_2008_0254PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/mpl/bool.hpp> +#include <boost/type_traits/is_base_of.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/utility/declval.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/spirit/home/x3/support/unused.hpp> +#include <boost/spirit/home/x3/support/context.hpp> +#include <boost/spirit/home/x3/support/traits/has_attribute.hpp> +#include <boost/spirit/home/x3/support/utility/sfinae.hpp> +#include <string> + +#if !defined(BOOST_SPIRIT_X3_NO_RTTI) +#include <typeinfo> +#endif + +namespace boost { namespace spirit { namespace x3 +{ + using x3::unused_type; + using x3::unused; + using x3::get; + + template <typename Subject, typename Action> + struct action; + + template <typename Subject, typename Handler> + struct guard; + + struct parser_base {}; + struct parser_id; + + template <typename Derived> + struct parser : parser_base + { + typedef Derived derived_type; + static bool const handles_container = false; + static bool const is_pass_through_unary = false; + static bool const has_action = false; + + Derived const& derived() const + { + return *static_cast<Derived const*>(this); + } + + template <typename Action> + action<Derived, Action> + operator[](Action f) const + { + return action<Derived, Action>(this->derived(), f); + } + + template <typename Handler> + guard<Derived, Handler> + on_error(Handler f) const + { + return guard<Derived, Handler>(this->derived(), f); + } + }; + + struct unary_category; + struct binary_category; + + template <typename Subject, typename Derived> + struct unary_parser : parser<Derived> + { + typedef unary_category category; + typedef Subject subject_type; + static bool const has_action = Subject::has_action; + + unary_parser(Subject subject) + : subject(subject) {} + + unary_parser const& get_unary() const { return *this; } + + Subject subject; + }; + + template <typename Left, typename Right, typename Derived> + struct binary_parser : parser<Derived> + { + typedef binary_category category; + typedef Left left_type; + typedef Right right_type; + static bool const has_action = + left_type::has_action || right_type::has_action; + + binary_parser(Left left, Right right) + : left(left), right(right) {} + + binary_parser const& get_binary() const { return *this; } + + Left left; + Right right; + }; + + /////////////////////////////////////////////////////////////////////////// + // as_parser: convert a type, T, into a parser. + /////////////////////////////////////////////////////////////////////////// + namespace extension + { + namespace detail + { + namespace as_parser_guard + { + void as_spirit_parser(...); + + template<typename T, typename R = + decltype(as_spirit_parser(boost::declval<T const&>()))> + struct deduce_as_parser + { + typedef R type; + typedef typename + boost::remove_cv< + typename boost::remove_reference<R>::type + >::type + value_type; + + static type call(T const& v) + { + return as_spirit_parser(v); + } + }; + template<typename T> + struct deduce_as_parser<T, void> + {}; + } + using as_parser_guard::deduce_as_parser; + } + + template <typename T, typename Enable = void> + struct as_parser : detail::deduce_as_parser<T> {}; + + template <> + struct as_parser<unused_type> + { + typedef unused_type type; + typedef unused_type value_type; + static type call(unused_type) + { + return unused; + } + }; + + template <typename Derived> + struct as_parser<Derived + , typename enable_if<is_base_of<parser_base, Derived>>::type> + { + typedef Derived const& type; + typedef Derived value_type; + static type call(Derived const& p) + { + return p; + } + }; + + template <typename Derived> + struct as_parser<parser<Derived>> + { + typedef Derived const& type; + typedef Derived value_type; + static type call(parser<Derived> const& p) + { + return p.derived(); + } + }; + } + + template <typename T> + inline typename extension::as_parser<T>::type + as_parser(T const& x) + { + return extension::as_parser<T>::call(x); + } + + template <typename Derived> + inline Derived const& + as_parser(parser<Derived> const& p) + { + return p.derived(); + } + + /////////////////////////////////////////////////////////////////////////// + // The main what function + // + // Note: unlike Spirit2, spirit parsers are no longer required to have a + // "what" member function. In X3, we specialize the get_info struct + // below where needed. If a specialization is not provided, the default + // below will be used. The default "what" result will be the typeid + // name of the parser if BOOST_SPIRIT_X3_NO_RTTI is not defined, otherwise + // "undefined" + /////////////////////////////////////////////////////////////////////////// + template <typename Parser, typename Enable = void> + struct get_info + { + typedef std::string result_type; + std::string operator()(Parser const&) const + { +#if !defined(BOOST_SPIRIT_X3_NO_RTTI) + return typeid(Parser).name(); +#else + return "undefined"; +#endif + } + }; + + template <typename Parser> + std::string what(Parser const& p) + { + return get_info<Parser>()(p); + } +}}} + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + template <typename Subject, typename Derived, typename Context> + struct has_attribute<x3::unary_parser<Subject, Derived>, Context> + : has_attribute<Subject, Context> {}; + + template <typename Left, typename Right, typename Derived, typename Context> + struct has_attribute<x3::binary_parser<Left, Right, Derived>, Context> + : mpl::bool_<has_attribute<Left, Context>::value || + has_attribute<Right, Context>::value> {}; +}}}} + +#endif diff --git a/boost/spirit/home/x3/core/proxy.hpp b/boost/spirit/home/x3/core/proxy.hpp new file mode 100644 index 0000000000..1a0ade59a8 --- /dev/null +++ b/boost/spirit/home/x3/core/proxy.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_PROXY_FEBRUARY_1_2013_0211PM) +#define BOOST_SPIRIT_X3_PROXY_FEBRUARY_1_2013_0211PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/core/detail/parse_into_container.hpp> +#include <boost/spirit/home/x3/support/traits/attribute_category.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename Subject, typename Derived> + struct proxy : unary_parser<Subject, Derived> + { + static bool const is_pass_through_unary = true; + + proxy(Subject const& subject) + : unary_parser<Subject, Derived>(subject) {} + + // Overload this when appropriate. The proxy parser will pick up + // the most derived overload. + template <typename Iterator, typename Context + , typename RuleContext, typename Attribute, typename Category> + bool parse_subject(Iterator& first, Iterator const& last + , Context const& context, RuleContext& rcontext, Attribute& attr, Category) const + { + this->subject.parse(first, last, context, rcontext, attr); + return true; + } + + // Main entry point. + template <typename Iterator, typename Context + , typename RuleContext, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, RuleContext& rcontext, Attribute& attr) const + { + return this->derived().parse_subject(first, last, context, rcontext, attr + , typename traits::attribute_category<Attribute>::type()); + } + }; + +}}} + +#endif diff --git a/boost/spirit/home/x3/core/skip_over.hpp b/boost/spirit/home/x3/core/skip_over.hpp new file mode 100644 index 0000000000..643ddb1f5b --- /dev/null +++ b/boost/spirit/home/x3/core/skip_over.hpp @@ -0,0 +1,104 @@ +/*============================================================================= + 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_SKIP_APRIL_16_2006_0625PM) +#define BOOST_SPIRIT_X3_SKIP_APRIL_16_2006_0625PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/unused.hpp> +#include <boost/spirit/home/x3/support/context.hpp> +#include <boost/spirit/home/x3/support/traits/attribute_category.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/mpl/not.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/utility/declval.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + /////////////////////////////////////////////////////////////////////////// + // Move the /first/ iterator to the first non-matching position + // given a skip-parser. The function is a no-op if unused_type or + // unused_skipper is passed as the skip-parser. + /////////////////////////////////////////////////////////////////////////// + template <typename Skipper> + struct unused_skipper : unused_type + { + unused_skipper(Skipper const& skipper) + : skipper(skipper) {} + Skipper const& skipper; + }; + + namespace detail + { + template <typename Skipper> + struct is_unused_skipper + : mpl::false_ {}; + + template <typename Skipper> + struct is_unused_skipper<unused_skipper<Skipper>> + : mpl::true_ {}; + + template <> + struct is_unused_skipper<unused_type> + : mpl::true_ {}; + + template <typename Skipper> + inline Skipper const& + get_unused_skipper(Skipper const& skipper) + { + return skipper; + } + template <typename Skipper> + inline Skipper const& + get_unused_skipper(unused_skipper<Skipper> const& unused_skipper) + { + return unused_skipper.skipper; + } + + template <typename Iterator, typename Skipper> + inline void skip_over( + Iterator& first, Iterator const& last, Skipper const& skipper) + { + while (first != last && skipper.parse(first, last, unused, unused, unused)) + /***/; + } + + template <typename Iterator> + inline void skip_over(Iterator&, Iterator const&, unused_type) + { + } + + template <typename Iterator, typename Skipper> + inline void skip_over( + Iterator&, Iterator const&, unused_skipper<Skipper> const&) + { + } + } + + // this tag is used to find the skipper from the context + struct skipper_tag; + + template <typename Context> + struct has_skipper + : mpl::not_<detail::is_unused_skipper< + typename remove_cv<typename remove_reference< + decltype(x3::get<skipper_tag>(boost::declval<Context>())) + >::type>::type + >> {}; + + template <typename Iterator, typename Context> + inline void skip_over( + Iterator& first, Iterator const& last, Context const& context) + { + detail::skip_over(first, last, x3::get<skipper_tag>(context)); + } +}}} + +#endif diff --git a/boost/spirit/home/x3/directive.hpp b/boost/spirit/home/x3/directive.hpp new file mode 100644 index 0000000000..81f7a8536a --- /dev/null +++ b/boost/spirit/home/x3/directive.hpp @@ -0,0 +1,28 @@ +/*============================================================================= + 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_DIRECTIVE_FEBRUARY_05_2007_0313PM) +#define BOOST_SPIRIT_X3_DIRECTIVE_FEBRUARY_05_2007_0313PM + +#if defined(_MSC_VER) +#pragma once +#endif + +//~ #include <boost/spirit/home/x3/directive/as.hpp> +//~ #include <boost/spirit/home/x3/directive/encoding.hpp> +//~ #include <boost/spirit/home/x3/directive/hold.hpp> +#include <boost/spirit/home/x3/directive/expect.hpp> +#include <boost/spirit/home/x3/directive/lexeme.hpp> +#include <boost/spirit/home/x3/directive/no_skip.hpp> +//~ #include <boost/spirit/home/x3/directive/matches.hpp> +//~ #include <boost/spirit/home/x3/directive/no_case.hpp> +#include <boost/spirit/home/x3/directive/omit.hpp> +#include <boost/spirit/home/x3/directive/raw.hpp> +//~ #include <boost/spirit/home/x3/directive/repeat.hpp> +#include <boost/spirit/home/x3/directive/skip.hpp> +#include <boost/spirit/home/x3/directive/with.hpp> + +#endif diff --git a/boost/spirit/home/x3/directive/expect.hpp b/boost/spirit/home/x3/directive/expect.hpp new file mode 100644 index 0000000000..4e59ce5dca --- /dev/null +++ b/boost/spirit/home/x3/directive/expect.hpp @@ -0,0 +1,80 @@ +/*============================================================================= + 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(SPIRIT_EXPECT_MARCH_16_2012_1024PM) +#define SPIRIT_EXPECT_MARCH_16_2012_1024PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/context.hpp> +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/throw_exception.hpp> +#include <stdexcept> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename Iterator> + struct expectation_failure : std::runtime_error + { + public: + + expectation_failure(Iterator where, std::string const& which) + : std::runtime_error("boost::spirit::x3::expectation_failure") + , where_(where), which_(which) + {} + ~expectation_failure() throw() {} + + std::string which() const { return which_; } + Iterator const& where() const { return where_; } + + private: + + Iterator where_; + std::string which_; + }; + + template <typename Subject> + struct expect_directive : unary_parser<Subject, expect_directive<Subject>> + { + typedef unary_parser<Subject, expect_directive<Subject> > base_type; + static bool const is_pass_through_unary = true; + + expect_directive(Subject const& subject) + : base_type(subject) {} + + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) const + { + bool r = this->subject.parse(first, last, context, rcontext, attr); + + if (!r) + { + boost::throw_exception( + expectation_failure<Iterator>( + first, what(this->subject))); + } + return r; + } + }; + + struct expect_gen + { + template <typename Subject> + expect_directive<typename extension::as_parser<Subject>::value_type> + operator[](Subject const& subject) const + { + return {as_parser(subject)}; + } + }; + + expect_gen const expect = expect_gen(); +}}} + +#endif diff --git a/boost/spirit/home/x3/directive/lexeme.hpp b/boost/spirit/home/x3/directive/lexeme.hpp new file mode 100644 index 0000000000..e5104272f9 --- /dev/null +++ b/boost/spirit/home/x3/directive/lexeme.hpp @@ -0,0 +1,84 @@ +/*============================================================================= + 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(SPIRIT_LEXEME_MARCH_24_2007_0802AM) +#define SPIRIT_LEXEME_MARCH_24_2007_0802AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/context.hpp> +#include <boost/spirit/home/x3/support/unused.hpp> +#include <boost/spirit/home/x3/core/skip_over.hpp> +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/utility/enable_if.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename Subject> + struct lexeme_directive : unary_parser<Subject, lexeme_directive<Subject>> + { + typedef unary_parser<Subject, lexeme_directive<Subject> > base_type; + static bool const is_pass_through_unary = true; + static bool const handles_container = Subject::handles_container; + + lexeme_directive(Subject const& subject) + : base_type(subject) {} + + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + typename enable_if<has_skipper<Context>, bool>::type + parse(Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) const + { + x3::skip_over(first, last, context); + auto const& skipper = x3::get<skipper_tag>(context); + + typedef unused_skipper< + typename remove_reference<decltype(skipper)>::type> + unused_skipper_type; + unused_skipper_type unused_skipper(skipper); + + return this->subject.parse( + first, last + , make_context<skipper_tag>(unused_skipper, context) + , rcontext + , attr); + } + + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + typename disable_if<has_skipper<Context>, bool>::type + parse(Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) const + { + // no need to pre-skip if skipper is unused + //- x3::skip_over(first, last, context); + + return this->subject.parse( + first, last + , context + , rcontext + , attr); + } + }; + + struct lexeme_gen + { + template <typename Subject> + lexeme_directive<typename extension::as_parser<Subject>::value_type> + operator[](Subject const& subject) const + { + return {as_parser(subject)}; + } + }; + + lexeme_gen const lexeme = lexeme_gen(); +}}} + +#endif diff --git a/boost/spirit/home/x3/directive/no_skip.hpp b/boost/spirit/home/x3/directive/no_skip.hpp new file mode 100644 index 0000000000..14dee4d85c --- /dev/null +++ b/boost/spirit/home/x3/directive/no_skip.hpp @@ -0,0 +1,82 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + 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(SPIRIT_NO_SKIP_JAN_16_2010_0802PM) +#define SPIRIT_NO_SKIP_JAN_16_2010_0802PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/context.hpp> +#include <boost/spirit/home/x3/support/unused.hpp> +#include <boost/spirit/home/x3/core/skip_over.hpp> +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/utility/enable_if.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + // same as lexeme[], but does not pre-skip + template <typename Subject> + struct no_skip_directive : unary_parser<Subject, no_skip_directive<Subject>> + { + typedef unary_parser<Subject, no_skip_directive<Subject> > base_type; + static bool const is_pass_through_unary = true; + static bool const handles_container = Subject::handles_container; + + no_skip_directive(Subject const& subject) + : base_type(subject) {} + + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + typename enable_if<has_skipper<Context>, bool>::type + parse(Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) const + { + auto const& skipper = x3::get<skipper_tag>(context); + + typedef unused_skipper< + typename remove_reference<decltype(skipper)>::type> + unused_skipper_type; + unused_skipper_type unused_skipper(skipper); + + return this->subject.parse( + first, last + , make_context<skipper_tag>(unused_skipper, context) + , rcontext + , attr); + } + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + typename disable_if<has_skipper<Context>, bool>::type + parse(Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) const + { + return this->subject.parse( + first, last + , context + , rcontext + , attr); + } + }; + + struct no_skip_gen + { + template <typename Subject> + no_skip_directive<typename extension::as_parser<Subject>::value_type> + operator[](Subject const& subject) const + { + return {as_parser(subject)}; + } + }; + + no_skip_gen const no_skip = no_skip_gen(); +}}} + +#endif diff --git a/boost/spirit/home/x3/directive/omit.hpp b/boost/spirit/home/x3/directive/omit.hpp new file mode 100644 index 0000000000..43ebd49aaf --- /dev/null +++ b/boost/spirit/home/x3/directive/omit.hpp @@ -0,0 +1,55 @@ +/*============================================================================= + 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(SPIRIT_OMIT_MARCH_24_2007_0802AM) +#define SPIRIT_OMIT_MARCH_24_2007_0802AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/unused.hpp> +#include <boost/spirit/home/x3/core/parser.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + /////////////////////////////////////////////////////////////////////////// + // omit_directive forces the attribute of subject parser + // to be unused_type + /////////////////////////////////////////////////////////////////////////// + template <typename Subject> + struct omit_directive : unary_parser<Subject, omit_directive<Subject>> + { + typedef unary_parser<Subject, omit_directive<Subject> > base_type; + typedef unused_type attribute_type; + static bool const has_attribute = false; + + typedef Subject subject_type; + omit_directive(Subject const& subject) + : base_type(subject) {} + + template <typename Iterator, typename Context, typename RContext> + bool parse(Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, unused_type) const + { + return this->subject.parse(first, last, context, rcontext, unused); + } + }; + + struct omit_gen + { + template <typename Subject> + omit_directive<typename extension::as_parser<Subject>::value_type> + operator[](Subject const& subject) const + { + return {as_parser(subject)}; + } + }; + + omit_gen const omit = omit_gen(); +}}} + +#endif diff --git a/boost/spirit/home/x3/directive/raw.hpp b/boost/spirit/home/x3/directive/raw.hpp new file mode 100644 index 0000000000..e6bcd9a3a1 --- /dev/null +++ b/boost/spirit/home/x3/directive/raw.hpp @@ -0,0 +1,70 @@ +/*============================================================================= + 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(SPIRIT_X3_RAW_APRIL_9_2007_0912AM) +#define SPIRIT_X3_RAW_APRIL_9_2007_0912AM + +#include <boost/spirit/home/x3/core/skip_over.hpp> +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/support/traits/move_to.hpp> +#include <boost/range/iterator_range.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + // this is a pseudo attribute type indicating that the parser wants the + // iterator range pointing to the [first, last) matching characters from + // the input iterators. + struct raw_attribute_type {}; + + template <typename Subject> + struct raw_directive : unary_parser<Subject, raw_directive<Subject>> + { + typedef unary_parser<Subject, raw_directive<Subject> > base_type; + typedef raw_attribute_type attribute_type; + static bool const handles_container = Subject::handles_container; + typedef Subject subject_type; + + raw_directive(Subject const& subject) + : base_type(subject) {} + + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) const + { + x3::skip_over(first, last, context); + Iterator i = first; + if (this->subject.parse(i, last, context, rcontext, unused)) + { + traits::move_to(first, i, attr); + first = i; + return true; + } + return false; + } + + template <typename Iterator, typename Context, typename RContext> + bool parse(Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, unused_type) const + { + return this->subject.parse(first, last, context, rcontext, unused); + } + }; + + struct raw_gen + { + template <typename Subject> + raw_directive<typename extension::as_parser<Subject>::value_type> + operator[](Subject const& subject) const + { + return {as_parser(subject)}; + } + }; + + raw_gen const raw = raw_gen(); +}}} + +#endif diff --git a/boost/spirit/home/x3/directive/skip.hpp b/boost/spirit/home/x3/directive/skip.hpp new file mode 100644 index 0000000000..c880720791 --- /dev/null +++ b/boost/spirit/home/x3/directive/skip.hpp @@ -0,0 +1,124 @@ +/*============================================================================= + 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(SPIRIT_SKIP_JANUARY_26_2008_0422PM) +#define SPIRIT_SKIP_JANUARY_26_2008_0422PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/context.hpp> +#include <boost/spirit/home/x3/support/unused.hpp> +#include <boost/spirit/home/x3/core/skip_over.hpp> +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/utility/enable_if.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename Subject> + struct reskip_directive : unary_parser<Subject, reskip_directive<Subject>> + { + typedef unary_parser<Subject, reskip_directive<Subject>> base_type; + static bool const is_pass_through_unary = true; + static bool const handles_container = Subject::handles_container; + + reskip_directive(Subject const& subject) + : base_type(subject) {} + + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + typename disable_if<has_skipper<Context>, bool>::type + parse(Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) const + { + auto const& skipper = + detail::get_unused_skipper(x3::get<skipper_tag>(context)); + + return this->subject.parse( + first, last + , make_context<skipper_tag>(skipper, context) + , rcontext + , attr); + } + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + typename enable_if<has_skipper<Context>, bool>::type + parse(Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) const + { + return this->subject.parse( + first, last + , context + , rcontext + , attr); + } + }; + + template <typename Subject, typename Skipper> + struct skip_directive : unary_parser<Subject, skip_directive<Subject, Skipper>> + { + typedef unary_parser<Subject, skip_directive<Subject, Skipper>> base_type; + static bool const is_pass_through_unary = true; + static bool const handles_container = Subject::handles_container; + + skip_directive(Subject const& subject, Skipper const& skipper) + : base_type(subject) + , skipper(skipper) + {} + + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) const + { + return this->subject.parse( + first, last + , make_context<skipper_tag>(skipper, context) + , rcontext + , attr); + } + + Skipper const skipper; + }; + + struct reskip_gen + { + template <typename Skipper> + struct skip_gen + { + explicit skip_gen(Skipper const& skipper) + : skipper_(skipper) {} + + template <typename Subject> + skip_directive<typename extension::as_parser<Subject>::value_type, Skipper> + operator[](Subject const& subject) const + { + return {as_parser(subject), skipper_}; + } + + Skipper skipper_; + }; + + template <typename Skipper> + skip_gen<Skipper> const operator()(Skipper const& skipper) const + { + return skip_gen<Skipper>(skipper); + } + + template <typename Subject> + reskip_directive<typename extension::as_parser<Subject>::value_type> + operator[](Subject const& subject) const + { + return {as_parser(subject)}; + } + }; + + reskip_gen const skip = reskip_gen(); +}}} + +#endif diff --git a/boost/spirit/home/x3/directive/with.hpp b/boost/spirit/home/x3/directive/with.hpp new file mode 100644 index 0000000000..cc6c442a34 --- /dev/null +++ b/boost/spirit/home/x3/directive/with.hpp @@ -0,0 +1,107 @@ +/*============================================================================= + 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(SPIRIT_X3_WITH_MAY_02_2014_0749AM) +#define SPIRIT_X3_WITH_MAY_02_2014_0749AM + +#include <boost/spirit/home/x3/support/unused.hpp> +#include <boost/spirit/home/x3/core/parser.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + /////////////////////////////////////////////////////////////////////////// + // with directive injects a value into the context prior to parsing. + /////////////////////////////////////////////////////////////////////////// + template <typename Subject, typename Derived, typename T> + struct with_value_holder + : unary_parser<Subject, Derived> + { + typedef unary_parser<Subject, Derived> base_type; + mutable T val; + with_value_holder(Subject const& subject, T const& val) + : base_type(subject) + , val(val) {} + }; + + template <typename Subject, typename Derived, typename T> + struct with_value_holder<Subject, Derived, T const> + : unary_parser<Subject, Derived> + { + typedef unary_parser<Subject, Derived> base_type; + T val; + with_value_holder(Subject const& subject, T const& val) + : base_type(subject) + , val(val) {} + }; + + template <typename Subject, typename ID, typename T> + struct with_directive + : with_value_holder<Subject, with_directive<Subject, ID, T>, T> + { + typedef with_value_holder<Subject, with_directive<Subject, ID, T>, T> base_type; + static bool const is_pass_through_unary = true; + static bool const handles_container = Subject::handles_container; + + typedef Subject subject_type; + + with_directive(Subject const& subject, T const& val) + : base_type(subject, val) {} + + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) const + { + return this->subject.parse( + first, last + , make_context<ID>(this->val, context) + , rcontext + , attr); + } + }; + + template <typename ID, typename T, typename NextContext = unused_type> + struct with_context + { + typedef context<ID, T, NextContext> type; + }; + + template <typename ID, typename T> + struct with_context<ID, T, unused_type> + { + typedef context<ID, T> const type; + }; + + template <typename ID, typename T> + struct with_gen + { + T& val; + + with_gen(T& val) + : val(val) {} + + template <typename Subject> + with_directive<typename extension::as_parser<Subject>::value_type, ID, T> + operator[](Subject const& subject) const + { + return {as_parser(subject), val}; + } + }; + + template <typename ID, typename T> + inline with_gen<ID, T> with(T& val) + { + return with_gen<ID, T>{val}; + } + + template <typename ID, typename T> + inline with_gen<ID, T const> with(T const& val) + { + return with_gen<ID, T const>{val}; + } +}}} + +#endif diff --git a/boost/spirit/home/x3/extensions.hpp b/boost/spirit/home/x3/extensions.hpp new file mode 100644 index 0000000000..a40b719c35 --- /dev/null +++ b/boost/spirit/home/x3/extensions.hpp @@ -0,0 +1,18 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2014 Thomas Bernard + Copyright (c) 2014 Lee Clagett + + 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_EXTENSIONS_APRIL_6_2014_1421PM) +#define BOOST_SPIRIT_X3_EXTENSIONS_APRIL_6_2014_1421PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/extensions/seek.hpp> + +#endif diff --git a/boost/spirit/home/x3/extensions/seek.hpp b/boost/spirit/home/x3/extensions/seek.hpp new file mode 100644 index 0000000000..bcd9544794 --- /dev/null +++ b/boost/spirit/home/x3/extensions/seek.hpp @@ -0,0 +1,70 @@ +/*============================================================================= + Copyright (c) 2011 Jamboree + Copyright (c) 2014 Lee Clagett + + 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_SEEK_APRIL_13_2014_1920PM) +#define BOOST_SPIRIT_X3_SEEK_APRIL_13_2014_1920PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/core/parser.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template<typename Subject> + struct seek_directive : unary_parser<Subject, seek_directive<Subject>> + { + typedef unary_parser<Subject, seek_directive<Subject>> base_type; + static bool const is_pass_through_unary = true; + static bool const handles_container = Subject::handles_container; + + seek_directive(Subject const& subject) : + base_type(subject) {} + + template<typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse( + Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) const + { + Iterator current(first); + for (/**/; current != last; ++current) + { + if (this->subject.parse(current, last, context, rcontext, attr)) + { + first = current; + return true; + } + } + + // Test for when subjects match on input empty. Example: + // comment = "//" >> seek[eol | eoi] + if (this->subject.parse(current, last, context, rcontext, attr)) + { + first = current; + return true; + } + + return false; + } + }; + + struct seek_gen + { + template<typename Subject> + seek_directive<typename extension::as_parser<Subject>::value_type> + operator[](Subject const& subject) const + { + return {as_parser(subject)}; + } + }; + + seek_gen const seek = seek_gen(); +}}} + +#endif diff --git a/boost/spirit/home/x3/nonterminal.hpp b/boost/spirit/home/x3/nonterminal.hpp new file mode 100644 index 0000000000..1e589bd903 --- /dev/null +++ b/boost/spirit/home/x3/nonterminal.hpp @@ -0,0 +1,19 @@ +/*============================================================================= + 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_NONTERMINAL_FEBRUARY_12_2007_1018AM) +#define BOOST_SPIRIT_X3_NONTERMINAL_FEBRUARY_12_2007_1018AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/nonterminal/rule.hpp> +//~ #include <boost/spirit/home/x3/nonterminal/error_handler.hpp> +//~ #include <boost/spirit/home/x3/nonterminal/debug_handler.hpp> +//~ #include <boost/spirit/home/x3/nonterminal/success_handler.hpp> + +#endif diff --git a/boost/spirit/home/x3/nonterminal/debug_handler_state.hpp b/boost/spirit/home/x3/nonterminal/debug_handler_state.hpp new file mode 100644 index 0000000000..800023f013 --- /dev/null +++ b/boost/spirit/home/x3/nonterminal/debug_handler_state.hpp @@ -0,0 +1,24 @@ +/*============================================================================= + 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_DEBUG_HANDLER_STATE_APR_21_2010_0733PM) +#define BOOST_SPIRIT_X3_DEBUG_HANDLER_STATE_APR_21_2010_0733PM + +#if defined(_MSC_VER) +#pragma once +#endif + +namespace boost { namespace spirit { namespace x3 +{ + enum debug_handler_state + { + pre_parse + , successful_parse + , failed_parse + }; +}}} + +#endif diff --git a/boost/spirit/home/x3/nonterminal/detail/rule.hpp b/boost/spirit/home/x3/nonterminal/detail/rule.hpp new file mode 100644 index 0000000000..54e2eef234 --- /dev/null +++ b/boost/spirit/home/x3/nonterminal/detail/rule.hpp @@ -0,0 +1,385 @@ +/*============================================================================= + 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_DETAIL_RULE_JAN_08_2012_0326PM) +#define BOOST_SPIRIT_X3_DETAIL_RULE_JAN_08_2012_0326PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/support/traits/make_attribute.hpp> +#include <boost/spirit/home/x3/support/utility/sfinae.hpp> +#include <boost/spirit/home/x3/nonterminal/detail/transform_attribute.hpp> +#include <boost/utility/addressof.hpp> + +#if defined(BOOST_SPIRIT_X3_DEBUG) +#include <boost/spirit/home/x3/nonterminal/simple_trace.hpp> +#endif + +namespace boost { namespace spirit { namespace x3 +{ + template <typename ID> + struct identity; + + template <typename ID, typename Attribute = unused_type> + struct rule; + + struct parse_pass_context_tag; + + namespace detail + { + // we use this so we can detect if the default parse_rule + // is the being called. + struct default_parse_rule_result + { + default_parse_rule_result(bool r) + : r(r) {} + operator bool() const { return r; } + bool r; + }; + } + + // default parse_rule implementation + template <typename ID, typename Attribute, typename Iterator + , typename Context, typename ActualAttribute> + inline detail::default_parse_rule_result + parse_rule( + rule<ID, Attribute> rule_ + , Iterator& first, Iterator const& last + , Context const& context, ActualAttribute& attr); +}}} + +namespace boost { namespace spirit { namespace x3 { namespace detail +{ +#if defined(BOOST_SPIRIT_X3_DEBUG) + template <typename Iterator, typename Attribute> + struct context_debug + { + context_debug( + char const* rule_name + , Iterator const& first, Iterator const& last + , Attribute const& attr + , bool const& ok_parse //was parse successful? + ) + : ok_parse(ok_parse), rule_name(rule_name) + , first(first), last(last) + , attr(attr) + , f(detail::get_simple_trace()) + { + f(first, last, attr, pre_parse, rule_name); + } + + ~context_debug() + { + auto status = ok_parse ? successful_parse : failed_parse ; + f(first, last, attr, status, rule_name); + } + + bool const& ok_parse; + char const* rule_name; + Iterator const& first; + Iterator const& last; + Attribute const& attr; + detail::simple_trace_type& f; + }; +#endif + + template <typename ID, typename Iterator, typename Context, typename Enable = void> + struct has_on_error : mpl::false_ {}; + + template <typename ID, typename Iterator, typename Context> + struct has_on_error<ID, Iterator, Context, + typename disable_if_substitution_failure< + decltype( + std::declval<ID>().on_error( + std::declval<Iterator&>() + , std::declval<Iterator>() + , std::declval<expectation_failure<Iterator>>() + , std::declval<Context>() + ) + )>::type + > + : mpl::true_ + {}; + + template <typename ID, typename Iterator, typename Attribute, typename Context, typename Enable = void> + struct has_on_success : mpl::false_ {}; + + template <typename ID, typename Iterator, typename Attribute, typename Context> + struct has_on_success<ID, Iterator, Context, Attribute, + typename disable_if_substitution_failure< + decltype( + std::declval<ID>().on_success( + std::declval<Iterator&>() + , std::declval<Iterator>() + , std::declval<Attribute&>() + , std::declval<Context>() + ) + )>::type + > + : mpl::true_ + {}; + + template <typename ID> + struct make_id + { + typedef identity<ID> type; + }; + + template <typename ID> + struct make_id<identity<ID>> + { + typedef identity<ID> type; + }; + + template <typename ID, typename RHS, typename Context> + Context const& + make_rule_context(RHS const& rhs, Context const& context + , mpl::false_ /* is_default_parse_rule */) + { + return context; + } + + template <typename ID, typename RHS, typename Context> + auto make_rule_context(RHS const& rhs, Context const& context + , mpl::true_ /* is_default_parse_rule */ ) + { + return make_unique_context<ID>(rhs, context); + } + + template <typename Attribute, typename ID> + struct rule_parser + { + template <typename Iterator, typename Context, typename ActualAttribute> + static bool call_on_success( + Iterator& first, Iterator const& last + , Context const& context, ActualAttribute& attr + , mpl::false_ /* No on_success handler */ ) + { + return true; + } + + template <typename Iterator, typename Context, typename ActualAttribute> + static bool call_on_success( + Iterator& first, Iterator const& last + , Context const& context, ActualAttribute& attr + , mpl::true_ /* Has on_success handler */) + { + bool pass = true; + ID().on_success( + first + , last + , attr + , make_context<parse_pass_context_tag>(pass, context) + ); + return pass; + } + + template <typename RHS, typename Iterator, typename Context + , typename RContext, typename ActualAttribute> + static bool parse_rhs_main( + RHS const& rhs + , Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, ActualAttribute& attr + , mpl::false_) + { + // see if the user has a BOOST_SPIRIT_DEFINE for this rule + typedef + decltype(parse_rule( + rule<ID, Attribute>(), first, last + , make_unique_context<ID>(rhs, context), attr)) + parse_rule_result; + + // If there is no BOOST_SPIRIT_DEFINE for this rule, + // we'll make a context for this rule tagged by its ID + // so we can extract the rule later on in the default + // (generic) parse_rule function. + typedef + is_same<parse_rule_result, default_parse_rule_result> + is_default_parse_rule; + + Iterator i = first; + bool r = rhs.parse( + i + , last + , make_rule_context<ID>(rhs, context, is_default_parse_rule()) + , rcontext + , attr + ); + + if (r) + { + auto first_ = first; + x3::skip_over(first_, last, context); + r = call_on_success(first_, i, context, attr + , has_on_success<ID, Iterator, Context, ActualAttribute>()); + } + + if (r) + first = i; + return r; + } + + template <typename RHS, typename Iterator, typename Context + , typename RContext, typename ActualAttribute> + static bool parse_rhs_main( + RHS const& rhs + , Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, ActualAttribute& attr + , mpl::true_ /* on_error is found */) + { + for (;;) + { + try + { + return parse_rhs_main( + rhs, first, last, context, rcontext, attr, mpl::false_()); + } + catch (expectation_failure<Iterator> const& x) + { + switch (ID().on_error(first, last, x, context)) + { + case error_handler_result::fail: + return false; + case error_handler_result::retry: + continue; + case error_handler_result::accept: + return true; + case error_handler_result::rethrow: + throw; + } + } + } + } + + template <typename RHS, typename Iterator + , typename Context, typename RContext, typename ActualAttribute> + static bool parse_rhs_main( + RHS const& rhs + , Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, ActualAttribute& attr) + { + return parse_rhs_main( + rhs, first, last, context, rcontext, attr + , has_on_error<ID, Iterator, Context>() + ); + } + + template <typename RHS, typename Iterator + , typename Context, typename RContext, typename ActualAttribute> + static bool parse_rhs( + RHS const& rhs + , Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, ActualAttribute& attr + , mpl::false_) + { + return parse_rhs_main(rhs, first, last, context, rcontext, attr); + } + + template <typename RHS, typename Iterator + , typename Context, typename RContext, typename ActualAttribute> + static bool parse_rhs( + RHS const& rhs + , Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, ActualAttribute& attr + , mpl::true_) + { + return parse_rhs_main(rhs, first, last, context, rcontext, unused); + } + + template <typename RHS, typename Iterator, typename Context + , typename ActualAttribute, typename ExplicitAttrPropagation> + static bool call_rule_definition( + RHS const& rhs + , char const* rule_name + , Iterator& first, Iterator const& last + , Context const& context, ActualAttribute& attr + , ExplicitAttrPropagation) + { + typedef traits::make_attribute<Attribute, ActualAttribute> make_attribute; + + // do down-stream transformation, provides attribute for + // rhs parser + typedef traits::transform_attribute< + typename make_attribute::type, Attribute, parser_id> + transform; + + typedef typename make_attribute::value_type value_type; + typedef typename transform::type transform_attr; + value_type made_attr = make_attribute::call(attr); + transform_attr attr_ = transform::pre(made_attr); + + bool ok_parse + //Creates a place to hold the result of parse_rhs + //called inside the following scope. + ; + { + //Create a scope to cause the dbg variable below (within + //the #if...#endif) to call it's DTOR before any + //modifications are made to the attribute, attr_ passed + //to parse_rhs (such as might be done in + //traits::post_transform when, for example, + //ActualAttribute is a recursive variant). +#if defined(BOOST_SPIRIT_X3_DEBUG) + context_debug<Iterator, typename make_attribute::value_type> + dbg(rule_name, first, last, attr_, ok_parse); +#endif + ok_parse=parse_rhs(rhs, first, last, context, attr_, attr_ + , mpl::bool_ + < ( RHS::has_action + && !ExplicitAttrPropagation::value + ) + >() + ); + } + if(ok_parse) + { + // do up-stream transformation, this integrates the results + // back into the original attribute value, if appropriate + traits::post_transform(attr, attr_); + } + return ok_parse; + } + +// template <typename RuleDef, typename Iterator, typename Context +// , typename ActualAttribute, typename AttributeContext> +// static bool call_from_rule( +// RuleDef const& rule_def +// , char const* rule_name +// , Iterator& first, Iterator const& last +// , Context const& context, ActualAttribute& attr, AttributeContext& attr_ctx) +// { +// // This is called when a rule-body has already been established. +// // The rule body is already established by the rule_definition class, +// // we will not do it again. We'll simply call the RHS by calling +// // call_rule_definition. +// +// return call_rule_definition( +// rule_def.rhs, rule_name, first, last +// , context, attr, attr_ctx.attr_ptr +// , mpl::bool_<(RuleDef::explicit_attribute_propagation)>()); +// } +// +// template <typename RuleDef, typename Iterator, typename Context +// , typename ActualAttribute> +// static bool call_from_rule( +// RuleDef const& rule_def +// , char const* rule_name +// , Iterator& first, Iterator const& last +// , Context const& context, ActualAttribute& attr, unused_type) +// { +// // This is called when a rule-body has *not yet* been established. +// // The rule body is established by the rule_definition class, so +// // we call it to parse and establish the rule-body. +// +// return rule_def.parse(first, last, context, unused, attr); // $$$ fix unused param $$$ +// } + }; +}}}} + +#endif diff --git a/boost/spirit/home/x3/nonterminal/detail/transform_attribute.hpp b/boost/spirit/home/x3/nonterminal/detail/transform_attribute.hpp new file mode 100644 index 0000000000..b1929f8993 --- /dev/null +++ b/boost/spirit/home/x3/nonterminal/detail/transform_attribute.hpp @@ -0,0 +1,108 @@ +/*============================================================================= + 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(SPIRIT_X3_DETAIL_ATTRIBUTES_APR_18_2010_0458PM) +#define SPIRIT_X3_DETAIL_ATTRIBUTES_APR_18_2010_0458PM + +#include <boost/spirit/home/x3/support/traits/transform_attribute.hpp> +#include <boost/spirit/home/x3/support/traits/move_to.hpp> + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { namespace x3 +{ + struct parser_id; + + template <typename Exposed, typename Transformed> + struct default_transform_attribute + { + typedef Transformed type; + + static Transformed pre(Exposed&) { return Transformed(); } + + static void post(Exposed& val, Transformed& attr) + { + traits::move_to(attr, val); + } + }; + + // handle case where no transformation is required as the types are the same + template <typename Attribute> + struct default_transform_attribute<Attribute, Attribute> + { + typedef Attribute& type; + static Attribute& pre(Attribute& val) { return val; } + static void post(Attribute&, Attribute const&) {} + }; + + // main specialization for x3 + template <typename Exposed, typename Transformed, typename Enable = void> + struct transform_attribute + : default_transform_attribute<Exposed, Transformed> {}; + + // reference types need special handling + template <typename Attribute> + struct transform_attribute<Attribute&, Attribute> + { + typedef Attribute& type; + static Attribute& pre(Attribute& val) { return val; } + static void post(Attribute&, Attribute const&) {} + }; + + // unused_type needs some special handling as well + template <> + struct transform_attribute<unused_type, unused_type> + { + typedef unused_type type; + static unused_type pre(unused_type) { return unused; } + static void post(unused_type, unused_type) {} + }; + + template <> + struct transform_attribute<unused_type const, unused_type> + : transform_attribute<unused_type, unused_type> {}; + + template <typename Attribute> + struct transform_attribute<unused_type, Attribute> + : transform_attribute<unused_type, unused_type> {}; + + template <typename Attribute> + struct transform_attribute<unused_type const, Attribute> + : transform_attribute<unused_type, unused_type> {}; + + template <typename Attribute> + struct transform_attribute<Attribute, unused_type> + : transform_attribute<unused_type, unused_type> {}; + + template <typename Attribute> + struct transform_attribute<Attribute const, unused_type> + : transform_attribute<unused_type, unused_type> {}; +}}} + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + template <typename Exposed, typename Transformed> + struct transform_attribute<Exposed, Transformed, x3::parser_id> + : x3::transform_attribute<Exposed, Transformed> {}; + + template <typename Exposed, typename Transformed> + struct transform_attribute<Exposed&, Transformed, x3::parser_id> + : transform_attribute<Exposed, Transformed, x3::parser_id> {}; + + template <typename Attribute> + struct transform_attribute<Attribute&, Attribute, x3::parser_id> + : x3::transform_attribute<Attribute&, Attribute> {}; + + /////////////////////////////////////////////////////////////////////////// + template <typename Exposed, typename Transformed> + void post_transform(Exposed& dest, Transformed&& attr) + { + return transform_attribute<Exposed, Transformed, x3::parser_id>::post(dest, attr); + } +}}}} + +#endif diff --git a/boost/spirit/home/x3/nonterminal/rule.hpp b/boost/spirit/home/x3/nonterminal/rule.hpp new file mode 100644 index 0000000000..049c6be57b --- /dev/null +++ b/boost/spirit/home/x3/nonterminal/rule.hpp @@ -0,0 +1,186 @@ +/*============================================================================= + 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_RULE_JAN_08_2012_0326PM) +#define BOOST_SPIRIT_X3_RULE_JAN_08_2012_0326PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/nonterminal/detail/rule.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/spirit/home/x3/support/context.hpp> +#include <boost/preprocessor/variadic/to_seq.hpp> +#include <boost/preprocessor/variadic/elem.hpp> +#include <boost/preprocessor/seq/for_each.hpp> + +#if !defined(BOOST_SPIRIT_X3_NO_RTTI) +#include <typeinfo> +#endif + +namespace boost { namespace spirit { namespace x3 +{ + template <typename ID> + struct identity {}; + + // default parse_rule implementation + template <typename ID, typename Attribute, typename Iterator + , typename Context, typename ActualAttribute> + inline detail::default_parse_rule_result + parse_rule( + rule<ID, Attribute> rule_ + , Iterator& first, Iterator const& last + , Context const& context, ActualAttribute& attr) + { + static_assert(!is_same<decltype(get<ID>(context)), unused_type>::value, + "BOOST_SPIRIT_DEFINE undefined for this rule."); + return get<ID>(context).parse(first, last, context, unused, attr); + } + + template <typename ID, typename RHS, typename Attribute, bool force_attribute_> + struct rule_definition : parser<rule_definition<ID, RHS, Attribute, force_attribute_>> + { + typedef rule_definition<ID, RHS, Attribute, force_attribute_> this_type; + typedef ID id; + typedef RHS rhs_type; + typedef rule<ID, Attribute> lhs_type; + typedef Attribute attribute_type; + + static bool const has_attribute = + !is_same<Attribute, unused_type>::value; + static bool const handles_container = + traits::is_container<Attribute>::value; + static bool const force_attribute = + force_attribute_; + + rule_definition(RHS rhs, char const* name) + : rhs(rhs), name(name) {} + + template <typename Iterator, typename Context, typename Attribute_> + bool parse(Iterator& first, Iterator const& last + , Context const& context, unused_type, Attribute_& attr) const + { + return detail::rule_parser<attribute_type, ID> + ::call_rule_definition( + rhs, name, first, last + , context + , attr + , mpl::bool_<force_attribute>()); + } + + RHS rhs; + char const* name; + }; + + template <typename ID, typename Attribute> + struct rule : parser<rule<ID, Attribute>> + { + typedef ID id; + typedef Attribute attribute_type; + static bool const has_attribute = + !is_same<Attribute, unused_type>::value; + static bool const handles_container = + traits::is_container<Attribute>::value; + +#if !defined(BOOST_SPIRIT_X3_NO_RTTI) + rule() : name(typeid(rule).name()) {} +#else + rule() : name("unnamed") {} +#endif + + rule(char const* name) + : name(name) {} + + template <typename RHS> + rule_definition< + ID, typename extension::as_parser<RHS>::value_type, Attribute, false> + operator=(RHS const& rhs) const + { + return {as_parser(rhs), name}; + } + + template <typename RHS> + rule_definition< + ID, typename extension::as_parser<RHS>::value_type, Attribute, true> + operator%=(RHS const& rhs) const + { + return {as_parser(rhs), name}; + } + + + template <typename Iterator, typename Context, typename Attribute_> + bool parse(Iterator& first, Iterator const& last + , Context const& context, unused_type, Attribute_& attr) const + { + return parse_rule(*this, first, last, context, attr); + } + + char const* name; + }; + + namespace traits + { + template <typename T, typename Enable = void> + struct is_rule : mpl::false_ {}; + + template <typename ID, typename Attribute> + struct is_rule<rule<ID, Attribute>> : mpl::true_ {}; + + template <typename ID, typename Attribute, typename RHS, bool force_attribute> + struct is_rule<rule_definition<ID, RHS, Attribute, force_attribute>> : mpl::true_ {}; + } + + template <typename T> + struct get_info<T, typename enable_if<traits::is_rule<T>>::type> + { + typedef std::string result_type; + std::string operator()(T const& r) const + { + return r.name; + } + }; + +#define BOOST_SPIRIT_DECLARE_(r, data, rule_type) \ + template <typename Iterator, typename Context, typename Attribute> \ + bool parse_rule( \ + rule_type rule_ \ + , Iterator& first, Iterator const& last \ + , Context const& context, Attribute& attr); \ + /***/ + +#define BOOST_SPIRIT_DECLARE(...) BOOST_PP_SEQ_FOR_EACH( \ + BOOST_SPIRIT_DECLARE_, _, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \ + /***/ + +#define BOOST_SPIRIT_DEFINE_(r, data, def) \ + template <typename Iterator, typename Context, typename Attribute> \ + inline bool parse_rule( \ + decltype(def)::lhs_type rule_ \ + , Iterator& first, Iterator const& last \ + , Context const& context, Attribute& attr) \ + { \ + using boost::spirit::x3::unused; \ + auto const& def_ = (def); \ + return def_.parse(first, last, context, unused, attr); \ + } \ + /***/ + +#define BOOST_SPIRIT_DEFINE(...) BOOST_PP_SEQ_FOR_EACH( \ + BOOST_SPIRIT_DEFINE_, _, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \ + /***/ + +#define BOOST_SPIRIT_INSTANTIATE(rule_type, Iterator, Context) \ + template bool parse_rule<Iterator, Context, rule_type::attribute_type>( \ + rule_type rule_ \ + , Iterator& first, Iterator const& last \ + , Context const& context, rule_type::attribute_type& attr); \ + /***/ + + +}}} + +#endif diff --git a/boost/spirit/home/x3/nonterminal/simple_trace.hpp b/boost/spirit/home/x3/nonterminal/simple_trace.hpp new file mode 100644 index 0000000000..b049b4ec3c --- /dev/null +++ b/boost/spirit/home/x3/nonterminal/simple_trace.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_SIMPLE_TRACE_DECEMBER_06_2008_1102AM) +#define BOOST_SPIRIT_X3_SIMPLE_TRACE_DECEMBER_06_2008_1102AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/unused.hpp> +#include <boost/spirit/home/x3/support/traits/print_token.hpp> +#include <boost/spirit/home/x3/support/traits/print_attribute.hpp> +#include <boost/spirit/home/x3/nonterminal/debug_handler_state.hpp> +#include <boost/fusion/include/out.hpp> +#include <boost/type_traits/is_same.hpp> +#include <ostream> + +// The stream to use for debug output +#if !defined(BOOST_SPIRIT_X3_DEBUG_OUT) +#define BOOST_SPIRIT_X3_DEBUG_OUT std::cerr +#endif + +// number of tokens to print while debugging +#if !defined(BOOST_SPIRIT_X3_DEBUG_PRINT_SOME) +#define BOOST_SPIRIT_X3_DEBUG_PRINT_SOME 20 +#endif + +// number of spaces to indent +#if !defined(BOOST_SPIRIT_X3_DEBUG_INDENT) +#define BOOST_SPIRIT_X3_DEBUG_INDENT 2 +#endif + +namespace boost { namespace spirit { namespace x3 +{ + namespace detail + { + template <typename Char> + inline void token_printer(std::ostream& o, Char c) + { + // allow customization of the token printer routine + x3::traits::print_token(o, c); + } + } + + template <int IndentSpaces = 2, int CharsToPrint = 20> + struct simple_trace + { + simple_trace(std::ostream& out) + : out(out), indent(0) {} + + void print_indent(int n) const + { + n *= IndentSpaces; + for (int i = 0; i != n; ++i) + out << ' '; + } + + template <typename Iterator> + void print_some( + char const* tag + , Iterator first, Iterator const& last) const + { + print_indent(indent); + out << '<' << tag << '>'; + int const n = CharsToPrint; + for (int i = 0; first != last && i != n && *first; ++i, ++first) + detail::token_printer(out, *first); + out << "</" << tag << '>' << std::endl; + + // $$$ FIXME convert invalid xml characters (e.g. '<') to valid + // character entities. $$$ + } + + template <typename Iterator, typename Attribute, typename State> + void operator()( + Iterator const& first + , Iterator const& last + , Attribute const& attr + , State state + , std::string const& rule_name) const + { + switch (state) + { + case pre_parse: + print_indent(indent++); + out + << '<' << rule_name << '>' + << std::endl; + print_some("try", first, last); + break; + + case successful_parse: + print_some("success", first, last); + if (!is_same<Attribute, unused_type>::value) + { + print_indent(indent); + out + << "<attributes>"; + traits::print_attribute(out, attr); + out + << "</attributes>"; + out << std::endl; + } + //~ if (!fusion::empty(context.locals)) + //~ out + //~ << "<locals>" + //~ << context.locals + //~ << "</locals>"; + print_indent(--indent); + out + << "</" << rule_name << '>' + << std::endl; + break; + + case failed_parse: + print_indent(indent); + out << "<fail/>" << std::endl; + print_indent(--indent); + out + << "</" << rule_name << '>' + << std::endl; + break; + } + } + + std::ostream& out; + mutable int indent; + }; + + namespace detail + { + typedef simple_trace< + BOOST_SPIRIT_X3_DEBUG_INDENT, BOOST_SPIRIT_X3_DEBUG_PRINT_SOME> + simple_trace_type; + + inline simple_trace_type& + get_simple_trace() + { + static simple_trace_type tracer(BOOST_SPIRIT_X3_DEBUG_OUT); + return tracer; + } + } +}}} + +#endif diff --git a/boost/spirit/home/x3/numeric.hpp b/boost/spirit/home/x3/numeric.hpp new file mode 100644 index 0000000000..c44d668569 --- /dev/null +++ b/boost/spirit/home/x3/numeric.hpp @@ -0,0 +1,19 @@ +/*============================================================================= + 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_NUMERIC_FEBRUARY_05_2007_1231PM) +#define BOOST_SPIRIT_X3_NUMERIC_FEBRUARY_05_2007_1231PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/numeric/bool.hpp> +#include <boost/spirit/home/x3/numeric/int.hpp> +#include <boost/spirit/home/x3/numeric/uint.hpp> +#include <boost/spirit/home/x3/numeric/real.hpp> + +#endif diff --git a/boost/spirit/home/x3/numeric/bool.hpp b/boost/spirit/home/x3/numeric/bool.hpp new file mode 100644 index 0000000000..1fb21c16fe --- /dev/null +++ b/boost/spirit/home/x3/numeric/bool.hpp @@ -0,0 +1,106 @@ +/*============================================================================= + Copyright (c) 2009 Hartmut Kaiser + 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(SPIRIT_X3_BOOL_SEP_29_2009_0709AM) +#define SPIRIT_X3_BOOL_SEP_29_2009_0709AM + +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/core/skip_over.hpp> +#include <boost/spirit/home/x3/numeric/bool_policies.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename T, typename BoolPolicies = bool_policies<T>> + struct bool_parser : parser<bool_parser<T, BoolPolicies>> + { + typedef T attribute_type; + static bool const has_attribute = true; + + bool_parser() + : policies() {} + + bool_parser(BoolPolicies const& policies) + : policies(policies) {} + + template <typename Iterator, typename Context> + bool parse(Iterator& first, Iterator const& last + , Context& context, unused_type, T& attr) const + { + x3::skip_over(first, last, context); + return policies.parse_true(first, last, attr) + || policies.parse_false(first, last, attr); + } + + template <typename Iterator, typename Context, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context& context, unused_type, Attribute& attr_param) const + { + // this case is called when Attribute is not T + T attr_; + if (parse(first, last, context, unused, attr_)) + { + traits::move_to(attr_, attr_param); + return true; + } + return false; + } + + BoolPolicies policies; + }; + + template <typename T, typename BoolPolicies = bool_policies<T>> + struct literal_bool_parser : parser<bool_parser<T, BoolPolicies>> + { + typedef T attribute_type; + static bool const has_attribute = true; + + template <typename Value> + literal_bool_parser(Value const& n) + : policies(), n_(n) {} + + template <typename Value> + literal_bool_parser(Value const& n, BoolPolicies const& policies) + : policies(policies), n_(n) {} + + template <typename Iterator, typename Context> + bool parse(Iterator& first, Iterator const& last + , Context& context, unused_type, T& attr) const + { + x3::skip_over(first, last, context); + return (n_ && policies.parse_true(first, last, attr)) + || (!n_ && policies.parse_false(first, last, attr)); + } + + template <typename Iterator, typename Context, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context& context, unused_type, Attribute& attr_param) const + { + // this case is called when Attribute is not T + T attr_; + if (parse(first, last, context, unused, attr_)) + { + traits::move_to(attr_, attr_param); + return true; + } + return false; + } + + BoolPolicies policies; + T n_; + }; + + typedef bool_parser<bool> bool_type; + bool_type const bool_ = {}; + + typedef literal_bool_parser<bool> true_type; + true_type const true_ = { true }; + + typedef literal_bool_parser<bool> false_type; + false_type const false_ = { false }; +}}} + +#endif diff --git a/boost/spirit/home/x3/numeric/bool_policies.hpp b/boost/spirit/home/x3/numeric/bool_policies.hpp new file mode 100644 index 0000000000..bafc5b5294 --- /dev/null +++ b/boost/spirit/home/x3/numeric/bool_policies.hpp @@ -0,0 +1,52 @@ +/*============================================================================= + Copyright (c) 2009 Hartmut Kaiser + 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(SPIRIT_QI_BOOL_POLICIES_SEP_29_2009_0710AM) +#define SPIRIT_QI_BOOL_POLICIES_SEP_29_2009_0710AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/string/detail/string_parse.hpp> +#include <boost/spirit/home/x3/support/traits/move_to.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + /////////////////////////////////////////////////////////////////////////// + // Default boolean policies + /////////////////////////////////////////////////////////////////////////// + template <typename T = bool> + struct bool_policies + { + template <typename Iterator, typename Attribute> + static bool + parse_true(Iterator& first, Iterator const& last, Attribute& attr_) + { + if (detail::string_parse("true", first, last, unused)) + { + traits::move_to(T(true), attr_); // result is true + return true; + } + return false; + } + + template <typename Iterator, typename Attribute> + static bool + parse_false(Iterator& first, Iterator const& last, Attribute& attr_) + { + if (detail::string_parse("false", first, last, unused)) + { + traits::move_to(T(false), attr_); // result is false + return true; + } + return false; + } + }; +}}} + +#endif diff --git a/boost/spirit/home/x3/numeric/int.hpp b/boost/spirit/home/x3/numeric/int.hpp new file mode 100644 index 0000000000..ba9ceb8243 --- /dev/null +++ b/boost/spirit/home/x3/numeric/int.hpp @@ -0,0 +1,66 @@ +/*============================================================================= + 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_INT_APR_17_2006_0830AM) +#define BOOST_SPIRIT_X3_INT_APR_17_2006_0830AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/core/skip_over.hpp> +#include <boost/spirit/home/x3/support/numeric_utils/extract_int.hpp> +#include <cstdint> + +namespace boost { namespace spirit { namespace x3 +{ + /////////////////////////////////////////////////////////////////////////// + template < + typename T + , unsigned Radix = 10 + , unsigned MinDigits = 1 + , int MaxDigits = -1> + struct int_parser : parser<int_parser<T, Radix, MinDigits, MaxDigits>> + { + // check template parameter 'Radix' for validity + static_assert( + (Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16), + "Error Unsupported Radix"); + + typedef T attribute_type; + static bool const has_attribute = true; + + template <typename Iterator, typename Context, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, unused_type, Attribute& attr) const + { + typedef extract_int<T, Radix, MinDigits, MaxDigits> extract; + x3::skip_over(first, last, context); + return extract::call(first, last, attr); + } + }; + +#define BOOST_SPIRIT_X3_INT_PARSER(int_type, name) \ + typedef int_parser<int_type> name##type; \ + name##type const name = {}; \ + /***/ + + BOOST_SPIRIT_X3_INT_PARSER(long, long_) + BOOST_SPIRIT_X3_INT_PARSER(short, short_) + BOOST_SPIRIT_X3_INT_PARSER(int, int_) + BOOST_SPIRIT_X3_INT_PARSER(long long, long_long) + + BOOST_SPIRIT_X3_INT_PARSER(int8_t, int8) + BOOST_SPIRIT_X3_INT_PARSER(int16_t, int16) + BOOST_SPIRIT_X3_INT_PARSER(int32_t, int32) + BOOST_SPIRIT_X3_INT_PARSER(int64_t, int64) + +#undef BOOST_SPIRIT_X3_INT_PARSER + +}}} + +#endif diff --git a/boost/spirit/home/x3/numeric/real.hpp b/boost/spirit/home/x3/numeric/real.hpp new file mode 100644 index 0000000000..91da536421 --- /dev/null +++ b/boost/spirit/home/x3/numeric/real.hpp @@ -0,0 +1,62 @@ +/*============================================================================= + 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_REAL_APRIL_18_2006_0850AM) +#define BOOST_SPIRIT_X3_REAL_APRIL_18_2006_0850AM + +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/core/skip_over.hpp> +#include <boost/spirit/home/x3/numeric/real_policies.hpp> +#include <boost/spirit/home/x3/support/numeric_utils/extract_real.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename T, typename RealPolicies = real_policies<T> > + struct real_parser : parser<real_parser<T, RealPolicies> > + { + typedef T attribute_type; + static bool const has_attribute = true; + + real_parser() + : policies() {} + + real_parser(RealPolicies const& policies) + : policies(policies) {} + + template <typename Iterator, typename Context> + bool parse(Iterator& first, Iterator const& last + , Context& context, unused_type, T& attr_) const + { + x3::skip_over(first, last, context); + return extract_real<T, RealPolicies>::parse(first, last, attr_, policies); + } + + template <typename Iterator, typename Context, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context& context, unused_type, Attribute& attr_param) const + { + // this case is called when Attribute is not T + T attr_; + if (parse(first, last, context, unused, attr_)) + { + traits::move_to(attr_, attr_param); + return true; + } + return false; + } + + RealPolicies policies; + }; + + typedef real_parser<float> float_type; + float_type const float_ = {}; + + typedef real_parser<double> double_type; + double_type const double_ = {}; + +}}} + +#endif diff --git a/boost/spirit/home/x3/numeric/real_policies.hpp b/boost/spirit/home/x3/numeric/real_policies.hpp new file mode 100644 index 0000000000..4e02b266c5 --- /dev/null +++ b/boost/spirit/home/x3/numeric/real_policies.hpp @@ -0,0 +1,186 @@ +/*============================================================================= + 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(SPIRIT_REAL_POLICIES_APRIL_17_2006_1158PM) +#define SPIRIT_REAL_POLICIES_APRIL_17_2006_1158PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/string/detail/string_parse.hpp> +#include <boost/spirit/home/x3/support/numeric_utils/extract_int.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + /////////////////////////////////////////////////////////////////////////// + // Default (unsigned) real number policies + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct ureal_policies + { + // trailing dot policy suggested by Gustavo Guerra + static bool const allow_leading_dot = true; + static bool const allow_trailing_dot = true; + static bool const expect_dot = false; + + template <typename Iterator> + static bool + parse_sign(Iterator& /*first*/, Iterator const& /*last*/) + { + return false; + } + + template <typename Iterator, typename Attribute> + static bool + parse_n(Iterator& first, Iterator const& last, Attribute& attr_) + { + return extract_uint<T, 10, 1, -1>::call(first, last, attr_); + } + + template <typename Iterator> + static bool + parse_dot(Iterator& first, Iterator const& last) + { + if (first == last || *first != '.') + return false; + ++first; + return true; + } + + template <typename Iterator, typename Attribute> + static bool + parse_frac_n(Iterator& first, Iterator const& last, Attribute& attr_) + { + return extract_uint<T, 10, 1, -1, true>::call(first, last, attr_); + } + + template <typename Iterator> + static bool + parse_exp(Iterator& first, Iterator const& last) + { + if (first == last || (*first != 'e' && *first != 'E')) + return false; + ++first; + return true; + } + + template <typename Iterator> + static bool + parse_exp_n(Iterator& first, Iterator const& last, int& attr_) + { + return extract_int<int, 10, 1, -1>::call(first, last, attr_); + } + + /////////////////////////////////////////////////////////////////////// + // The parse_nan() and parse_inf() functions get called whenever: + // + // - a number to parse does not start with a digit (after having + // successfully parsed an optional sign) + // + // or + // + // - after a floating point number of the value 1 (having no + // exponential part and a fractional part value of 0) has been + // parsed. + // + // The first call allows to recognize representations of NaN or Inf + // starting with a non-digit character (such as NaN, Inf, QNaN etc.). + // + // The second call allows to recognize representation formats starting + // with a 1.0 (such as 1.0#NAN or 1.0#INF etc.). + // + // The functions should return true if a Nan or Inf has been found. In + // this case the attr should be set to the matched value (NaN or + // Inf). The optional sign will be automatically applied afterwards. + // + // The default implementation below recognizes representations of NaN + // and Inf as mandated by the C99 Standard and as proposed for + // inclusion into the C++0x Standard: nan, nan(...), inf and infinity + // (the matching is performed case-insensitively). + /////////////////////////////////////////////////////////////////////// + template <typename Iterator, typename Attribute> + static bool + parse_nan(Iterator& first, Iterator const& last, Attribute& attr_) + { + if (first == last) + return false; // end of input reached + + if (*first != 'n' && *first != 'N') + return false; // not "nan" + + // nan[(...)] ? + if (detail::string_parse("nan", "NAN", first, last, unused)) + { + if (*first == '(') + { + // skip trailing (...) part + Iterator i = first; + + while (++i != last && *i != ')') + ; + if (i == last) + return false; // no trailing ')' found, give up + + first = ++i; + } + attr_ = std::numeric_limits<T>::quiet_NaN(); + return true; + } + return false; + } + + template <typename Iterator, typename Attribute> + static bool + parse_inf(Iterator& first, Iterator const& last, Attribute& attr_) + { + if (first == last) + return false; // end of input reached + + if (*first != 'i' && *first != 'I') + return false; // not "inf" + + // inf or infinity ? + if (detail::string_parse("inf", "INF", first, last, unused)) + { + // skip allowed 'inity' part of infinity + detail::string_parse("inity", "INITY", first, last, unused); + attr_ = std::numeric_limits<T>::infinity(); + return true; + } + return false; + } + }; + + /////////////////////////////////////////////////////////////////////////// + // Default (signed) real number policies + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct real_policies : ureal_policies<T> + { + template <typename Iterator> + static bool + parse_sign(Iterator& first, Iterator const& last) + { + return extract_sign(first, last); + } + }; + + template <typename T> + struct strict_ureal_policies : ureal_policies<T> + { + static bool const expect_dot = true; + }; + + template <typename T> + struct strict_real_policies : real_policies<T> + { + static bool const expect_dot = true; + }; +}}} + +#endif diff --git a/boost/spirit/home/x3/numeric/uint.hpp b/boost/spirit/home/x3/numeric/uint.hpp new file mode 100644 index 0000000000..624bae52de --- /dev/null +++ b/boost/spirit/home/x3/numeric/uint.hpp @@ -0,0 +1,79 @@ +/*============================================================================= + 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_UINT_APR_17_2006_0901AM) +#define BOOST_SPIRIT_X3_UINT_APR_17_2006_0901AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/core/skip_over.hpp> +#include <boost/spirit/home/x3/support/numeric_utils/extract_int.hpp> +#include <cstdint> + +namespace boost { namespace spirit { namespace x3 +{ + /////////////////////////////////////////////////////////////////////////// + template < + typename T + , unsigned Radix = 10 + , unsigned MinDigits = 1 + , int MaxDigits = -1> + struct uint_parser : parser<uint_parser<T, Radix, MinDigits, MaxDigits>> + { + // check template parameter 'Radix' for validity + static_assert( + (Radix >= 2 && Radix <= 36), + "Error Unsupported Radix"); + + typedef T attribute_type; + static bool const has_attribute = true; + + template <typename Iterator, typename Context, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, unused_type, Attribute& attr) const + { + typedef extract_uint<T, Radix, MinDigits, MaxDigits> extract; + x3::skip_over(first, last, context); + return extract::call(first, last, attr); + } + }; + +#define BOOST_SPIRIT_X3_UINT_PARSER(uint_type, name) \ + typedef uint_parser<uint_type> name##type; \ + name##type const name = {}; \ + /***/ + + BOOST_SPIRIT_X3_UINT_PARSER(unsigned long, ulong_) + BOOST_SPIRIT_X3_UINT_PARSER(unsigned short, ushort_) + BOOST_SPIRIT_X3_UINT_PARSER(unsigned int, uint_) + BOOST_SPIRIT_X3_UINT_PARSER(unsigned long long, ulong_long) + + BOOST_SPIRIT_X3_UINT_PARSER(uint8_t, uint8) + BOOST_SPIRIT_X3_UINT_PARSER(uint16_t, uint16) + BOOST_SPIRIT_X3_UINT_PARSER(uint32_t, uint32) + BOOST_SPIRIT_X3_UINT_PARSER(uint64_t, uint64) + +#undef BOOST_SPIRIT_X3_UINT_PARSER + +#define BOOST_SPIRIT_X3_UINT_PARSER(uint_type, radix, name) \ + typedef uint_parser<uint_type, radix> name##type; \ + name##type const name = name##type(); \ + /***/ + + BOOST_SPIRIT_X3_UINT_PARSER(unsigned, 2, bin) + BOOST_SPIRIT_X3_UINT_PARSER(unsigned, 8, oct) + BOOST_SPIRIT_X3_UINT_PARSER(unsigned, 16, hex) + +#undef BOOST_SPIRIT_X3_UINT_PARSER + + +}}} + +#endif diff --git a/boost/spirit/home/x3/operator.hpp b/boost/spirit/home/x3/operator.hpp new file mode 100644 index 0000000000..1244e2f04d --- /dev/null +++ b/boost/spirit/home/x3/operator.hpp @@ -0,0 +1,26 @@ +/*============================================================================= + 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_OPERATOR_FEBRUARY_02_2007_0558PM) +#define BOOST_SPIRIT_X3_OPERATOR_FEBRUARY_02_2007_0558PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/operator/sequence.hpp> +#include <boost/spirit/home/x3/operator/alternative.hpp> +//~ #include <boost/spirit/home/x3/operator/sequential_or.hpp> +//~ #include <boost/spirit/home/x3/operator/permutation.hpp> +#include <boost/spirit/home/x3/operator/difference.hpp> +#include <boost/spirit/home/x3/operator/list.hpp> +#include <boost/spirit/home/x3/operator/optional.hpp> +#include <boost/spirit/home/x3/operator/kleene.hpp> +#include <boost/spirit/home/x3/operator/plus.hpp> +#include <boost/spirit/home/x3/operator/and_predicate.hpp> +#include <boost/spirit/home/x3/operator/not_predicate.hpp> + +#endif diff --git a/boost/spirit/home/x3/operator/alternative.hpp b/boost/spirit/home/x3/operator/alternative.hpp new file mode 100644 index 0000000000..1566780bc6 --- /dev/null +++ b/boost/spirit/home/x3/operator/alternative.hpp @@ -0,0 +1,68 @@ +/*============================================================================= + 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(SPIRIT_ALTERNATIVE_JAN_07_2013_1131AM) +#define SPIRIT_ALTERNATIVE_JAN_07_2013_1131AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/traits/attribute_of.hpp> +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/operator/detail/alternative.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename Left, typename Right> + struct alternative : binary_parser<Left, Right, alternative<Left, Right>> + { + typedef binary_parser<Left, Right, alternative<Left, Right>> base_type; + + alternative(Left left, Right right) + : base_type(left, right) {} + + template <typename Iterator, typename Context, typename RContext> + bool parse( + Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, unused_type) const + { + return this->left.parse(first, last, context, rcontext, unused) + || this->right.parse(first, last, context, rcontext, unused); + } + + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse( + Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) const + { + if (detail::parse_alternative(this->left, first, last, context, rcontext, attr)) + return true; + if (detail::parse_alternative(this->right, first, last, context, rcontext, attr)) + return true; + return false; + } + }; + + template <typename Left, typename Right> + inline alternative< + typename extension::as_parser<Left>::value_type + , typename extension::as_parser<Right>::value_type> + operator|(Left const& left, Right const& right) + { + return {as_parser(left), as_parser(right)}; + } +}}} + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + template <typename Left, typename Right, typename Context> + struct attribute_of<x3::alternative<Left, Right>, Context> + : x3::detail::attribute_of_alternative<Left, Right, Context> {}; +}}}} + +#endif diff --git a/boost/spirit/home/x3/operator/and_predicate.hpp b/boost/spirit/home/x3/operator/and_predicate.hpp new file mode 100644 index 0000000000..e0892cd8cf --- /dev/null +++ b/boost/spirit/home/x3/operator/and_predicate.hpp @@ -0,0 +1,47 @@ +/*============================================================================= + 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(SPIRIT_AND_PREDICATE_MARCH_23_2007_0617PM) +#define SPIRIT_AND_PREDICATE_MARCH_23_2007_0617PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/core/parser.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename Subject> + struct and_predicate : unary_parser<Subject, and_predicate<Subject>> + { + typedef unary_parser<Subject, and_predicate<Subject>> base_type; + + typedef unused_type attribute_type; + static bool const has_attribute = false; + + and_predicate(Subject const& subject) + : base_type(subject) {} + + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& /*attr*/) const + { + Iterator i = first; + return this->subject.parse(i, last, context, rcontext, unused); + } + }; + + template <typename Subject> + inline and_predicate<typename extension::as_parser<Subject>::value_type> + operator&(Subject const& subject) + { + return {as_parser(subject)}; + } +}}} + +#endif diff --git a/boost/spirit/home/x3/operator/detail/alternative.hpp b/boost/spirit/home/x3/operator/detail/alternative.hpp new file mode 100644 index 0000000000..54f86e00df --- /dev/null +++ b/boost/spirit/home/x3/operator/detail/alternative.hpp @@ -0,0 +1,317 @@ +/*============================================================================= + 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(SPIRIT_ALTERNATIVE_DETAIL_JAN_07_2013_1245PM) +#define SPIRIT_ALTERNATIVE_DETAIL_JAN_07_2013_1245PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/traits/attribute_of.hpp> +#include <boost/spirit/home/x3/support/traits/is_variant.hpp> +#include <boost/spirit/home/x3/support/traits/tuple_traits.hpp> +#include <boost/spirit/home/x3/support/traits/move_to.hpp> +#include <boost/spirit/home/x3/support/traits/variant_has_substitute.hpp> +#include <boost/spirit/home/x3/support/traits/variant_find_substitute.hpp> +#include <boost/spirit/home/x3/core/detail/parse_into_container.hpp> +#include <boost/variant/variant.hpp> + +#include <boost/mpl/copy_if.hpp> +#include <boost/mpl/not.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/eval_if.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/joint_view.hpp> + +#include <boost/fusion/include/front.hpp> + +#include <boost/type_traits/is_same.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename Left, typename Right> + struct alternative; +}}} + +namespace boost { namespace spirit { namespace x3 { namespace detail +{ + struct pass_variant_unused + { + typedef unused_type type; + + template <typename T> + static unused_type + call(T&) + { + return unused_type(); + } + }; + + template <typename Attribute> + struct pass_variant_used + { + typedef Attribute& type; + + static Attribute& + call(Attribute& v) + { + return v; + } + }; + + template <> + struct pass_variant_used<unused_type> : pass_variant_unused {}; + + template <typename Parser, typename Attribute, typename Context + , typename Enable = void> + struct pass_parser_attribute + { + typedef typename + traits::attribute_of<Parser, Context>::type + attribute_type; + typedef typename + traits::variant_find_substitute<Attribute, attribute_type>::type + substitute_type; + + typedef typename + mpl::if_< + is_same<Attribute, substitute_type> + , Attribute& + , substitute_type + >::type + type; + + template <typename Attribute_> + static Attribute_& + call(Attribute_& attr, mpl::true_) + { + return attr; + } + + template <typename Attribute_> + static type + call(Attribute_&, mpl::false_) + { + return type(); + } + + template <typename Attribute_> + static type + call(Attribute_& attr) + { + return call(attr, is_same<Attribute_, typename remove_reference<type>::type>()); + } + }; + + // Pass non-variant attributes as-is + template <typename Parser, typename Attribute, typename Context + , typename Enable = void> + struct pass_non_variant_attribute + { + typedef Attribute& type; + + static Attribute& + call(Attribute& attr) + { + return attr; + } + }; + + // Unwrap single element sequences + template <typename Parser, typename Attribute, typename Context> + struct pass_non_variant_attribute<Parser, Attribute, Context, + typename enable_if<traits::is_size_one_sequence<Attribute>>::type> + { + typedef typename remove_reference< + typename fusion::result_of::front<Attribute>::type>::type + attr_type; + + typedef pass_parser_attribute<Parser, attr_type, Context> pass; + typedef typename pass::type type; + + template <typename Attribute_> + static type + call(Attribute_& attr) + { + return pass::call(fusion::front(attr)); + } + }; + + template <typename Parser, typename Attribute, typename Context> + struct pass_parser_attribute<Parser, Attribute, Context, + typename enable_if_c<(!traits::is_variant<Attribute>::value)>::type> + : pass_non_variant_attribute<Parser, Attribute, Context> + {}; + + template <typename Parser, typename Context> + struct pass_parser_attribute<Parser, unused_type, Context> + : pass_variant_unused {}; + + template <typename Parser, typename Attribute, typename Context> + struct pass_variant_attribute : + mpl::if_c<traits::has_attribute<Parser, Context>::value + , pass_parser_attribute<Parser, Attribute, Context> + , pass_variant_unused>::type + { + typedef typename mpl::false_ is_alternative; + }; + + template <typename L, typename R, typename Attribute, typename Context> + struct pass_variant_attribute<alternative<L, R>, Attribute, Context> : + mpl::if_c<traits::has_attribute<alternative<L, R>, Context>::value + , pass_variant_used<Attribute> + , pass_variant_unused>::type + { + typedef typename mpl::true_ is_alternative; + }; + + template <typename L, typename R, typename C> + struct get_alternative_types + { + typedef + mpl::vector< + typename traits::attribute_of<L, C>::type + , typename traits::attribute_of<R, C>::type + > + type; + }; + + template <typename LL, typename LR, typename R, typename C> + struct get_alternative_types<alternative<LL, LR>, R, C> + { + typedef typename + mpl::push_back< + typename get_alternative_types<LL, LR, C>::type + , typename traits::attribute_of<R, C>::type + >::type + type; + }; + + template <typename L, typename RL, typename RR, typename C> + struct get_alternative_types<L, alternative<RL, RR>, C> + { + typedef typename + mpl::push_front< + typename get_alternative_types<RL, RR, C>::type + , typename traits::attribute_of<L, C>::type + >::type + type; + }; + + template <typename LL, typename LR, typename RL, typename RR, typename C> + struct get_alternative_types<alternative<LL, LR>, alternative<RL, RR>, C> + { + typedef + mpl::joint_view< + typename get_alternative_types<LL, LR, C>::type + , typename get_alternative_types<RL, RR, C>::type + > + type; + }; + + template <typename L, typename R, typename C> + struct attribute_of_alternative + { + // Get all alternative attribute types + typedef typename get_alternative_types<L, R, C>::type all_types; + + // Filter all unused_types + typedef typename + mpl::copy_if< + all_types + , mpl::not_<is_same<mpl::_1, unused_type>> + , mpl::back_inserter<mpl::vector<>> + >::type + filtered_types; + + // Build a variant if filtered_types is not empty, + // else just return unused_type + typedef typename + mpl::eval_if< + mpl::empty<filtered_types> + , mpl::identity<unused_type> + , make_variant_over<filtered_types> + >::type + type; + }; + + template <typename IsAlternative> + struct move_if_not_alternative + { + template<typename T1, typename T2> + static void call(T1& attr_, T2& attr) {} + }; + + template <> + struct move_if_not_alternative<mpl::false_ /*is alternative*/> + { + template<typename T1, typename T2> + static void call(T1& attr_, T2& attr) + { + traits::move_to(attr_, attr); + } + }; + + template <typename Parser, typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse_alternative(Parser const& p, Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) + { + typedef detail::pass_variant_attribute<Parser, Attribute, Context> pass; + + typename pass::type attr_ = pass::call(attr); + if (p.parse(first, last, context, rcontext, attr_)) + { + move_if_not_alternative<typename pass::is_alternative>::call(attr_, attr); + return true; + } + return false; + } + + + template <typename Left, typename Right, typename Context, typename RContext> + struct parse_into_container_impl<alternative<Left, Right>, Context, RContext> + { + typedef alternative<Left, Right> parser_type; + + template <typename Iterator, typename Attribute> + static bool call( + parser_type const& parser + , Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr, mpl::true_) + { + return parse_alternative(parser, first, last, context, rcontext, attr); + } + + template <typename Iterator, typename Attribute> + static bool call( + parser_type const& parser + , Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr, mpl::false_) + { + return parse_into_container_base_impl<parser_type>::call( + parser, first, last, context, rcontext, attr); + } + + template <typename Iterator, typename Attribute> + static bool call( + parser_type const& parser + , Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) + { + typedef typename + traits::attribute_of<parser_type, Context>::type + attribute_type; + + return call(parser, first, last, context, rcontext, attr + , traits::variant_has_substitute<attribute_type, Attribute>()); + } + }; + +}}}} + +#endif diff --git a/boost/spirit/home/x3/operator/detail/sequence.hpp b/boost/spirit/home/x3/operator/detail/sequence.hpp new file mode 100644 index 0000000000..1163707128 --- /dev/null +++ b/boost/spirit/home/x3/operator/detail/sequence.hpp @@ -0,0 +1,501 @@ +/*============================================================================= + 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(SPIRIT_SEQUENCE_DETAIL_JAN_06_2013_1015AM) +#define SPIRIT_SEQUENCE_DETAIL_JAN_06_2013_1015AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/traits/attribute_of.hpp> +#include <boost/spirit/home/x3/support/traits/attribute_category.hpp> +#include <boost/spirit/home/x3/support/traits/make_attribute.hpp> +#include <boost/spirit/home/x3/support/traits/has_attribute.hpp> +#include <boost/spirit/home/x3/support/traits/is_substitute.hpp> +#include <boost/spirit/home/x3/support/traits/container_traits.hpp> +#include <boost/spirit/home/x3/core/detail/parse_into_container.hpp> + +#include <boost/fusion/include/begin.hpp> +#include <boost/fusion/include/end.hpp> +#include <boost/fusion/include/advance.hpp> +#include <boost/fusion/include/empty.hpp> +#include <boost/fusion/include/front.hpp> +#include <boost/fusion/include/iterator_range.hpp> +#include <boost/fusion/include/as_deque.hpp> +#include <boost/fusion/include/mpl.hpp> + +#include <boost/mpl/copy_if.hpp> +#include <boost/mpl/not.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/eval_if.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/eval_if.hpp> +#include <boost/mpl/identity.hpp> + +#include <boost/type_traits/add_reference.hpp> +#include <boost/type_traits/is_same.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename Left, typename Right> + struct sequence; +}}} + +namespace boost { namespace spirit { namespace x3 { namespace detail +{ + template <typename Parser, typename Context, typename Enable = void> + struct sequence_size + { + static int const value = traits::has_attribute<Parser, Context>::value; + }; + + template <typename Parser, typename Context> + struct sequence_size_subject + : sequence_size<typename Parser::subject_type, Context> {}; + + template <typename Parser, typename Context> + struct sequence_size<Parser, Context + , typename enable_if_c<(Parser::is_pass_through_unary)>::type> + : sequence_size_subject<Parser, Context> {}; + + template <typename L, typename R, typename Context> + struct sequence_size<sequence<L, R>, Context> + { + static int const value = + sequence_size<L, Context>::value + + sequence_size<R, Context>::value; + }; + + struct pass_sequence_attribute_unused + { + typedef unused_type type; + + template <typename T> + static unused_type + call(T&) + { + return unused_type(); + } + }; + + template <typename Attribute> + struct pass_sequence_attribute_front + { + typedef typename fusion::result_of::front<Attribute>::type type; + + static typename add_reference<type>::type + call(Attribute& attr) + { + return fusion::front(attr); + } + }; + + template <typename Attribute> + struct pass_through_sequence_attribute + { + typedef Attribute& type; + + template <typename Attribute_> + static Attribute_& + call(Attribute_& attr) + { + return attr; + } + }; + + template <typename Parser, typename Attribute> + struct pass_sequence_attribute_used : + mpl::if_< + traits::is_size_one_sequence<Attribute> + , pass_sequence_attribute_front<Attribute> + , pass_through_sequence_attribute<Attribute>>::type {}; + + template <typename Parser, typename Attribute, typename Enable = void> + struct pass_sequence_attribute : + mpl::if_< + fusion::result_of::empty<Attribute> + , pass_sequence_attribute_unused + , pass_sequence_attribute_used<Parser, Attribute>>::type {}; + + template <typename L, typename R, typename Attribute> + struct pass_sequence_attribute<sequence<L, R>, Attribute> + : pass_through_sequence_attribute<Attribute> {}; + + template <typename Parser, typename Attribute> + struct pass_sequence_attribute_subject : + pass_sequence_attribute<typename Parser::subject_type, Attribute> {}; + + template <typename Parser, typename Attribute> + struct pass_sequence_attribute<Parser, Attribute + , typename enable_if_c<(Parser::is_pass_through_unary)>::type> + : pass_sequence_attribute_subject<Parser, Attribute> {}; + + template <typename L, typename R, typename Attribute, typename Context + , typename Enable = void> + struct partition_attribute + { + static int const l_size = sequence_size<L, Context>::value; + static int const r_size = sequence_size<R, Context>::value; + + // If you got an error here, then you are trying to pass + // a fusion sequence with the wrong number of elements + // as that expected by the (sequence) parser. + static_assert( + fusion::result_of::size<Attribute>::value == (l_size + r_size) + , "Attribute does not have the expected size." + ); + + typedef typename fusion::result_of::begin<Attribute>::type l_begin; + typedef typename fusion::result_of::advance_c<l_begin, l_size>::type l_end; + typedef typename fusion::result_of::end<Attribute>::type r_end; + typedef fusion::iterator_range<l_begin, l_end> l_part; + typedef fusion::iterator_range<l_end, r_end> r_part; + typedef pass_sequence_attribute<L, l_part> l_pass; + typedef pass_sequence_attribute<R, r_part> r_pass; + + static l_part left(Attribute& s) + { + auto i = fusion::begin(s); + return l_part(i, fusion::advance_c<l_size>(i)); + } + + static r_part right(Attribute& s) + { + return r_part( + fusion::advance_c<l_size>(fusion::begin(s)) + , fusion::end(s)); + } + }; + + template <typename L, typename R, typename Attribute, typename Context> + struct partition_attribute<L, R, Attribute, Context, + typename enable_if_c<(!traits::has_attribute<L, Context>::value && + traits::has_attribute<R, Context>::value)>::type> + { + typedef unused_type l_part; + typedef Attribute& r_part; + typedef pass_sequence_attribute_unused l_pass; + typedef pass_sequence_attribute<R, Attribute> r_pass; + + static unused_type left(Attribute&) + { + return unused; + } + + static Attribute& right(Attribute& s) + { + return s; + } + }; + + template <typename L, typename R, typename Attribute, typename Context> + struct partition_attribute<L, R, Attribute, Context, + typename enable_if_c<(traits::has_attribute<L, Context>::value && + !traits::has_attribute<R, Context>::value)>::type> + { + typedef Attribute& l_part; + typedef unused_type r_part; + typedef pass_sequence_attribute<L, Attribute> l_pass; + typedef pass_sequence_attribute_unused r_pass; + + static Attribute& left(Attribute& s) + { + return s; + } + + static unused_type right(Attribute&) + { + return unused; + } + }; + + template <typename L, typename R, typename Attribute, typename Context> + struct partition_attribute<L, R, Attribute, Context, + typename enable_if_c<(!traits::has_attribute<L, Context>::value && + !traits::has_attribute<R, Context>::value)>::type> + { + typedef unused_type l_part; + typedef unused_type r_part; + typedef pass_sequence_attribute_unused l_pass; + typedef pass_sequence_attribute_unused r_pass; + + static unused_type left(Attribute&) + { + return unused; + } + + static unused_type right(Attribute&) + { + return unused; + } + }; + + template <typename L, typename R, typename C> + struct get_sequence_types + { + typedef + mpl::vector< + typename traits::attribute_of<L, C>::type + , typename traits::attribute_of<R, C>::type + > + type; + }; + + template <typename LL, typename LR, typename R, typename C> + struct get_sequence_types<sequence<LL, LR>, R, C> + { + typedef typename + mpl::push_back< + typename get_sequence_types<LL, LR, C>::type + , typename traits::attribute_of<R, C>::type + >::type + type; + }; + + template <typename L, typename RL, typename RR, typename C> + struct get_sequence_types<L, sequence<RL, RR>, C> + { + typedef typename + mpl::push_front< + typename get_sequence_types<RL, RR, C>::type + , typename traits::attribute_of<L, C>::type + >::type + type; + }; + + template <typename LL, typename LR, typename RL, typename RR, typename C> + struct get_sequence_types<sequence<LL, LR>, sequence<RL, RR>, C> + { + typedef + mpl::joint_view< + typename get_sequence_types<LL, LR, C>::type + , typename get_sequence_types<RL, RR, C>::type + > + type; + }; + + template <typename L, typename R, typename C> + struct attribute_of_sequence + { + // Get all sequence attribute types + typedef typename get_sequence_types<L, R, C>::type all_types; + + // Filter all unused_types + typedef typename + mpl::copy_if< + all_types + , mpl::not_<is_same<mpl::_1, unused_type>> + , mpl::back_inserter<mpl::vector<>> + >::type + filtered_types; + + // Build a fusion::deque if filtered_types is not empty, + // else just return unused_type + typedef typename + mpl::eval_if< + mpl::empty<filtered_types> + , mpl::identity<unused_type> + , mpl::if_<mpl::equal_to<mpl::size<filtered_types>, mpl::int_<1> >, + typename mpl::front<filtered_types>::type + , typename fusion::result_of::as_deque<filtered_types>::type > + >::type + type; + }; + + template <typename Parser, typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse_sequence( + Parser const& parser, Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr + , traits::tuple_attribute) + { + typedef typename Parser::left_type Left; + typedef typename Parser::right_type Right; + typedef partition_attribute<Left, Right, Attribute, Context> partition; + typedef typename partition::l_pass l_pass; + typedef typename partition::r_pass r_pass; + + typename partition::l_part l_part = partition::left(attr); + typename partition::r_part r_part = partition::right(attr); + typename l_pass::type l_attr = l_pass::call(l_part); + typename r_pass::type r_attr = r_pass::call(r_part); + + Iterator save = first; + if (parser.left.parse(first, last, context, rcontext, l_attr) + && parser.right.parse(first, last, context, rcontext, r_attr)) + return true; + first = save; + return false; + } + + template <typename Parser, typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse_sequence( + Parser const& parser , Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr + , traits::plain_attribute) + { + typedef typename Parser::left_type Left; + typedef typename Parser::right_type Right; + typedef typename traits::attribute_of<Left, Context>::type l_attr_type; + typedef typename traits::attribute_of<Right, Context>::type r_attr_type; + typedef traits::make_attribute<l_attr_type, Attribute> l_make_attribute; + typedef traits::make_attribute<r_attr_type, Attribute> r_make_attribute; + + typename l_make_attribute::type l_attr = l_make_attribute::call(attr); + typename r_make_attribute::type r_attr = r_make_attribute::call(attr); + + Iterator save = first; + if (parser.left.parse(first, last, context, rcontext, l_attr) + && parser.right.parse(first, last, context, rcontext, r_attr)) + return true; + first = save; + return false; + } + + template <typename Left, typename Right, typename Iterator + , typename Context, typename RContext, typename Attribute> + bool parse_sequence( + Left const& left, Right const& right + , Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr + , traits::container_attribute); + + template <typename Parser, typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse_sequence( + Parser const& parser , Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr + , traits::container_attribute) + { + Iterator save = first; + if (parse_into_container(parser.left, first, last, context, rcontext, attr) + && parse_into_container(parser.right, first, last, context, rcontext, attr)) + return true; + first = save; + return false; + } + + template <typename Parser, typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse_sequence_assoc( + Parser const& parser , Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr, mpl::false_ /*should_split*/) + { + return parse_into_container(parser, first, last, context, rcontext, attr); + } + + template <typename Parser, typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse_sequence_assoc( + Parser const& parser , Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr, mpl::true_ /*should_split*/) + { + Iterator save = first; + if (parser.left.parse( first, last, context, rcontext, attr) + && parser.right.parse(first, last, context, rcontext, attr)) + return true; + first = save; + return false; + } + + template <typename Parser, typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse_sequence( + Parser const& parser, Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr + , traits::associative_attribute) + { + // we can come here in 2 cases: + // - when sequence is key >> value and therefore must + // be parsed with tuple synthesized attribute and then + // that tuple is used to save into associative attribute provided here. + // Example: key >> value; + // + // - when either this->left or this->right provides full key-value + // pair (like in case 1) and another one provides nothing. + // Example: eps >> rule<class x; fusion::map<...> > + // + // first case must be parsed as whole, and second one should + // be parsed separately for left and right. + + typedef typename traits::attribute_of< + decltype(parser.left), Context>::type l_attr_type; + typedef typename traits::attribute_of< + decltype(parser.right), Context>::type r_attr_type; + + typedef typename + mpl::or_< + is_same<l_attr_type, unused_type> + , is_same<r_attr_type, unused_type> > + should_split; + + return parse_sequence_assoc(parser, first, last, context, rcontext, attr + , should_split()); + } + + template <typename Left, typename Right, typename Context, typename RContext> + struct parse_into_container_impl<sequence<Left, Right>, Context, RContext> + { + typedef sequence<Left, Right> parser_type; + + template <typename Iterator, typename Attribute> + static bool call( + parser_type const& parser + , Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr, mpl::false_) + { + // inform user what went wrong if we jumped here in attempt to + // parse incompatible sequence into fusion::map + static_assert(!is_same< typename traits::attribute_category<Attribute>::type, + traits::associative_attribute>::value, + "To parse directly into fusion::map sequence must produce tuple attribute " + "where type of first element is existing key in fusion::map and second element " + "is value to be stored under that key"); + + Attribute attr_; + if (!parse_sequence(parser + , first, last, context, rcontext, attr_, traits::container_attribute())) + { + return false; + } + traits::append(attr, traits::begin(attr_), traits::end(attr_)); + return true; + } + + template <typename Iterator, typename Attribute> + static bool call( + parser_type const& parser + , Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr, mpl::true_) + { + return parse_into_container_base_impl<parser_type>::call( + parser, first, last, context, rcontext, attr); + } + + template <typename Iterator, typename Attribute> + static bool call( + parser_type const& parser + , Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) + { + typedef typename + traits::attribute_of<parser_type, Context>::type + attribute_type; + + typedef typename + traits::container_value<Attribute>::type + value_type; + + return call(parser, first, last, context, rcontext, attr + , typename traits::is_substitute<attribute_type, value_type>::type()); + } + }; + +}}}} + +#endif diff --git a/boost/spirit/home/x3/operator/difference.hpp b/boost/spirit/home/x3/operator/difference.hpp new file mode 100644 index 0000000000..13a9274de0 --- /dev/null +++ b/boost/spirit/home/x3/operator/difference.hpp @@ -0,0 +1,75 @@ +/*============================================================================= + 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(SPIRIT_DIFFERENCE_FEBRUARY_11_2007_1250PM) +#define SPIRIT_DIFFERENCE_FEBRUARY_11_2007_1250PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/traits/attribute_of.hpp> +#include <boost/spirit/home/x3/support/traits/has_attribute.hpp> +#include <boost/spirit/home/x3/core/parser.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename Left, typename Right> + struct difference : binary_parser<Left, Right, difference<Left, Right>> + { + typedef binary_parser<Left, Right, difference<Left, Right>> base_type; + static bool const handles_container = Left::handles_container; + + difference(Left const& left, Right const& right) + : base_type(left, right) {} + + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) const + { + // Try Right first + Iterator start = first; + if (this->right.parse(first, last, context, rcontext, unused)) + { + // Right succeeds, we fail. + first = start; + return false; + } + // Right fails, now try Left + return this->left.parse(first, last, context, rcontext, attr); + } + + template <typename Left_, typename Right_> + difference<Left_, Right_> + make(Left_ const& left, Right_ const& right) const + { + return difference<Left_, Right_>(left, right); + } + }; + + template <typename Left, typename Right> + inline difference< + typename extension::as_parser<Left>::value_type + , typename extension::as_parser<Right>::value_type> + operator-(Left const& left, Right const& right) + { + return {as_parser(left), as_parser(right)}; + } +}}} + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + template <typename Left, typename Right, typename Context> + struct attribute_of<x3::difference<Left, Right>, Context> + : attribute_of<Left, Context> {}; + + template <typename Left, typename Right, typename Context> + struct has_attribute<x3::difference<Left, Right>, Context> + : has_attribute<Left, Context> {}; +}}}} + +#endif diff --git a/boost/spirit/home/x3/operator/kleene.hpp b/boost/spirit/home/x3/operator/kleene.hpp new file mode 100644 index 0000000000..7e02bf4a02 --- /dev/null +++ b/boost/spirit/home/x3/operator/kleene.hpp @@ -0,0 +1,59 @@ +/*============================================================================= + 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(SPIRIT_KLEENE_JANUARY_07_2007_0818AM) +#define SPIRIT_KLEENE_JANUARY_07_2007_0818AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/support/traits/container_traits.hpp> +#include <boost/spirit/home/x3/support/traits/attribute_of.hpp> +#include <boost/spirit/home/x3/core/detail/parse_into_container.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename Subject> + struct kleene : unary_parser<Subject, kleene<Subject>> + { + typedef unary_parser<Subject, kleene<Subject>> base_type; + static bool const handles_container = true; + + kleene(Subject const& subject) + : base_type(subject) {} + + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) const + { + while (detail::parse_into_container( + this->subject, first, last, context, rcontext, attr)) + ; + return true; + } + }; + + template <typename Subject> + inline kleene<typename extension::as_parser<Subject>::value_type> + operator*(Subject const& subject) + { + return {as_parser(subject)}; + } +}}} + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + template <typename Subject, typename Context> + struct attribute_of<x3::kleene<Subject>, Context> + : build_container< + typename attribute_of<Subject, Context>::type> {}; +}}}} + +#endif diff --git a/boost/spirit/home/x3/operator/list.hpp b/boost/spirit/home/x3/operator/list.hpp new file mode 100644 index 0000000000..a463a7f9e0 --- /dev/null +++ b/boost/spirit/home/x3/operator/list.hpp @@ -0,0 +1,73 @@ +/*============================================================================= + 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(SPIRIT_LIST_MARCH_24_2007_1031AM) +#define SPIRIT_LIST_MARCH_24_2007_1031AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/support/traits/container_traits.hpp> +#include <boost/spirit/home/x3/support/traits/attribute_of.hpp> +#include <boost/spirit/home/x3/core/detail/parse_into_container.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename Left, typename Right> + struct list : binary_parser<Left, Right, list<Left, Right>> + { + typedef binary_parser<Left, Right, list<Left, Right>> base_type; + static bool const handles_container = true; + static bool const has_attribute = true; + + list(Left const& left, Right const& right) + : base_type(left, right) {} + + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) const + { + // in order to succeed we need to match at least one element + if (!detail::parse_into_container( + this->left, first, last, context, rcontext, attr)) + return false; + + Iterator save = first; + while (this->right.parse(first, last, context, rcontext, unused) + && detail::parse_into_container( + this->left, first, last, context, rcontext, attr)) + { + save = first; + } + + first = save; + return true; + } + }; + + template <typename Left, typename Right> + inline list< + typename extension::as_parser<Left>::value_type + , typename extension::as_parser<Right>::value_type> + operator%(Left const& left, Right const& right) + { + return {as_parser(left), as_parser(right)}; + } +}}} + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + template <typename Left, typename Right, typename Context> + struct attribute_of<x3::list<Left, Right>, Context> + : traits::build_container< + typename attribute_of<Left, Context>::type> {}; +}}}} + +#endif diff --git a/boost/spirit/home/x3/operator/not_predicate.hpp b/boost/spirit/home/x3/operator/not_predicate.hpp new file mode 100644 index 0000000000..38b24bd2e2 --- /dev/null +++ b/boost/spirit/home/x3/operator/not_predicate.hpp @@ -0,0 +1,47 @@ +/*============================================================================= + 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(SPIRIT_NOT_PREDICATE_MARCH_23_2007_0618PM) +#define SPIRIT_NOT_PREDICATE_MARCH_23_2007_0618PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/core/parser.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename Subject> + struct not_predicate : unary_parser<Subject, not_predicate<Subject>> + { + typedef unary_parser<Subject, not_predicate<Subject>> base_type; + + typedef unused_type attribute_type; + static bool const has_attribute = false; + + not_predicate(Subject const& subject) + : base_type(subject) {} + + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& /*attr*/) const + { + Iterator i = first; + return !this->subject.parse(i, last, context, rcontext, unused); + } + }; + + template <typename Subject> + inline not_predicate<typename extension::as_parser<Subject>::value_type> + operator!(Subject const& subject) + { + return {as_parser(subject)}; + } +}}} + +#endif diff --git a/boost/spirit/home/x3/operator/optional.hpp b/boost/spirit/home/x3/operator/optional.hpp new file mode 100644 index 0000000000..16432f89d1 --- /dev/null +++ b/boost/spirit/home/x3/operator/optional.hpp @@ -0,0 +1,86 @@ +/*============================================================================= + 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(SPIRIT_OPTIONAL_MARCH_23_2007_1117PM) +#define SPIRIT_OPTIONAL_MARCH_23_2007_1117PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/core/proxy.hpp> +#include <boost/spirit/home/x3/core/detail/parse_into_container.hpp> +#include <boost/spirit/home/x3/support/traits/attribute_of.hpp> +#include <boost/spirit/home/x3/support/traits/move_to.hpp> +#include <boost/spirit/home/x3/support/traits/optional_traits.hpp> +#include <boost/spirit/home/x3/support/traits/attribute_category.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename Subject> + struct optional : proxy<Subject, optional<Subject>> + { + typedef proxy<Subject, optional<Subject>> base_type; + static bool const handles_container = true; + + optional(Subject const& subject) + : base_type(subject) {} + + using base_type::parse_subject; + + // Attribute is a container + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse_subject(Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr + , traits::container_attribute) const + { + detail::parse_into_container( + this->subject, first, last, context, rcontext, attr); + return true; + } + + // Attribute is an optional + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse_subject(Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr + , traits::optional_attribute) const + { + typedef typename + x3::traits::optional_value<Attribute>::type + value_type; + + // create a local value + value_type val = value_type(); + + if (this->subject.parse(first, last, context, rcontext, val)) + { + // assign the parsed value into our attribute + x3::traits::move_to(val, attr); + } + return true; + } + }; + + template <typename Subject> + inline optional<typename extension::as_parser<Subject>::value_type> + operator-(Subject const& subject) + { + return {as_parser(subject)}; + } +}}} + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + template <typename Subject, typename Context> + struct attribute_of<x3::optional<Subject>, Context> + : build_optional< + typename attribute_of<Subject, Context>::type> {}; +}}}} + +#endif diff --git a/boost/spirit/home/x3/operator/plus.hpp b/boost/spirit/home/x3/operator/plus.hpp new file mode 100644 index 0000000000..32c7dbfffb --- /dev/null +++ b/boost/spirit/home/x3/operator/plus.hpp @@ -0,0 +1,63 @@ +/*============================================================================= + 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(SPIRIT_PLUS_MARCH_13_2007_0127PM) +#define SPIRIT_PLUS_MARCH_13_2007_0127PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/support/traits/container_traits.hpp> +#include <boost/spirit/home/x3/support/traits/attribute_of.hpp> +#include <boost/spirit/home/x3/core/detail/parse_into_container.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename Subject> + struct plus : unary_parser<Subject, plus<Subject>> + { + typedef unary_parser<Subject, plus<Subject>> base_type; + static bool const handles_container = true; + + plus(Subject const& subject) + : base_type(subject) {} + + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) const + { + if (!detail::parse_into_container( + this->subject, first, last, context, rcontext, attr)) + return false; + + while (detail::parse_into_container( + this->subject, first, last, context, rcontext, attr)) + ; + return true; + } + }; + + template <typename Subject> + inline plus<typename extension::as_parser<Subject>::value_type> + operator+(Subject const& subject) + { + return {as_parser(subject)}; + } +}}} + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + template <typename Subject, typename Context> + struct attribute_of<x3::plus<Subject>, Context> + : build_container< + typename attribute_of<Subject, Context>::type> {}; +}}}} + +#endif diff --git a/boost/spirit/home/x3/operator/sequence.hpp b/boost/spirit/home/x3/operator/sequence.hpp new file mode 100644 index 0000000000..23d5e3d8d9 --- /dev/null +++ b/boost/spirit/home/x3/operator/sequence.hpp @@ -0,0 +1,79 @@ +/*============================================================================= + 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(SPIRIT_SEQUENCE_JAN_06_2013_1015AM) +#define SPIRIT_SEQUENCE_JAN_06_2013_1015AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/traits/attribute_of.hpp> +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/operator/detail/sequence.hpp> +#include <boost/spirit/home/x3/directive/expect.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename Left, typename Right> + struct sequence : binary_parser<Left, Right, sequence<Left, Right>> + { + typedef binary_parser<Left, Right, sequence<Left, Right>> base_type; + + sequence(Left left, Right right) + : base_type(left, right) {} + + template <typename Iterator, typename Context, typename RContext> + bool parse( + Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, unused_type) const + { + Iterator save = first; + if (this->left.parse(first, last, context, rcontext, unused) + && this->right.parse(first, last, context, rcontext, unused)) + return true; + first = save; + return false; + } + + template <typename Iterator, typename Context + , typename RContext, typename Attribute> + bool parse( + Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) const + { + return detail::parse_sequence(*this, first, last, context, rcontext, attr + , typename traits::attribute_category<Attribute>::type()); + } + }; + + template <typename Left, typename Right> + inline sequence< + typename extension::as_parser<Left>::value_type + , typename extension::as_parser<Right>::value_type> + operator>>(Left const& left, Right const& right) + { + return {as_parser(left), as_parser(right)}; + } + + template <typename Left, typename Right> + inline sequence< + typename extension::as_parser<Left>::value_type + , expect_directive<typename extension::as_parser<Right>::value_type>> + operator>(Left const& left, Right const& right) + { + return {as_parser(left), as_parser(right)}; + } +}}} + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + template <typename Left, typename Right, typename Context> + struct attribute_of<x3::sequence<Left, Right>, Context> + : x3::detail::attribute_of_sequence<Left, Right, Context> {}; +}}}} + +#endif diff --git a/boost/spirit/home/x3/string.hpp b/boost/spirit/home/x3/string.hpp new file mode 100644 index 0000000000..e0f5c6ebac --- /dev/null +++ b/boost/spirit/home/x3/string.hpp @@ -0,0 +1,17 @@ +/*============================================================================= + 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_STRING_FEBRUARY_03_2007_0355PM) +#define BOOST_SPIRIT_X3_STRING_FEBRUARY_03_2007_0355PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/string/literal_string.hpp> +#include <boost/spirit/home/x3/string/symbols.hpp> + +#endif diff --git a/boost/spirit/home/x3/string/detail/string_parse.hpp b/boost/spirit/home/x3/string/detail/string_parse.hpp new file mode 100644 index 0000000000..f7a77df804 --- /dev/null +++ b/boost/spirit/home/x3/string/detail/string_parse.hpp @@ -0,0 +1,89 @@ +/*============================================================================= + 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_STRING_PARSE_APR_18_2006_1125PM) +#define BOOST_SPIRIT_X3_STRING_PARSE_APR_18_2006_1125PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/traits/move_to.hpp> + +namespace boost { namespace spirit { namespace x3 { namespace detail +{ + template <typename Char, typename Iterator, typename Attribute> + inline bool string_parse( + Char const* str + , Iterator& first, Iterator const& last, Attribute& attr) + { + Iterator i = first; + Char ch = *str; + + for (; !!ch; ++i) + { + if (i == last || (ch != *i)) + return false; + ch = *++str; + } + + x3::traits::move_to(first, i, attr); + first = i; + return true; + } + + template <typename String, typename Iterator, typename Attribute> + inline bool string_parse( + String const& str + , Iterator& first, Iterator const& last, Attribute& attr) + { + Iterator i = first; + typename String::const_iterator stri = str.begin(); + typename String::const_iterator str_last = str.end(); + + for (; stri != str_last; ++stri, ++i) + if (i == last || (*stri != *i)) + return false; + x3::traits::move_to(first, i, attr); + first = i; + return true; + } + + template <typename Char, typename Iterator, typename Attribute> + inline bool string_parse( + Char const* uc_i, Char const* lc_i + , Iterator& first, Iterator const& last, Attribute& attr) + { + Iterator i = first; + + for (; *uc_i && *lc_i; ++uc_i, ++lc_i, ++i) + if (i == last || ((*uc_i != *i) && (*lc_i != *i))) + return false; + x3::traits::move_to(first, i, attr); + first = i; + return true; + } + + template <typename String, typename Iterator, typename Attribute> + inline bool string_parse( + String const& ucstr, String const& lcstr + , Iterator& first, Iterator const& last, Attribute& attr) + { + typename String::const_iterator uc_i = ucstr.begin(); + typename String::const_iterator uc_last = ucstr.end(); + typename String::const_iterator lc_i = lcstr.begin(); + Iterator i = first; + + for (; uc_i != uc_last; ++uc_i, ++lc_i, ++i) + if (i == last || ((*uc_i != *i) && (*lc_i != *i))) + return false; + x3::traits::move_to(first, i, attr); + first = i; + return true; + } +}}}} + +#endif diff --git a/boost/spirit/home/x3/string/detail/tst.hpp b/boost/spirit/home/x3/string/detail/tst.hpp new file mode 100644 index 0000000000..df61f4dec7 --- /dev/null +++ b/boost/spirit/home/x3/string/detail/tst.hpp @@ -0,0 +1,213 @@ +/*============================================================================= + 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_TST_MARCH_09_2007_0905AM) +#define BOOST_SPIRIT_X3_TST_MARCH_09_2007_0905AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/call_traits.hpp> +#include <boost/detail/iterator.hpp> +#include <boost/foreach.hpp> +#include <boost/assert.hpp> + +namespace boost { namespace spirit { namespace x3 { namespace detail +{ + // This file contains low level TST routines, not for + // public consumption. + + template <typename Char, typename T> + struct tst_node + { + tst_node(Char id) + : id(id), data(0), lt(0), eq(0), gt(0) + { + } + + template <typename Alloc> + static void + destruct_node(tst_node* p, Alloc* alloc) + { + if (p) + { + if (p->data) + alloc->delete_data(p->data); + destruct_node(p->lt, alloc); + destruct_node(p->eq, alloc); + destruct_node(p->gt, alloc); + alloc->delete_node(p); + } + } + + template <typename Alloc> + static tst_node* + clone_node(tst_node* p, Alloc* alloc) + { + if (p) + { + tst_node* clone = alloc->new_node(p->id); + if (p->data) + clone->data = alloc->new_data(*p->data); + clone->lt = clone_node(p->lt, alloc); + clone->eq = clone_node(p->eq, alloc); + clone->gt = clone_node(p->gt, alloc); + return clone; + } + return 0; + } + + template <typename Iterator, typename Filter> + static T* + find(tst_node* start, Iterator& first, Iterator last, Filter filter) + { + if (first == last) + return 0; + + Iterator i = first; + Iterator latest = first; + tst_node* p = start; + T* found = 0; + + while (p && i != last) + { + typename + boost::detail::iterator_traits<Iterator>::value_type + c = filter(*i); // filter only the input + + if (c == p->id) + { + if (p->data) + { + found = p->data; + latest = i; + } + p = p->eq; + i++; + } + else if (c < p->id) + { + p = p->lt; + } + else + { + p = p->gt; + } + } + + if (found) + first = ++latest; // one past the last matching char + return found; + } + + template <typename Iterator, typename Alloc> + static T* + add( + tst_node*& start + , Iterator first + , Iterator last + , typename boost::call_traits<T>::param_type val + , Alloc* alloc) + { + if (first == last) + return 0; + + tst_node** pp = &start; + for(;;) + { + typename + boost::detail::iterator_traits<Iterator>::value_type + c = *first; + + if (*pp == 0) + *pp = alloc->new_node(c); + tst_node* p = *pp; + + if (c == p->id) + { + if (++first == last) + { + if (p->data == 0) + p->data = alloc->new_data(val); + return p->data; + } + pp = &p->eq; + } + else if (c < p->id) + { + pp = &p->lt; + } + else + { + pp = &p->gt; + } + } + } + + template <typename Iterator, typename Alloc> + static void + remove(tst_node*& p, Iterator first, Iterator last, Alloc* alloc) + { + if (p == 0 || first == last) + return; + + typename + boost::detail::iterator_traits<Iterator>::value_type + c = *first; + + if (c == p->id) + { + if (++first == last) + { + if (p->data) + { + alloc->delete_data(p->data); + p->data = 0; + } + } + remove(p->eq, first, last, alloc); + } + else if (c < p->id) + { + remove(p->lt, first, last, alloc); + } + else + { + remove(p->gt, first, last, alloc); + } + + if (p->data == 0 && p->lt == 0 && p->eq == 0 && p->gt == 0) + { + alloc->delete_node(p); + p = 0; + } + } + + template <typename F> + static void + for_each(tst_node* p, std::basic_string<Char> prefix, F f) + { + if (p) + { + for_each(p->lt, prefix, f); + std::basic_string<Char> s = prefix + p->id; + for_each(p->eq, s, f); + if (p->data) + f(s, *p->data); + for_each(p->gt, prefix, f); + } + } + + Char id; // the node's identity character + T* data; // optional data + tst_node* lt; // left pointer + tst_node* eq; // middle pointer + tst_node* gt; // right pointer + }; +}}}} + +#endif diff --git a/boost/spirit/home/x3/string/literal_string.hpp b/boost/spirit/home/x3/string/literal_string.hpp new file mode 100644 index 0000000000..bf05a9a08e --- /dev/null +++ b/boost/spirit/home/x3/string/literal_string.hpp @@ -0,0 +1,124 @@ +/*============================================================================= + 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_LITERAL_STRING_APR_18_2006_1125PM) +#define BOOST_SPIRIT_X3_LITERAL_STRING_APR_18_2006_1125PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/core/skip_over.hpp> +#include <boost/spirit/home/x3/string/detail/string_parse.hpp> +#include <boost/spirit/home/x3/support/utility/utf8.hpp> +#include <boost/spirit/home/support/char_encoding/ascii.hpp> +#include <boost/spirit/home/support/char_encoding/standard.hpp> +#include <boost/spirit/home/support/char_encoding/standard_wide.hpp> + +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/add_reference.hpp> +#include <string> + +namespace boost { namespace spirit { namespace x3 +{ + template <typename String, typename Encoding, + typename Attribute = std::basic_string<typename Encoding::char_type>> + struct literal_string : parser<literal_string<String, Encoding, Attribute>> + { + typedef typename Encoding::char_type char_type; + typedef Encoding encoding; + typedef Attribute attribute_type; + static bool const has_attribute = + !is_same<unused_type, attribute_type>::value; + static bool const handles_container = has_attribute; + + literal_string(typename add_reference<String>::type str) + : str(str) + {} + + template <typename Iterator, typename Context, typename Attribute_> + bool parse(Iterator& first, Iterator const& last + , Context const& context, unused_type, Attribute_& attr) const + { + x3::skip_over(first, last, context); + return detail::string_parse(str, first, last, attr); + } + + String str; + }; + + namespace standard + { + inline literal_string<char const*, char_encoding::standard> + string(char const* s) + { + return literal_string<char const*, char_encoding::standard>(s); + } + } + using standard::string; + + namespace extension + { + template <int N> + struct as_parser<char[N]> + { + typedef + literal_string< + char const*, char_encoding::standard, unused_type> + type; + + typedef type value_type; + + static type call(char const* s) + { + return type(s); + } + }; + + template <int N> + struct as_parser<char const[N]> : as_parser<char[N]> {}; + + template <int N> + struct as_parser<wchar_t[N]> + { + typedef + literal_string< + wchar_t const*, char_encoding::standard_wide, unused_type> + type; + + typedef type value_type; + + static type call(wchar_t const* s) + { + return type(s); + } + }; + + template <int N> + struct as_parser<wchar_t const[N]> : as_parser<wchar_t[N]> {}; + } + + using standard::string; + + inline literal_string<char const*, char_encoding::standard, unused_type> + lit(char const* s) + { + return literal_string<char const*, char_encoding::standard, unused_type>(s); + } + + template <typename String, typename Encoding, typename Attribute> + struct get_info<literal_string<String, Encoding, Attribute>> + { + typedef std::string result_type; + std::string operator()(literal_string<String, Encoding, Attribute> const& p) const + { + return '"' + to_utf8(p.str) + '"'; + } + }; +}}} + +#endif diff --git a/boost/spirit/home/x3/string/symbols.hpp b/boost/spirit/home/x3/string/symbols.hpp new file mode 100644 index 0000000000..b35a00a121 --- /dev/null +++ b/boost/spirit/home/x3/string/symbols.hpp @@ -0,0 +1,358 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2013 Carl Barron + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_SPIRIT_X3_SYMBOLS_MARCH_11_2007_1055AM) +#define BOOST_SPIRIT_X3_SYMBOLS_MARCH_11_2007_1055AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/core/skip_over.hpp> +#include <boost/spirit/home/x3/core/parser.hpp> +#include <boost/spirit/home/x3/string/tst.hpp> +#include <boost/spirit/home/x3/support/unused.hpp> +#include <boost/spirit/home/x3/support/traits/string_traits.hpp> +#include <boost/spirit/home/x3/support/traits/move_to.hpp> + +#include <boost/fusion/include/at.hpp> +#include <boost/range.hpp> +#include <boost/type_traits/add_reference.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/shared_ptr.hpp> + +#include <initializer_list> + +#if defined(BOOST_MSVC) +# pragma warning(push) +# pragma warning(disable: 4355) // 'this' : used in base member initializer list warning +#endif + +namespace boost { namespace spirit { namespace x3 +{ + template < + typename Char = char + , typename T = unused_type + , typename Lookup = tst<Char, T> + , typename Filter = tst_pass_through> + struct symbols : parser<symbols<Char, T, Lookup, Filter>> + { + typedef Char char_type; // the character type + typedef T value_type; // the value associated with each entry + typedef symbols<Char, T, Lookup, Filter> this_type; + typedef value_type attribute_type; + + static bool const has_attribute = + !is_same<unused_type, attribute_type>::value; + static bool const handles_container = + traits::is_container<attribute_type>::value; + + symbols(std::string const& name = "symbols") + : add(*this) + , remove(*this) + , lookup(new Lookup()) + , name_(name) + { + } + + symbols(symbols const& syms) + : add(*this) + , remove(*this) + , lookup(syms.lookup) + , name_(syms.name_) + { + } + + template <typename Filter_> + symbols(symbols<Char, T, Lookup, Filter_> const& syms) + : add(*this) + , remove(*this) + , lookup(syms.lookup) + , name_(syms.name_) + { + } + + template <typename Symbols> + symbols(Symbols const& syms, std::string const& name = "symbols") + : add(*this) + , remove(*this) + , lookup(new Lookup()) + , name_(name) + { + typename range_const_iterator<Symbols>::type si = boost::begin(syms); + while (si != boost::end(syms)) + add(*si++); + } + + template <typename Symbols, typename Data> + symbols(Symbols const& syms, Data const& data + , std::string const& name = "symbols") + : add(*this) + , remove(*this) + , lookup(new Lookup()) + , name_(name) + { + typename range_const_iterator<Symbols>::type si = boost::begin(syms); + typename range_const_iterator<Data>::type di = boost::begin(data); + while (si != boost::end(syms)) + add(*si++, *di++); + } + + symbols(std::initializer_list<std::pair<Char const*, T>> syms + , std::string const & name="symbols") + : add(*this) + , remove(*this) + , lookup(new Lookup()) + , name_(name) + { + typedef std::initializer_list<std::pair<Char const*, T>> symbols_t; + typename range_const_iterator<symbols_t>::type si = boost::begin(syms); + for (;si != boost::end(syms); ++si) + add(si->first, si->second); + } + + symbols(std::initializer_list<Char const*> syms + , std::string const &name="symbols") + : add(*this) + , remove(*this) + , lookup(new Lookup()) + , name_(name) + { + typedef std::initializer_list<Char const*> symbols_t; + typename range_const_iterator<symbols_t>::type si = boost::begin(syms); + while (si != boost::end(syms)) + add(*si++); + } + + symbols& + operator=(symbols const& rhs) + { + name_ = rhs.name_; + lookup = rhs.lookup; + return *this; + } + + template <typename Filter_> + symbols& + operator=(symbols<Char, T, Lookup, Filter_> const& rhs) + { + name_ = rhs.name_; + lookup = rhs.lookup; + return *this; + } + + void clear() + { + lookup->clear(); + } + + struct adder; + struct remover; + + template <typename Str> + adder const& + operator=(Str const& str) + { + lookup->clear(); + return add(str); + } + + template <typename Str> + friend adder const& + operator+=(symbols& sym, Str const& str) + { + return sym.add(str); + } + + template <typename Str> + friend remover const& + operator-=(symbols& sym, Str const& str) + { + return sym.remove(str); + } + + template <typename F> + void for_each(F f) const + { + lookup->for_each(f); + } + + template <typename Str> + value_type& at(Str const& str) + { + return *lookup->add(traits::get_string_begin<Char>(str) + , traits::get_string_end<Char>(str), T()); + } + + template <typename Iterator> + value_type* prefix_find(Iterator& first, Iterator const& last) + { + return lookup->find(first, last, Filter()); + } + + template <typename Iterator> + value_type const* prefix_find(Iterator& first, Iterator const& last) const + { + return lookup->find(first, last, Filter()); + } + + template <typename Str> + value_type* find(Str const& str) + { + return find_impl(traits::get_string_begin<Char>(str) + , traits::get_string_end<Char>(str)); + } + + template <typename Str> + value_type const* find(Str const& str) const + { + return find_impl(traits::get_string_begin<Char>(str) + , traits::get_string_end<Char>(str)); + } + + private: + template <typename Iterator> + value_type* find_impl(Iterator begin, Iterator end) + { + value_type* r = lookup->find(begin, end, Filter()); + return begin == end ? r : 0; + } + + template <typename Iterator> + value_type const* find_impl(Iterator begin, Iterator end) const + { + value_type const* r = lookup->find(begin, end, Filter()); + return begin == end ? r : 0; + } + + public: + template <typename Iterator, typename Context, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& context, unused_type, Attribute& attr) const + { + x3::skip_over(first, last, context); + + if (value_type* val_ptr + = lookup->find(first, last, Filter())) + { + x3::traits::move_to(*val_ptr, attr); + return true; + } + return false; + } + + void name(std::string const &str) + { + name_ = str; + } + std::string const &name() const + { + return name_; + } + + struct adder + { + template <typename, typename = unused_type, typename = unused_type> + struct result { typedef adder const& type; }; + + adder(symbols& sym) + : sym(sym) + { + } + + template <typename Iterator> + adder const& + operator()(Iterator first, Iterator last, T const& val) const + { + sym.lookup->add(first, last, val); + return *this; + } + + template <typename Str> + adder const& + operator()(Str const& s, T const& val = T()) const + { + sym.lookup->add(traits::get_string_begin<Char>(s) + , traits::get_string_end<Char>(s), val); + return *this; + } + + template <typename Str> + adder const& + operator,(Str const& s) const + { + sym.lookup->add(traits::get_string_begin<Char>(s) + , traits::get_string_end<Char>(s), T()); + return *this; + } + + symbols& sym; + }; + + struct remover + { + template <typename, typename = unused_type, typename = unused_type> + struct result { typedef remover const& type; }; + + remover(symbols& sym) + : sym(sym) + { + } + + template <typename Iterator> + remover const& + operator()(Iterator const& first, Iterator const& last) const + { + sym.lookup->remove(first, last); + return *this; + } + + template <typename Str> + remover const& + operator()(Str const& s) const + { + sym.lookup->remove(traits::get_string_begin<Char>(s) + , traits::get_string_end<Char>(s)); + return *this; + } + + template <typename Str> + remover const& + operator,(Str const& s) const + { + sym.lookup->remove(traits::get_string_begin<Char>(s) + , traits::get_string_end<Char>(s)); + return *this; + } + + symbols& sym; + }; + + adder add; + remover remove; + shared_ptr<Lookup> lookup; + std::string name_; + }; + + template <typename Char, typename T, typename Lookup, typename Filter> + struct get_info<symbols<Char, T, Lookup, Filter>> + { + typedef std::string result_type; + result_type operator()(symbols< Char, T + , Lookup, Filter + > const& symbols) const + { + return symbols.name(); + } + }; +}}} + +#if defined(BOOST_MSVC) +# pragma warning(pop) +#endif + +#endif diff --git a/boost/spirit/home/x3/string/tst.hpp b/boost/spirit/home/x3/string/tst.hpp new file mode 100644 index 0000000000..5379b032be --- /dev/null +++ b/boost/spirit/home/x3/string/tst.hpp @@ -0,0 +1,137 @@ +/*============================================================================= + 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_TST_JUNE_03_2007_1031AM) +#define BOOST_SPIRIT_X3_TST_JUNE_03_2007_1031AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/string/detail/tst.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + struct tst_pass_through + { + template <typename Char> + Char operator()(Char ch) const + { + return ch; + } + }; + + template <typename Char, typename T> + struct tst + { + typedef Char char_type; // the character type + typedef T value_type; // the value associated with each entry + typedef detail::tst_node<Char, T> node; + + tst() + : root(0) + { + } + + ~tst() + { + clear(); + } + + tst(tst const& rhs) + : root(0) + { + copy(rhs); + } + + tst& operator=(tst const& rhs) + { + return assign(rhs); + } + + template <typename Iterator, typename Filter> + T* find(Iterator& first, Iterator last, Filter filter) const + { + return node::find(root, first, last, filter); + } + + template <typename Iterator> + T* find(Iterator& first, Iterator last) const + { + return find(first, last, tst_pass_through()); + } + + template <typename Iterator> + T* add( + Iterator first + , Iterator last + , typename boost::call_traits<T>::param_type val) + { + return node::add(root, first, last, val, this); + } + + template <typename Iterator> + void remove(Iterator first, Iterator last) + { + node::remove(root, first, last, this); + } + + void clear() + { + node::destruct_node(root, this); + root = 0; + } + + template <typename F> + void for_each(F f) const + { + node::for_each(root, std::basic_string<Char>(), f); + } + + private: + + friend struct detail::tst_node<Char, T>; + + void copy(tst const& rhs) + { + root = node::clone_node(rhs.root, this); + } + + tst& assign(tst const& rhs) + { + if (this != &rhs) + { + clear(); + copy(rhs); + } + return *this; + } + + node* root; + + node* new_node(Char id) + { + return new node(id); + } + + T* new_data(typename boost::call_traits<T>::param_type val) + { + return new T(val); + } + + void delete_node(node* p) + { + delete p; + } + + void delete_data(T* p) + { + delete p; + } + }; +}}} + +#endif diff --git a/boost/spirit/home/x3/string/tst_map.hpp b/boost/spirit/home/x3/string/tst_map.hpp new file mode 100644 index 0000000000..2501324de6 --- /dev/null +++ b/boost/spirit/home/x3/string/tst_map.hpp @@ -0,0 +1,216 @@ +/*============================================================================= + 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_TST_MAP_JUNE_03_2007_1143AM) +#define BOOST_SPIRIT_X3_TST_MAP_JUNE_03_2007_1143AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/string/detail/tst.hpp> +#include <unordered_map> +#include <boost/pool/object_pool.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + struct tst_pass_through; // declared in tst.hpp + + template <typename Char, typename T> + struct tst_map + { + typedef Char char_type; // the character type + typedef T value_type; // the value associated with each entry + typedef detail::tst_node<Char, T> node; + + tst_map() + { + } + + ~tst_map() + { + // Nothing to do here. + // The pools do the right thing for us + } + + tst_map(tst_map const& rhs) + { + copy(rhs); + } + + tst_map& operator=(tst_map const& rhs) + { + return assign(rhs); + } + + template <typename Iterator, typename Filter> + T* find(Iterator& first, Iterator last, Filter filter) const + { + if (first != last) + { + Iterator save = first; + typename map_type::const_iterator + i = map.find(filter(*first++)); + if (i == map.end()) + { + first = save; + return 0; + } + if (T* p = node::find(i->second.root, first, last, filter)) + { + return p; + } + return i->second.data; + } + return 0; + } + + template <typename Iterator> + T* find(Iterator& first, Iterator last) const + { + return find(first, last, tst_pass_through()); + } + + template <typename Iterator> + bool add( + Iterator first + , Iterator last + , typename boost::call_traits<T>::param_type val) + { + if (first != last) + { + map_data x = {0, 0}; + std::pair<typename map_type::iterator, bool> + r = map.insert(std::pair<Char, map_data>(*first++, x)); + + if (first != last) + { + return node::add(r.first->second.root + , first, last, val, this) ? true : false; + } + else + { + if (r.first->second.data) + return false; + r.first->second.data = this->new_data(val); + } + return true; + } + return false; + } + + template <typename Iterator> + void remove(Iterator first, Iterator last) + { + if (first != last) + { + typename map_type::iterator i = map.find(*first++); + if (i != map.end()) + { + if (first != last) + { + node::remove(i->second.root, first, last, this); + } + else if (i->second.data) + { + this->delete_data(i->second.data); + i->second.data = 0; + } + if (i->second.data == 0 && i->second.root == 0) + { + map.erase(i); + } + } + } + } + + void clear() + { + BOOST_FOREACH(typename map_type::value_type& x, map) + { + node::destruct_node(x.second.root, this); + if (x.second.data) + this->delete_data(x.second.data); + } + map.clear(); + } + + template <typename F> + void for_each(F f) const + { + BOOST_FOREACH(typename map_type::value_type const& x, map) + { + std::basic_string<Char> s(1, x.first); + node::for_each(x.second.root, s, f); + if (x.second.data) + f(s, *x.second.data); + } + } + + private: + + friend struct detail::tst_node<Char, T>; + + struct map_data + { + node* root; + T* data; + }; + + typedef std::unordered_map<Char, map_data> map_type; + + void copy(tst_map const& rhs) + { + BOOST_FOREACH(typename map_type::value_type const& x, rhs.map) + { + map_data xx = {node::clone_node(x.second.root, this), 0}; + if (x.second.data) + xx.data = data_pool.construct(*x.second.data); + map[x.first] = xx; + } + } + + tst_map& assign(tst_map const& rhs) + { + if (this != &rhs) + { + BOOST_FOREACH(typename map_type::value_type& x, map) + { + node::destruct_node(x.second.root, this); + } + map.clear(); + copy(rhs); + } + return *this; + } + + node* new_node(Char id) + { + return node_pool.construct(id); + } + + T* new_data(typename boost::call_traits<T>::param_type val) + { + return data_pool.construct(val); + } + + void delete_node(node* p) + { + node_pool.destroy(p); + } + + void delete_data(T* p) + { + data_pool.destroy(p); + } + + map_type map; + object_pool<node> node_pool; + object_pool<T> data_pool; + }; +}}} + +#endif 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 |