]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/libs/spirit/include/boost/spirit/home/qi/operator/sequence_base.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / spirit / include / boost / spirit / home / qi / operator / sequence_base.hpp
diff --git a/ceph/src/boost/libs/spirit/include/boost/spirit/home/qi/operator/sequence_base.hpp b/ceph/src/boost/libs/spirit/include/boost/spirit/home/qi/operator/sequence_base.hpp
new file mode 100644 (file)
index 0000000..3664686
--- /dev/null
@@ -0,0 +1,140 @@
+/*=============================================================================
+    Copyright (c) 2001-2011 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_SEQUENCE_BASE_APRIL_22_2006_0811AM)
+#define SPIRIT_SEQUENCE_BASE_APRIL_22_2006_0811AM
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/qi/domain.hpp>
+#include <boost/spirit/home/qi/detail/pass_container.hpp>
+#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/support/algorithm/any_if.hpp>
+#include <boost/spirit/home/support/detail/what_function.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/spirit/home/support/info.hpp>
+#include <boost/spirit/home/support/sequence_base_id.hpp>
+#include <boost/spirit/home/support/has_semantic_action.hpp>
+#include <boost/spirit/home/qi/parser.hpp>
+#include <boost/fusion/include/as_vector.hpp>
+#include <boost/fusion/include/vector.hpp>
+#include <boost/fusion/include/for_each.hpp>
+#include <boost/mpl/identity.hpp>
+
+namespace boost { namespace spirit { namespace qi
+{
+    template <typename Derived, typename Elements>
+    struct sequence_base // this class is shared by sequence and expect
+      : nary_parser<Derived>
+    {
+        typedef Elements elements_type;
+        struct sequence_base_id;
+
+        template <typename Context, typename Iterator>
+        struct attribute
+        {
+            // Put all the element attributes in a tuple
+            typedef typename traits::build_attribute_sequence<
+                Elements, Context, traits::sequence_attribute_transform
+              , Iterator, qi::domain
+            >::type all_attributes;
+
+            // Now, build a fusion vector over the attributes. Note
+            // that build_fusion_vector 1) removes all unused attributes
+            // and 2) may return unused_type if all elements have
+            // unused_type(s).
+            typedef typename
+                traits::build_fusion_vector<all_attributes>::type
+            type_;
+
+            // Finally, strip single element vectors into its
+            // naked form: vector1<T> --> T
+            typedef typename
+                traits::strip_single_element_vector<type_>::type
+            type;
+        };
+
+        sequence_base(Elements const& elements_)
+          : elements(elements_) {}
+
+        // standard case. Attribute is a fusion tuple
+        template <typename Iterator, typename Context
+          , typename Skipper, typename Attribute>
+        bool parse_impl(Iterator& first, Iterator const& last
+          , Context& context, Skipper const& skipper
+          , Attribute& attr_, mpl::false_) const
+        {
+            Iterator iter = first;
+            typedef traits::attribute_not_unused<Context, Iterator> predicate;
+
+            // wrap the attribute in a tuple if it is not a tuple or if the 
+            // attribute of this sequence is a single element tuple
+            typedef typename attribute<Context, Iterator>::type_ attr_type_;
+            typename traits::wrap_if_not_tuple<Attribute
+              , typename mpl::and_<
+                    traits::one_element_sequence<attr_type_>
+                  , mpl::not_<traits::one_element_sequence<Attribute> >
+                >::type
+            >::type attr_local(attr_);
+
+            // return false if *any* of the parsers fail
+            if (spirit::any_if(elements, attr_local
+              , Derived::fail_function(iter, last, context, skipper), predicate()))
+                return false;
+            first = iter;
+            return true;
+        }
+
+        // Special case when Attribute is an stl container
+        template <typename Iterator, typename Context
+          , typename Skipper, typename Attribute>
+        bool parse_impl(Iterator& first, Iterator const& last
+          , Context& context, Skipper const& skipper
+          , Attribute& attr_, mpl::true_) const
+        {
+            // ensure the attribute is actually a container type
+            traits::make_container(attr_);
+
+            Iterator iter = first;
+            // return false if *any* of the parsers fail
+            if (fusion::any(elements
+              , detail::make_sequence_pass_container(
+                    Derived::fail_function(iter, last, context, skipper), attr_))
+                )
+                return false;
+            first = iter;
+            return true;
+        }
+
+        // main parse function. Dispatches to parse_impl depending
+        // on the Attribute type.
+        template <typename Iterator, typename Context
+          , typename Skipper, typename Attribute>
+        bool parse(Iterator& first, Iterator const& last
+          , Context& context, Skipper const& skipper
+          , Attribute& attr_) const
+        {
+            return parse_impl(first, last, context, skipper, attr_
+              , traits::is_container<Attribute>());
+        }
+
+        template <typename Context>
+        info what(Context& context) const
+        {
+            info result(this->derived().id());
+            fusion::for_each(elements,
+                spirit::detail::what_function<Context>(result, context));
+            return result;
+        }
+
+        Elements elements;
+    };
+}}}
+
+#endif