File indexing completed on 2025-01-31 10:02:36
0001
0002
0003
0004
0005
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
0137
0138
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_ )
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_ )
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
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
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
0370
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