Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 10:02:36

0001 /*=============================================================================
0002     Copyright (c) 2001-2014 Joel de Guzman
0003 
0004     Distributed under the Boost Software License, Version 1.0. (See accompanying
0005     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 =============================================================================*/
0007 #if !defined(BOOST_SPIRIT_X3_SEQUENCE_DETAIL_JAN_06_2013_1015AM)
0008 #define BOOST_SPIRIT_X3_SEQUENCE_DETAIL_JAN_06_2013_1015AM
0009 
0010 #include <boost/spirit/home/x3/support/traits/attribute_of.hpp>
0011 #include <boost/spirit/home/x3/support/traits/attribute_category.hpp>
0012 #include <boost/spirit/home/x3/support/traits/has_attribute.hpp>
0013 #include <boost/spirit/home/x3/support/traits/is_substitute.hpp>
0014 #include <boost/spirit/home/x3/support/traits/container_traits.hpp>
0015 #include <boost/spirit/home/x3/support/traits/tuple_traits.hpp>
0016 #include <boost/spirit/home/x3/core/detail/parse_into_container.hpp>
0017 
0018 #include <boost/fusion/include/begin.hpp>
0019 #include <boost/fusion/include/end.hpp>
0020 #include <boost/fusion/include/advance.hpp>
0021 #include <boost/fusion/include/deref.hpp>
0022 #include <boost/fusion/include/empty.hpp>
0023 #include <boost/fusion/include/front.hpp>
0024 #include <boost/fusion/include/iterator_range.hpp>
0025 
0026 #include <boost/mpl/if.hpp>
0027 
0028 #include <boost/type_traits/add_reference.hpp>
0029 #include <boost/type_traits/is_same.hpp>
0030 
0031 #include <iterator> // for std::make_move_iterator
0032 
0033 namespace boost { namespace spirit { namespace x3
0034 {
0035     template <typename Left, typename Right>
0036     struct sequence;
0037 }}}
0038 
0039 namespace boost { namespace spirit { namespace x3 { namespace detail
0040 {
0041     template <typename Parser, typename Context, typename Enable = void>
0042     struct sequence_size
0043     {
0044         static int const value = traits::has_attribute<Parser, Context>::value;
0045     };
0046 
0047     template <typename Parser, typename Context>
0048     struct sequence_size_subject
0049       : sequence_size<typename Parser::subject_type, Context> {};
0050 
0051     template <typename Parser, typename Context>
0052     struct sequence_size<Parser, Context
0053       , typename enable_if_c<(Parser::is_pass_through_unary)>::type>
0054       : sequence_size_subject<Parser, Context> {};
0055 
0056     template <typename L, typename R, typename Context>
0057     struct sequence_size<sequence<L, R>, Context>
0058     {
0059         static int const value =
0060             sequence_size<L, Context>::value +
0061             sequence_size<R, Context>::value;
0062     };
0063 
0064     struct pass_sequence_attribute_unused
0065     {
0066         typedef unused_type type;
0067 
0068         template <typename T>
0069         static unused_type
0070         call(T&)
0071         {
0072             return unused_type();
0073         }
0074     };
0075 
0076     template <typename Attribute>
0077     struct pass_sequence_attribute_size_one_view
0078     {
0079         typedef typename fusion::result_of::deref<
0080             typename fusion::result_of::begin<Attribute>::type
0081         >::type type;
0082 
0083         static type call(Attribute& attribute)
0084         {
0085             return fusion::deref(fusion::begin(attribute));
0086         }
0087     };
0088 
0089     template <typename Attribute>
0090     struct pass_through_sequence_attribute
0091     {
0092         typedef Attribute& type;
0093 
0094         template <typename Attribute_>
0095         static Attribute_&
0096         call(Attribute_& attribute)
0097         {
0098             return attribute;
0099         }
0100     };
0101 
0102     template <typename Parser, typename Attribute, typename Enable = void>
0103     struct pass_sequence_attribute :
0104         mpl::if_<
0105             traits::is_size_one_view<Attribute>
0106           , pass_sequence_attribute_size_one_view<Attribute>
0107           , pass_through_sequence_attribute<Attribute>>::type {};
0108 
0109     template <typename L, typename R, typename Attribute>
0110     struct pass_sequence_attribute<sequence<L, R>, Attribute>
0111       : pass_through_sequence_attribute<Attribute> {};
0112 
0113     template <typename Parser, typename Attribute>
0114     struct pass_sequence_attribute_subject :
0115         pass_sequence_attribute<typename Parser::subject_type, Attribute> {};
0116 
0117     template <typename Parser, typename Attribute>
0118     struct pass_sequence_attribute<Parser, Attribute
0119       , typename enable_if_c<(Parser::is_pass_through_unary)>::type>
0120       : pass_sequence_attribute_subject<Parser, Attribute> {};
0121 
0122     template <typename L, typename R, typename Attribute, typename Context
0123       , typename Enable = void>
0124     struct partition_attribute
0125     {
0126         using attr_category = typename traits::attribute_category<Attribute>::type;
0127         static_assert(is_same<traits::tuple_attribute, attr_category>::value,
0128             "The parser expects tuple-like attribute type");
0129 
0130         static int const l_size = sequence_size<L, Context>::value;
0131         static int const r_size = sequence_size<R, Context>::value;
0132 
0133         static int constexpr actual_size = fusion::result_of::size<Attribute>::value;
0134         static int constexpr expected_size = l_size + r_size;
0135 
0136         // If you got an error here, then you are trying to pass
0137         // a fusion sequence with the wrong number of elements
0138         // as that expected by the (sequence) parser.
0139         static_assert(
0140             actual_size >= expected_size
0141           , "Size of the passed attribute is less than expected."
0142         );
0143         static_assert(
0144             actual_size <= expected_size
0145           , "Size of the passed attribute is bigger than expected."
0146         );
0147 
0148         typedef typename fusion::result_of::begin<Attribute>::type l_begin;
0149         typedef typename fusion::result_of::advance_c<l_begin, l_size>::type l_end;
0150         typedef typename fusion::result_of::end<Attribute>::type r_end;
0151         typedef fusion::iterator_range<l_begin, l_end> l_part;
0152         typedef fusion::iterator_range<l_end, r_end> r_part;
0153         typedef pass_sequence_attribute<L, l_part> l_pass;
0154         typedef pass_sequence_attribute<R, r_part> r_pass;
0155 
0156         static l_part left(Attribute& s)
0157         {
0158             auto i = fusion::begin(s);
0159             return l_part(i, fusion::advance_c<l_size>(i));
0160         }
0161 
0162         static r_part right(Attribute& s)
0163         {
0164             return r_part(
0165                 fusion::advance_c<l_size>(fusion::begin(s))
0166               , fusion::end(s));
0167         }
0168     };
0169 
0170     template <typename L, typename R, typename Attribute, typename Context>
0171     struct partition_attribute<L, R, Attribute, Context,
0172         typename enable_if_c<(!traits::has_attribute<L, Context>::value &&
0173             traits::has_attribute<R, Context>::value)>::type>
0174     {
0175         typedef unused_type l_part;
0176         typedef Attribute& r_part;
0177         typedef pass_sequence_attribute_unused l_pass;
0178         typedef pass_sequence_attribute<R, Attribute> r_pass;
0179 
0180         static unused_type left(Attribute&)
0181         {
0182             return unused;
0183         }
0184 
0185         static Attribute& right(Attribute& s)
0186         {
0187             return s;
0188         }
0189     };
0190 
0191     template <typename L, typename R, typename Attribute, typename Context>
0192     struct partition_attribute<L, R, Attribute, Context,
0193         typename enable_if_c<(traits::has_attribute<L, Context>::value &&
0194             !traits::has_attribute<R, Context>::value)>::type>
0195     {
0196         typedef Attribute& l_part;
0197         typedef unused_type r_part;
0198         typedef pass_sequence_attribute<L, Attribute> l_pass;
0199         typedef pass_sequence_attribute_unused r_pass;
0200 
0201         static Attribute& left(Attribute& s)
0202         {
0203             return s;
0204         }
0205 
0206         static unused_type right(Attribute&)
0207         {
0208             return unused;
0209         }
0210     };
0211 
0212     template <typename L, typename R, typename Attribute, typename Context>
0213     struct partition_attribute<L, R, Attribute, Context,
0214         typename enable_if_c<(!traits::has_attribute<L, Context>::value &&
0215             !traits::has_attribute<R, Context>::value)>::type>
0216     {
0217         typedef unused_type l_part;
0218         typedef unused_type r_part;
0219         typedef pass_sequence_attribute_unused l_pass;
0220         typedef pass_sequence_attribute_unused r_pass;
0221 
0222         static unused_type left(Attribute&)
0223         {
0224             return unused;
0225         }
0226 
0227         static unused_type right(Attribute&)
0228         {
0229             return unused;
0230         }
0231     };
0232 
0233     template <typename Parser, typename Iterator, typename Context
0234       , typename RContext, typename Attribute, typename AttributeCategory>
0235     bool parse_sequence(
0236         Parser const& parser, Iterator& first, Iterator const& last
0237       , Context const& context, RContext& rcontext, Attribute& attr
0238       , AttributeCategory)
0239     {
0240         using Left = typename Parser::left_type;
0241         using Right = typename Parser::right_type;
0242         using partition = partition_attribute<Left, Right, Attribute, Context>;
0243         using l_pass = typename partition::l_pass;
0244         using r_pass = typename partition::r_pass;
0245 
0246         typename partition::l_part l_part = partition::left(attr);
0247         typename partition::r_part r_part = partition::right(attr);
0248         typename l_pass::type l_attr = l_pass::call(l_part);
0249         typename r_pass::type r_attr = r_pass::call(r_part);
0250 
0251         Iterator save = first;
0252         if (parser.left.parse(first, last, context, rcontext, l_attr)
0253             && parser.right.parse(first, last, context, rcontext, r_attr))
0254             return true;
0255         first = save;
0256         return false;
0257     }
0258 
0259     template <typename Parser, typename Context>
0260     constexpr bool pass_sequence_container_attribute
0261         = sequence_size<Parser, Context>::value > 1;
0262 
0263     template <typename Parser, typename Iterator, typename Context
0264       , typename RContext, typename Attribute>
0265     typename enable_if_c<pass_sequence_container_attribute<Parser, Context>, bool>::type
0266     parse_sequence_container(
0267         Parser const& parser
0268       , Iterator& first, Iterator const& last, Context const& context
0269       , RContext& rcontext, Attribute& attr)
0270     {
0271         return parser.parse(first, last, context, rcontext, attr);
0272     }
0273 
0274     template <typename Parser, typename Iterator, typename Context
0275       , typename RContext, typename Attribute>
0276     typename disable_if_c<pass_sequence_container_attribute<Parser, Context>, bool>::type
0277     parse_sequence_container(
0278         Parser const& parser
0279       , Iterator& first, Iterator const& last, Context const& context
0280       , RContext& rcontext, Attribute& attr)
0281     {
0282         return parse_into_container(parser, first, last, context, rcontext, attr);
0283     }
0284 
0285     template <typename Parser, typename Iterator, typename Context
0286       , typename RContext, typename Attribute>
0287     bool parse_sequence(
0288         Parser const& parser , Iterator& first, Iterator const& last
0289       , Context const& context, RContext& rcontext, Attribute& attr
0290       , traits::container_attribute)
0291     {
0292         Iterator save = first;
0293         if (parse_sequence_container(parser.left, first, last, context, rcontext, attr)
0294             && parse_sequence_container(parser.right, first, last, context, rcontext, attr))
0295             return true;
0296         first = save;
0297         return false;
0298     }
0299 
0300     template <typename Parser, typename Iterator, typename Context
0301       , typename RContext, typename Attribute>
0302     bool parse_sequence_assoc(
0303         Parser const& parser , Iterator& first, Iterator const& last
0304       , Context const& context, RContext& rcontext, Attribute& attr, mpl::false_ /*should_split*/)
0305     {
0306         return parse_into_container(parser, first, last, context, rcontext, attr);
0307     }
0308 
0309     template <typename Parser, typename Iterator, typename Context
0310       , typename RContext, typename Attribute>
0311     bool parse_sequence_assoc(
0312         Parser const& parser , Iterator& first, Iterator const& last
0313       , Context const& context, RContext& rcontext, Attribute& attr, mpl::true_ /*should_split*/)
0314     {
0315         Iterator save = first;
0316         if (parser.left.parse( first, last, context, rcontext, attr)
0317             && parser.right.parse(first, last, context, rcontext, attr))
0318             return true;
0319         first = save;
0320         return false;
0321     }
0322 
0323     template <typename Parser, typename Iterator, typename Context
0324       , typename RContext, typename Attribute>
0325     bool parse_sequence(
0326         Parser const& parser, Iterator& first, Iterator const& last
0327       , Context const& context, RContext& rcontext, Attribute& attr
0328       , traits::associative_attribute)
0329     {
0330         // we can come here in 2 cases:
0331         // - when sequence is key >> value and therefore must
0332         // be parsed with tuple synthesized attribute and then
0333         // that tuple is used to save into associative attribute provided here.
0334         // Example:  key >> value;
0335         //
0336         // - when either this->left or this->right provides full key-value
0337         // pair (like in case 1) and another one provides nothing.
0338         // Example:  eps >> rule<class x; fusion::map<...> >
0339         //
0340         // first case must be parsed as whole, and second one should
0341         // be parsed separately for left and right.
0342 
0343         typedef typename traits::attribute_of<
0344             decltype(parser.left), Context>::type l_attr_type;
0345         typedef typename traits::attribute_of<
0346             decltype(parser.right), Context>::type r_attr_type;
0347 
0348         typedef typename
0349             mpl::or_<
0350                 is_same<l_attr_type, unused_type>
0351               , is_same<r_attr_type, unused_type> >
0352         should_split;
0353 
0354         return parse_sequence_assoc(parser, first, last, context, rcontext, attr
0355           , should_split());
0356     }
0357 
0358     template <typename Left, typename Right, typename Context, typename RContext>
0359     struct parse_into_container_impl<sequence<Left, Right>, Context, RContext>
0360     {
0361         typedef sequence<Left, Right> parser_type;
0362 
0363         template <typename Iterator, typename Attribute>
0364         static bool call(
0365             parser_type const& parser
0366           , Iterator& first, Iterator const& last
0367           , Context const& context, RContext& rcontext, Attribute& attr, mpl::false_)
0368         {
0369             // inform user what went wrong if we jumped here in attempt to
0370             // parse incompatible sequence into fusion::map
0371             static_assert(!is_same< typename traits::attribute_category<Attribute>::type,
0372                   traits::associative_attribute>::value,
0373                   "To parse directly into fusion::map sequence must produce tuple attribute "
0374                   "where type of first element is existing key in fusion::map and second element "
0375                   "is value to be stored under that key");
0376 
0377             Attribute attr_{};
0378             if (!parse_sequence(parser
0379                    , first, last, context, rcontext, attr_, traits::container_attribute()))
0380             {
0381                 return false;
0382             }
0383             traits::append(attr, std::make_move_iterator(traits::begin(attr_)),
0384                                  std::make_move_iterator(traits::end(attr_)));
0385             return true;
0386         }
0387 
0388         template <typename Iterator, typename Attribute>
0389         static bool call(
0390             parser_type const& parser
0391           , Iterator& first, Iterator const& last
0392           , Context const& context, RContext& rcontext, Attribute& attr, mpl::true_)
0393         {
0394             return parse_into_container_base_impl<parser_type>::call(
0395                 parser, first, last, context, rcontext, attr);
0396         }
0397 
0398         template <typename Iterator, typename Attribute>
0399         static bool call(
0400             parser_type const& parser
0401           , Iterator& first, Iterator const& last
0402           , Context const& context, RContext& rcontext, Attribute& attr)
0403         {
0404             typedef typename
0405                 traits::attribute_of<parser_type, Context>::type
0406             attribute_type;
0407 
0408             typedef typename
0409                 traits::container_value<Attribute>::type
0410             value_type;
0411 
0412             return call(parser, first, last, context, rcontext, attr
0413             , typename traits::is_substitute<attribute_type, value_type>::type());
0414         }
0415     };
0416 
0417 }}}}
0418 
0419 #endif