sequence.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  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/mpl/if.hpp>
  23. #include <boost/type_traits/add_reference.hpp>
  24. #include <boost/type_traits/is_same.hpp>
  25. #include <iterator> // for std::make_move_iterator
  26. namespace boost { namespace spirit { namespace x3
  27. {
  28. template <typename Left, typename Right>
  29. struct sequence;
  30. }}}
  31. namespace boost { namespace spirit { namespace x3 { namespace detail
  32. {
  33. template <typename Parser, typename Context, typename Enable = void>
  34. struct sequence_size
  35. {
  36. static int const value = traits::has_attribute<Parser, Context>::value;
  37. };
  38. template <typename Parser, typename Context>
  39. struct sequence_size_subject
  40. : sequence_size<typename Parser::subject_type, Context> {};
  41. template <typename Parser, typename Context>
  42. struct sequence_size<Parser, Context
  43. , typename enable_if_c<(Parser::is_pass_through_unary)>::type>
  44. : sequence_size_subject<Parser, Context> {};
  45. template <typename L, typename R, typename Context>
  46. struct sequence_size<sequence<L, R>, Context>
  47. {
  48. static int const value =
  49. sequence_size<L, Context>::value +
  50. sequence_size<R, Context>::value;
  51. };
  52. struct pass_sequence_attribute_unused
  53. {
  54. typedef unused_type type;
  55. template <typename T>
  56. static unused_type
  57. call(T&)
  58. {
  59. return unused_type();
  60. }
  61. };
  62. template <typename Attribute>
  63. struct pass_sequence_attribute_size_one_view
  64. {
  65. typedef typename fusion::result_of::deref<
  66. typename fusion::result_of::begin<Attribute>::type
  67. >::type type;
  68. static type call(Attribute& attribute)
  69. {
  70. return fusion::deref(fusion::begin(attribute));
  71. }
  72. };
  73. template <typename Attribute>
  74. struct pass_through_sequence_attribute
  75. {
  76. typedef Attribute& type;
  77. template <typename Attribute_>
  78. static Attribute_&
  79. call(Attribute_& attribute)
  80. {
  81. return attribute;
  82. }
  83. };
  84. template <typename Parser, typename Attribute, typename Enable = void>
  85. struct pass_sequence_attribute :
  86. mpl::if_<
  87. traits::is_size_one_view<Attribute>
  88. , pass_sequence_attribute_size_one_view<Attribute>
  89. , pass_through_sequence_attribute<Attribute>>::type {};
  90. template <typename L, typename R, typename Attribute>
  91. struct pass_sequence_attribute<sequence<L, R>, Attribute>
  92. : pass_through_sequence_attribute<Attribute> {};
  93. template <typename Parser, typename Attribute>
  94. struct pass_sequence_attribute_subject :
  95. pass_sequence_attribute<typename Parser::subject_type, Attribute> {};
  96. template <typename Parser, typename Attribute>
  97. struct pass_sequence_attribute<Parser, Attribute
  98. , typename enable_if_c<(Parser::is_pass_through_unary)>::type>
  99. : pass_sequence_attribute_subject<Parser, Attribute> {};
  100. template <typename L, typename R, typename Attribute, typename Context
  101. , typename Enable = void>
  102. struct partition_attribute
  103. {
  104. using attr_category = typename traits::attribute_category<Attribute>::type;
  105. static_assert(is_same<traits::tuple_attribute, attr_category>::value,
  106. "The parser expects tuple-like attribute type");
  107. static int const l_size = sequence_size<L, Context>::value;
  108. static int const r_size = sequence_size<R, Context>::value;
  109. static int constexpr actual_size = fusion::result_of::size<Attribute>::value;
  110. static int constexpr expected_size = l_size + r_size;
  111. // If you got an error here, then you are trying to pass
  112. // a fusion sequence with the wrong number of elements
  113. // as that expected by the (sequence) parser.
  114. static_assert(
  115. actual_size >= expected_size
  116. , "Size of the passed attribute is less than expected."
  117. );
  118. static_assert(
  119. actual_size <= expected_size
  120. , "Size of the passed attribute is bigger than expected."
  121. );
  122. typedef typename fusion::result_of::begin<Attribute>::type l_begin;
  123. typedef typename fusion::result_of::advance_c<l_begin, l_size>::type l_end;
  124. typedef typename fusion::result_of::end<Attribute>::type r_end;
  125. typedef fusion::iterator_range<l_begin, l_end> l_part;
  126. typedef fusion::iterator_range<l_end, r_end> r_part;
  127. typedef pass_sequence_attribute<L, l_part> l_pass;
  128. typedef pass_sequence_attribute<R, r_part> r_pass;
  129. static l_part left(Attribute& s)
  130. {
  131. auto i = fusion::begin(s);
  132. return l_part(i, fusion::advance_c<l_size>(i));
  133. }
  134. static r_part right(Attribute& s)
  135. {
  136. return r_part(
  137. fusion::advance_c<l_size>(fusion::begin(s))
  138. , fusion::end(s));
  139. }
  140. };
  141. template <typename L, typename R, typename Attribute, typename Context>
  142. struct partition_attribute<L, R, Attribute, Context,
  143. typename enable_if_c<(!traits::has_attribute<L, Context>::value &&
  144. traits::has_attribute<R, Context>::value)>::type>
  145. {
  146. typedef unused_type l_part;
  147. typedef Attribute& r_part;
  148. typedef pass_sequence_attribute_unused l_pass;
  149. typedef pass_sequence_attribute<R, Attribute> r_pass;
  150. static unused_type left(Attribute&)
  151. {
  152. return unused;
  153. }
  154. static Attribute& right(Attribute& s)
  155. {
  156. return s;
  157. }
  158. };
  159. template <typename L, typename R, typename Attribute, typename Context>
  160. struct partition_attribute<L, R, Attribute, Context,
  161. typename enable_if_c<(traits::has_attribute<L, Context>::value &&
  162. !traits::has_attribute<R, Context>::value)>::type>
  163. {
  164. typedef Attribute& l_part;
  165. typedef unused_type r_part;
  166. typedef pass_sequence_attribute<L, Attribute> l_pass;
  167. typedef pass_sequence_attribute_unused r_pass;
  168. static Attribute& left(Attribute& s)
  169. {
  170. return s;
  171. }
  172. static unused_type right(Attribute&)
  173. {
  174. return unused;
  175. }
  176. };
  177. template <typename L, typename R, typename Attribute, typename Context>
  178. struct partition_attribute<L, R, Attribute, Context,
  179. typename enable_if_c<(!traits::has_attribute<L, Context>::value &&
  180. !traits::has_attribute<R, Context>::value)>::type>
  181. {
  182. typedef unused_type l_part;
  183. typedef unused_type r_part;
  184. typedef pass_sequence_attribute_unused l_pass;
  185. typedef pass_sequence_attribute_unused r_pass;
  186. static unused_type left(Attribute&)
  187. {
  188. return unused;
  189. }
  190. static unused_type right(Attribute&)
  191. {
  192. return unused;
  193. }
  194. };
  195. template <typename Parser, typename Iterator, typename Context
  196. , typename RContext, typename Attribute, typename AttributeCategory>
  197. bool parse_sequence(
  198. Parser const& parser, Iterator& first, Iterator const& last
  199. , Context const& context, RContext& rcontext, Attribute& attr
  200. , AttributeCategory)
  201. {
  202. using Left = typename Parser::left_type;
  203. using Right = typename Parser::right_type;
  204. using partition = partition_attribute<Left, Right, Attribute, Context>;
  205. using l_pass = typename partition::l_pass;
  206. using r_pass = typename partition::r_pass;
  207. typename partition::l_part l_part = partition::left(attr);
  208. typename partition::r_part r_part = partition::right(attr);
  209. typename l_pass::type l_attr = l_pass::call(l_part);
  210. typename r_pass::type r_attr = r_pass::call(r_part);
  211. Iterator save = first;
  212. if (parser.left.parse(first, last, context, rcontext, l_attr)
  213. && parser.right.parse(first, last, context, rcontext, r_attr))
  214. return true;
  215. first = save;
  216. return false;
  217. }
  218. template <typename Parser, typename Context>
  219. constexpr bool pass_sequence_container_attribute
  220. = sequence_size<Parser, Context>::value > 1;
  221. template <typename Parser, typename Iterator, typename Context
  222. , typename RContext, typename Attribute>
  223. typename enable_if_c<pass_sequence_container_attribute<Parser, Context>, bool>::type
  224. parse_sequence_container(
  225. Parser const& parser
  226. , Iterator& first, Iterator const& last, Context const& context
  227. , RContext& rcontext, Attribute& attr)
  228. {
  229. return parser.parse(first, last, context, rcontext, attr);
  230. }
  231. template <typename Parser, typename Iterator, typename Context
  232. , typename RContext, typename Attribute>
  233. typename disable_if_c<pass_sequence_container_attribute<Parser, Context>, bool>::type
  234. parse_sequence_container(
  235. Parser const& parser
  236. , Iterator& first, Iterator const& last, Context const& context
  237. , RContext& rcontext, Attribute& attr)
  238. {
  239. return parse_into_container(parser, first, last, context, rcontext, attr);
  240. }
  241. template <typename Parser, typename Iterator, typename Context
  242. , typename RContext, typename Attribute>
  243. bool parse_sequence(
  244. Parser const& parser , Iterator& first, Iterator const& last
  245. , Context const& context, RContext& rcontext, Attribute& attr
  246. , traits::container_attribute)
  247. {
  248. Iterator save = first;
  249. if (parse_sequence_container(parser.left, first, last, context, rcontext, attr)
  250. && parse_sequence_container(parser.right, first, last, context, rcontext, attr))
  251. return true;
  252. first = save;
  253. return false;
  254. }
  255. template <typename Parser, typename Iterator, typename Context
  256. , typename RContext, typename Attribute>
  257. bool parse_sequence_assoc(
  258. Parser const& parser , Iterator& first, Iterator const& last
  259. , Context const& context, RContext& rcontext, Attribute& attr, mpl::false_ /*should_split*/)
  260. {
  261. return parse_into_container(parser, first, last, context, rcontext, attr);
  262. }
  263. template <typename Parser, typename Iterator, typename Context
  264. , typename RContext, typename Attribute>
  265. bool parse_sequence_assoc(
  266. Parser const& parser , Iterator& first, Iterator const& last
  267. , Context const& context, RContext& rcontext, Attribute& attr, mpl::true_ /*should_split*/)
  268. {
  269. Iterator save = first;
  270. if (parser.left.parse( first, last, context, rcontext, attr)
  271. && parser.right.parse(first, last, context, rcontext, attr))
  272. return true;
  273. first = save;
  274. return false;
  275. }
  276. template <typename Parser, typename Iterator, typename Context
  277. , typename RContext, typename Attribute>
  278. bool parse_sequence(
  279. Parser const& parser, Iterator& first, Iterator const& last
  280. , Context const& context, RContext& rcontext, Attribute& attr
  281. , traits::associative_attribute)
  282. {
  283. // we can come here in 2 cases:
  284. // - when sequence is key >> value and therefore must
  285. // be parsed with tuple synthesized attribute and then
  286. // that tuple is used to save into associative attribute provided here.
  287. // Example: key >> value;
  288. //
  289. // - when either this->left or this->right provides full key-value
  290. // pair (like in case 1) and another one provides nothing.
  291. // Example: eps >> rule<class x; fusion::map<...> >
  292. //
  293. // first case must be parsed as whole, and second one should
  294. // be parsed separately for left and right.
  295. typedef typename traits::attribute_of<
  296. decltype(parser.left), Context>::type l_attr_type;
  297. typedef typename traits::attribute_of<
  298. decltype(parser.right), Context>::type r_attr_type;
  299. typedef typename
  300. mpl::or_<
  301. is_same<l_attr_type, unused_type>
  302. , is_same<r_attr_type, unused_type> >
  303. should_split;
  304. return parse_sequence_assoc(parser, first, last, context, rcontext, attr
  305. , should_split());
  306. }
  307. template <typename Left, typename Right, typename Context, typename RContext>
  308. struct parse_into_container_impl<sequence<Left, Right>, Context, RContext>
  309. {
  310. typedef sequence<Left, Right> parser_type;
  311. template <typename Iterator, typename Attribute>
  312. static bool call(
  313. parser_type const& parser
  314. , Iterator& first, Iterator const& last
  315. , Context const& context, RContext& rcontext, Attribute& attr, mpl::false_)
  316. {
  317. // inform user what went wrong if we jumped here in attempt to
  318. // parse incompatible sequence into fusion::map
  319. static_assert(!is_same< typename traits::attribute_category<Attribute>::type,
  320. traits::associative_attribute>::value,
  321. "To parse directly into fusion::map sequence must produce tuple attribute "
  322. "where type of first element is existing key in fusion::map and second element "
  323. "is value to be stored under that key");
  324. Attribute attr_{};
  325. if (!parse_sequence(parser
  326. , first, last, context, rcontext, attr_, traits::container_attribute()))
  327. {
  328. return false;
  329. }
  330. traits::append(attr, std::make_move_iterator(traits::begin(attr_)),
  331. std::make_move_iterator(traits::end(attr_)));
  332. return true;
  333. }
  334. template <typename Iterator, typename Attribute>
  335. static bool call(
  336. parser_type const& parser
  337. , Iterator& first, Iterator const& last
  338. , Context const& context, RContext& rcontext, Attribute& attr, mpl::true_)
  339. {
  340. return parse_into_container_base_impl<parser_type>::call(
  341. parser, first, last, context, rcontext, attr);
  342. }
  343. template <typename Iterator, typename Attribute>
  344. static bool call(
  345. parser_type const& parser
  346. , Iterator& first, Iterator const& last
  347. , Context const& context, RContext& rcontext, Attribute& attr)
  348. {
  349. typedef typename
  350. traits::attribute_of<parser_type, Context>::type
  351. attribute_type;
  352. typedef typename
  353. traits::container_value<Attribute>::type
  354. value_type;
  355. return call(parser, first, last, context, rcontext, attr
  356. , typename traits::is_substitute<attribute_type, value_type>::type());
  357. }
  358. };
  359. }}}}
  360. #endif