PageRenderTime 48ms CodeModel.GetById 13ms app.highlight 28ms RepoModel.GetById 1ms app.codeStats 1ms

/src/contrib/boost/spirit/home/qi/operator/sequence_base.hpp

http://pythonocc.googlecode.com/
C++ Header | 134 lines | 98 code | 15 blank | 21 comment | 2 complexity | 63f52cd2dcab475476dbbe7e84aaed6d MD5 | raw file
  1/*=============================================================================
  2    Copyright (c) 2001-2010 Joel de Guzman
  3
  4    Distributed under the Boost Software License, Version 1.0. (See accompanying
  5    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6=============================================================================*/
  7#if !defined(SPIRIT_SEQUENCE_BASE_APRIL_22_2006_0811AM)
  8#define SPIRIT_SEQUENCE_BASE_APRIL_22_2006_0811AM
  9
 10#if defined(_MSC_VER)
 11#pragma once
 12#endif
 13
 14#include <boost/spirit/home/qi/domain.hpp>
 15#include <boost/spirit/home/qi/detail/pass_container.hpp>
 16#include <boost/spirit/home/support/attributes.hpp>
 17#include <boost/spirit/home/support/algorithm/any_if.hpp>
 18#include <boost/spirit/home/support/detail/what_function.hpp>
 19#include <boost/spirit/home/support/unused.hpp>
 20#include <boost/spirit/home/support/info.hpp>
 21#include <boost/spirit/home/support/sequence_base_id.hpp>
 22#include <boost/spirit/home/qi/parser.hpp>
 23#include <boost/fusion/include/as_vector.hpp>
 24#include <boost/fusion/include/vector.hpp>
 25#include <boost/fusion/include/for_each.hpp>
 26#include <boost/mpl/identity.hpp>
 27
 28namespace boost { namespace spirit { namespace qi
 29{
 30    template <typename Derived, typename Elements>
 31    struct sequence_base // this class is shared by sequence and expect
 32      : nary_parser<Derived>
 33    {
 34        typedef Elements elements_type;
 35        struct sequence_base_id;
 36
 37        template <typename Context, typename Iterator>
 38        struct attribute
 39        {
 40            // Put all the element attributes in a tuple
 41            typedef typename traits::build_attribute_sequence<
 42                Elements, Context, mpl::identity, Iterator>::type
 43            all_attributes;
 44
 45            // Now, build a fusion vector over the attributes. Note
 46            // that build_fusion_vector 1) removes all unused attributes
 47            // and 2) may return unused_type if all elements have
 48            // unused_type(s).
 49            typedef typename
 50                traits::build_fusion_vector<all_attributes>::type
 51            type_;
 52
 53            // Finally, strip single element vectors into its
 54            // naked form: vector1<T> --> T
 55            typedef typename
 56                traits::strip_single_element_vector<type_>::type
 57            type;
 58        };
 59
 60        sequence_base(Elements const& elements)
 61          : elements(elements) {}
 62
 63        // standard case. Attribute is a fusion tuple
 64        template <typename Iterator, typename Context
 65          , typename Skipper, typename Attribute>
 66        bool parse_impl(Iterator& first, Iterator const& last
 67          , Context& context, Skipper const& skipper
 68          , Attribute& attr_, mpl::false_) const
 69        {
 70            Iterator iter = first;
 71            typedef traits::attribute_not_unused<Context, Iterator> predicate;
 72
 73            // wrap the attribute in a tuple if it is not a tuple or if the 
 74            // attribute of this sequence is a single element tuple
 75            typedef typename attribute<Context, Iterator>::type_ attr_type_;
 76            typename traits::wrap_if_not_tuple<Attribute
 77              , typename mpl::and_<
 78                    traits::one_element_sequence<attr_type_>
 79                  , mpl::not_<traits::one_element_sequence<Attribute> >
 80                >::type 
 81            >::type attr(attr_);
 82
 83            // return false if *any* of the parsers fail
 84            if (spirit::any_if(elements, attr
 85              , Derived::fail_function(iter, last, context, skipper), predicate()))
 86                return false;
 87            first = iter;
 88            return true;
 89        }
 90
 91        // Special case when Attribute is an stl container
 92        template <typename Iterator, typename Context
 93          , typename Skipper, typename Attribute>
 94        bool parse_impl(Iterator& first, Iterator const& last
 95          , Context& context, Skipper const& skipper
 96          , Attribute& attr_, mpl::true_) const
 97        {
 98            Iterator iter = first;
 99            // return false if *any* of the parsers fail
100            if (fusion::any(elements
101              , detail::make_pass_container(
102                    Derived::fail_function(iter, last, context, skipper), attr_))
103                )
104                return false;
105            first = iter;
106            return true;
107        }
108
109        // main parse function. Dispatches to parse_impl depending
110        // on the Attribute type.
111        template <typename Iterator, typename Context
112          , typename Skipper, typename Attribute>
113        bool parse(Iterator& first, Iterator const& last
114          , Context& context, Skipper const& skipper
115          , Attribute& attr) const
116        {
117            return parse_impl(first, last, context, skipper, attr
118              , traits::is_container<Attribute>());
119        }
120
121        template <typename Context>
122        info what(Context& context) const
123        {
124            info result(this->derived().id());
125            fusion::for_each(elements,
126                spirit::detail::what_function<Context>(result, context));
127            return result;
128        }
129
130        Elements elements;
131    };
132}}}
133
134#endif