sequence.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. /*=============================================================================
  2. Copyright (c) 2001-2014 Joel de Guzman
  3. Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. =============================================================================*/
  6. #if !defined(BOOST_SPIRIT_X3_SEQUENCE_DETAIL_JAN_06_2013_1015AM)
  7. #define BOOST_SPIRIT_X3_SEQUENCE_DETAIL_JAN_06_2013_1015AM
  8. #include <boost/spirit/home/x3/support/traits/attribute_of.hpp>
  9. #include <boost/spirit/home/x3/support/traits/attribute_category.hpp>
  10. #include <boost/spirit/home/x3/support/traits/has_attribute.hpp>
  11. #include <boost/spirit/home/x3/support/traits/is_substitute.hpp>
  12. #include <boost/spirit/home/x3/support/traits/container_traits.hpp>
  13. #include <boost/spirit/home/x3/support/traits/tuple_traits.hpp>
  14. #include <boost/spirit/home/x3/core/detail/parse_into_container.hpp>
  15. #include <boost/fusion/include/begin.hpp>
  16. #include <boost/fusion/include/end.hpp>
  17. #include <boost/fusion/include/advance.hpp>
  18. #include <boost/fusion/include/deref.hpp>
  19. #include <boost/fusion/include/empty.hpp>
  20. #include <boost/fusion/include/front.hpp>
  21. #include <boost/fusion/include/iterator_range.hpp>
  22. #include <boost/fusion/include/as_deque.hpp>
  23. #include <boost/fusion/include/mpl.hpp>
  24. #include <boost/mpl/copy_if.hpp>
  25. #include <boost/mpl/not.hpp>
  26. #include <boost/mpl/if.hpp>
  27. #include <boost/mpl/insert_range.hpp>
  28. #include <boost/mpl/eval_if.hpp>
  29. #include <boost/mpl/vector.hpp>
  30. #include <boost/mpl/identity.hpp>
  31. #include <boost/type_traits/add_reference.hpp>
  32. #include <boost/type_traits/is_same.hpp>
  33. #include <iterator> // for std::make_move_iterator
  34. namespace boost { namespace spirit { namespace x3
  35. {
  36. template <typename Left, typename Right>
  37. struct sequence;
  38. }}}
  39. namespace boost { namespace spirit { namespace x3 { namespace detail
  40. {
  41. template <typename Parser, typename Context, typename Enable = void>
  42. struct sequence_size
  43. {
  44. static int const value = traits::has_attribute<Parser, Context>::value;
  45. };
  46. template <typename Parser, typename Context>
  47. struct sequence_size_subject
  48. : sequence_size<typename Parser::subject_type, Context> {};
  49. template <typename Parser, typename Context>
  50. struct sequence_size<Parser, Context
  51. , typename enable_if_c<(Parser::is_pass_through_unary)>::type>
  52. : sequence_size_subject<Parser, Context> {};
  53. template <typename L, typename R, typename Context>
  54. struct sequence_size<sequence<L, R>, Context>
  55. {
  56. static int const value =
  57. sequence_size<L, Context>::value +
  58. sequence_size<R, Context>::value;
  59. };
  60. struct pass_sequence_attribute_unused
  61. {
  62. typedef unused_type type;
  63. template <typename T>
  64. static unused_type
  65. call(T&)
  66. {
  67. return unused_type();
  68. }
  69. };
  70. template <typename Attribute>
  71. struct pass_sequence_attribute_size_one_view
  72. {
  73. typedef typename fusion::result_of::deref<
  74. typename fusion::result_of::begin<Attribute>::type
  75. >::type type;
  76. static type call(Attribute& attr)
  77. {
  78. return fusion::deref(fusion::begin(attr));
  79. }
  80. };
  81. template <typename Attribute>
  82. struct pass_through_sequence_attribute
  83. {
  84. typedef Attribute& type;
  85. template <typename Attribute_>
  86. static Attribute_&
  87. call(Attribute_& attr)
  88. {
  89. return attr;
  90. }
  91. };
  92. template <typename Parser, typename Attribute, typename Enable = void>
  93. struct pass_sequence_attribute :
  94. mpl::if_<
  95. traits::is_size_one_view<Attribute>
  96. , pass_sequence_attribute_size_one_view<Attribute>
  97. , pass_through_sequence_attribute<Attribute>>::type {};
  98. template <typename L, typename R, typename Attribute>
  99. struct pass_sequence_attribute<sequence<L, R>, Attribute>
  100. : pass_through_sequence_attribute<Attribute> {};
  101. template <typename Parser, typename Attribute>
  102. struct pass_sequence_attribute_subject :
  103. pass_sequence_attribute<typename Parser::subject_type, Attribute> {};
  104. template <typename Parser, typename Attribute>
  105. struct pass_sequence_attribute<Parser, Attribute
  106. , typename enable_if_c<(Parser::is_pass_through_unary)>::type>
  107. : pass_sequence_attribute_subject<Parser, Attribute> {};
  108. template <typename L, typename R, typename Attribute, typename Context
  109. , typename Enable = void>
  110. struct partition_attribute
  111. {
  112. using attr_category = typename traits::attribute_category<Attribute>::type;
  113. static_assert(is_same<traits::tuple_attribute, attr_category>::value,
  114. "The parser expects tuple-like attribute type");
  115. static int const l_size = sequence_size<L, Context>::value;
  116. static int const r_size = sequence_size<R, Context>::value;
  117. static int constexpr actual_size = fusion::result_of::size<Attribute>::value;
  118. static int constexpr expected_size = l_size + r_size;
  119. // If you got an error here, then you are trying to pass
  120. // a fusion sequence with the wrong number of elements
  121. // as that expected by the (sequence) parser.
  122. static_assert(
  123. actual_size >= expected_size
  124. , "Size of the passed attribute is less than expected."
  125. );
  126. static_assert(
  127. actual_size <= expected_size
  128. , "Size of the passed attribute is bigger than expected."
  129. );
  130. typedef typename fusion::result_of::begin<Attribute>::type l_begin;
  131. typedef typename fusion::result_of::advance_c<l_begin, l_size>::type l_end;
  132. typedef typename fusion::result_of::end<Attribute>::type r_end;
  133. typedef fusion::iterator_range<l_begin, l_end> l_part;
  134. typedef fusion::iterator_range<l_end, r_end> r_part;
  135. typedef pass_sequence_attribute<L, l_part> l_pass;
  136. typedef pass_sequence_attribute<R, r_part> r_pass;
  137. static l_part left(Attribute& s)
  138. {
  139. auto i = fusion::begin(s);
  140. return l_part(i, fusion::advance_c<l_size>(i));
  141. }
  142. static r_part right(Attribute& s)
  143. {
  144. return r_part(
  145. fusion::advance_c<l_size>(fusion::begin(s))
  146. , fusion::end(s));
  147. }
  148. };
  149. template <typename L, typename R, typename Attribute, typename Context>
  150. struct partition_attribute<L, R, Attribute, Context,
  151. typename enable_if_c<(!traits::has_attribute<L, Context>::value &&
  152. traits::has_attribute<R, Context>::value)>::type>
  153. {
  154. typedef unused_type l_part;
  155. typedef Attribute& r_part;
  156. typedef pass_sequence_attribute_unused l_pass;
  157. typedef pass_sequence_attribute<R, Attribute> r_pass;
  158. static unused_type left(Attribute&)
  159. {
  160. return unused;
  161. }
  162. static Attribute& right(Attribute& s)
  163. {
  164. return s;
  165. }
  166. };
  167. template <typename L, typename R, typename Attribute, typename Context>
  168. struct partition_attribute<L, R, Attribute, Context,
  169. typename enable_if_c<(traits::has_attribute<L, Context>::value &&
  170. !traits::has_attribute<R, Context>::value)>::type>
  171. {
  172. typedef Attribute& l_part;
  173. typedef unused_type r_part;
  174. typedef pass_sequence_attribute<L, Attribute> l_pass;
  175. typedef pass_sequence_attribute_unused r_pass;
  176. static Attribute& left(Attribute& s)
  177. {
  178. return s;
  179. }
  180. static unused_type right(Attribute&)
  181. {
  182. return unused;
  183. }
  184. };
  185. template <typename L, typename R, typename Attribute, typename Context>
  186. struct partition_attribute<L, R, Attribute, Context,
  187. typename enable_if_c<(!traits::has_attribute<L, Context>::value &&
  188. !traits::has_attribute<R, Context>::value)>::type>
  189. {
  190. typedef unused_type l_part;
  191. typedef unused_type r_part;
  192. typedef pass_sequence_attribute_unused l_pass;
  193. typedef pass_sequence_attribute_unused r_pass;
  194. static unused_type left(Attribute&)
  195. {
  196. return unused;
  197. }
  198. static unused_type right(Attribute&)
  199. {
  200. return unused;
  201. }
  202. };
  203. template <typename L, typename R, typename C>
  204. struct get_sequence_types
  205. {
  206. typedef
  207. mpl::vector<
  208. typename traits::attribute_of<L, C>::type
  209. , typename traits::attribute_of<R, C>::type
  210. >
  211. type;
  212. };
  213. template <typename LL, typename LR, typename R, typename C>
  214. struct get_sequence_types<sequence<LL, LR>, R, C>
  215. : mpl::push_back< typename get_sequence_types<LL, LR, C>::type
  216. , typename traits::attribute_of<R, C>::type> {};
  217. template <typename L, typename RL, typename RR, typename C>
  218. struct get_sequence_types<L, sequence<RL, RR>, C>
  219. : mpl::push_front< typename get_sequence_types<RL, RR, C>::type
  220. , typename traits::attribute_of<L, C>::type> {};
  221. template <typename LL, typename LR, typename RL, typename RR, typename C>
  222. struct get_sequence_types<sequence<LL, LR>, sequence<RL, RR>, C>
  223. {
  224. typedef typename get_sequence_types<LL, LR, C>::type left;
  225. typedef typename get_sequence_types<RL, RR, C>::type right;
  226. typedef typename
  227. mpl::insert_range<left, typename mpl::end<left>::type, right>::type
  228. type;
  229. };
  230. template <typename L, typename R, typename C>
  231. struct attribute_of_sequence
  232. {
  233. // Get all sequence attribute types
  234. typedef typename get_sequence_types<L, R, C>::type all_types;
  235. // Filter all unused_types
  236. typedef typename
  237. mpl::copy_if<
  238. all_types
  239. , mpl::not_<is_same<mpl::_1, unused_type>>
  240. , mpl::back_inserter<mpl::vector<>>
  241. >::type
  242. filtered_types;
  243. // Build a fusion::deque if filtered_types is not empty,
  244. // else just return unused_type
  245. typedef typename
  246. mpl::eval_if<
  247. mpl::empty<filtered_types>
  248. , mpl::identity<unused_type>
  249. , mpl::if_<mpl::equal_to<mpl::size<filtered_types>, mpl::int_<1> >,
  250. typename mpl::front<filtered_types>::type
  251. , typename fusion::result_of::as_deque<filtered_types>::type >
  252. >::type
  253. type;
  254. };
  255. template <typename Parser, typename Iterator, typename Context
  256. , typename RContext, typename Attribute, typename AttributeCategory>
  257. bool parse_sequence(
  258. Parser const& parser, Iterator& first, Iterator const& last
  259. , Context const& context, RContext& rcontext, Attribute& attr
  260. , AttributeCategory)
  261. {
  262. using Left = typename Parser::left_type;
  263. using Right = typename Parser::right_type;
  264. using partition = partition_attribute<Left, Right, Attribute, Context>;
  265. using l_pass = typename partition::l_pass;
  266. using r_pass = typename partition::r_pass;
  267. typename partition::l_part l_part = partition::left(attr);
  268. typename partition::r_part r_part = partition::right(attr);
  269. typename l_pass::type l_attr = l_pass::call(l_part);
  270. typename r_pass::type r_attr = r_pass::call(r_part);
  271. Iterator save = first;
  272. if (parser.left.parse(first, last, context, rcontext, l_attr)
  273. && parser.right.parse(first, last, context, rcontext, r_attr))
  274. return true;
  275. first = save;
  276. return false;
  277. }
  278. template <typename Parser, typename Context>
  279. constexpr bool pass_sequence_container_attribute
  280. = sequence_size<Parser, Context>::value > 1;
  281. template <typename Parser, typename Iterator, typename Context
  282. , typename RContext, typename Attribute>
  283. typename enable_if_c<pass_sequence_container_attribute<Parser, Context>, bool>::type
  284. parse_sequence_container(
  285. Parser const& parser
  286. , Iterator& first, Iterator const& last, Context const& context
  287. , RContext& rcontext, Attribute& attr)
  288. {
  289. return parser.parse(first, last, context, rcontext, attr);
  290. }
  291. template <typename Parser, typename Iterator, typename Context
  292. , typename RContext, typename Attribute>
  293. typename disable_if_c<pass_sequence_container_attribute<Parser, Context>, bool>::type
  294. parse_sequence_container(
  295. Parser const& parser
  296. , Iterator& first, Iterator const& last, Context const& context
  297. , RContext& rcontext, Attribute& attr)
  298. {
  299. return parse_into_container(parser, first, last, context, rcontext, attr);
  300. }
  301. template <typename Parser, typename Iterator, typename Context
  302. , typename RContext, typename Attribute>
  303. bool parse_sequence(
  304. Parser const& parser , Iterator& first, Iterator const& last
  305. , Context const& context, RContext& rcontext, Attribute& attr
  306. , traits::container_attribute)
  307. {
  308. Iterator save = first;
  309. if (parse_sequence_container(parser.left, first, last, context, rcontext, attr)
  310. && parse_sequence_container(parser.right, first, last, context, rcontext, attr))
  311. return true;
  312. first = save;
  313. return false;
  314. }
  315. template <typename Parser, typename Iterator, typename Context
  316. , typename RContext, typename Attribute>
  317. bool parse_sequence_assoc(
  318. Parser const& parser , Iterator& first, Iterator const& last
  319. , Context const& context, RContext& rcontext, Attribute& attr, mpl::false_ /*should_split*/)
  320. {
  321. return parse_into_container(parser, first, last, context, rcontext, attr);
  322. }
  323. template <typename Parser, typename Iterator, typename Context
  324. , typename RContext, typename Attribute>
  325. bool parse_sequence_assoc(
  326. Parser const& parser , Iterator& first, Iterator const& last
  327. , Context const& context, RContext& rcontext, Attribute& attr, mpl::true_ /*should_split*/)
  328. {
  329. Iterator save = first;
  330. if (parser.left.parse( first, last, context, rcontext, attr)
  331. && parser.right.parse(first, last, context, rcontext, attr))
  332. return true;
  333. first = save;
  334. return false;
  335. }
  336. template <typename Parser, typename Iterator, typename Context
  337. , typename RContext, typename Attribute>
  338. bool parse_sequence(
  339. Parser const& parser, Iterator& first, Iterator const& last
  340. , Context const& context, RContext& rcontext, Attribute& attr
  341. , traits::associative_attribute)
  342. {
  343. // we can come here in 2 cases:
  344. // - when sequence is key >> value and therefore must
  345. // be parsed with tuple synthesized attribute and then
  346. // that tuple is used to save into associative attribute provided here.
  347. // Example: key >> value;
  348. //
  349. // - when either this->left or this->right provides full key-value
  350. // pair (like in case 1) and another one provides nothing.
  351. // Example: eps >> rule<class x; fusion::map<...> >
  352. //
  353. // first case must be parsed as whole, and second one should
  354. // be parsed separately for left and right.
  355. typedef typename traits::attribute_of<
  356. decltype(parser.left), Context>::type l_attr_type;
  357. typedef typename traits::attribute_of<
  358. decltype(parser.right), Context>::type r_attr_type;
  359. typedef typename
  360. mpl::or_<
  361. is_same<l_attr_type, unused_type>
  362. , is_same<r_attr_type, unused_type> >
  363. should_split;
  364. return parse_sequence_assoc(parser, first, last, context, rcontext, attr
  365. , should_split());
  366. }
  367. template <typename Left, typename Right, typename Context, typename RContext>
  368. struct parse_into_container_impl<sequence<Left, Right>, Context, RContext>
  369. {
  370. typedef sequence<Left, Right> parser_type;
  371. template <typename Iterator, typename Attribute>
  372. static bool call(
  373. parser_type const& parser
  374. , Iterator& first, Iterator const& last
  375. , Context const& context, RContext& rcontext, Attribute& attr, mpl::false_)
  376. {
  377. // inform user what went wrong if we jumped here in attempt to
  378. // parse incompatible sequence into fusion::map
  379. static_assert(!is_same< typename traits::attribute_category<Attribute>::type,
  380. traits::associative_attribute>::value,
  381. "To parse directly into fusion::map sequence must produce tuple attribute "
  382. "where type of first element is existing key in fusion::map and second element "
  383. "is value to be stored under that key");
  384. Attribute attr_;
  385. if (!parse_sequence(parser
  386. , first, last, context, rcontext, attr_, traits::container_attribute()))
  387. {
  388. return false;
  389. }
  390. traits::append(attr, std::make_move_iterator(traits::begin(attr_)),
  391. std::make_move_iterator(traits::end(attr_)));
  392. return true;
  393. }
  394. template <typename Iterator, typename Attribute>
  395. static bool call(
  396. parser_type const& parser
  397. , Iterator& first, Iterator const& last
  398. , Context const& context, RContext& rcontext, Attribute& attr, mpl::true_)
  399. {
  400. return parse_into_container_base_impl<parser_type>::call(
  401. parser, first, last, context, rcontext, attr);
  402. }
  403. template <typename Iterator, typename Attribute>
  404. static bool call(
  405. parser_type const& parser
  406. , Iterator& first, Iterator const& last
  407. , Context const& context, RContext& rcontext, Attribute& attr)
  408. {
  409. typedef typename
  410. traits::attribute_of<parser_type, Context>::type
  411. attribute_type;
  412. typedef typename
  413. traits::container_value<Attribute>::type
  414. value_type;
  415. return call(parser, first, last, context, rcontext, attr
  416. , typename traits::is_substitute<attribute_type, value_type>::type());
  417. }
  418. };
  419. }}}}
  420. #endif