diff options
Diffstat (limited to 'boost/spirit/home/x3/operator')
-rw-r--r-- | boost/spirit/home/x3/operator/alternative.hpp | 68 | ||||
-rw-r--r-- | boost/spirit/home/x3/operator/and_predicate.hpp | 47 | ||||
-rw-r--r-- | boost/spirit/home/x3/operator/detail/alternative.hpp | 317 | ||||
-rw-r--r-- | boost/spirit/home/x3/operator/detail/sequence.hpp | 501 | ||||
-rw-r--r-- | boost/spirit/home/x3/operator/difference.hpp | 75 | ||||
-rw-r--r-- | boost/spirit/home/x3/operator/kleene.hpp | 59 | ||||
-rw-r--r-- | boost/spirit/home/x3/operator/list.hpp | 73 | ||||
-rw-r--r-- | boost/spirit/home/x3/operator/not_predicate.hpp | 47 | ||||
-rw-r--r-- | boost/spirit/home/x3/operator/optional.hpp | 86 | ||||
-rw-r--r-- | boost/spirit/home/x3/operator/plus.hpp | 63 | ||||
-rw-r--r-- | boost/spirit/home/x3/operator/sequence.hpp | 79 |
11 files changed, 1415 insertions, 0 deletions
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 |