rule.hpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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_RULE_JAN_08_2012_0326PM)
  7. #define BOOST_SPIRIT_X3_RULE_JAN_08_2012_0326PM
  8. #include <boost/spirit/home/x3/nonterminal/detail/rule.hpp>
  9. #include <boost/type_traits/is_same.hpp>
  10. #include <boost/spirit/home/x3/support/context.hpp>
  11. #include <boost/preprocessor/variadic/to_seq.hpp>
  12. #include <boost/preprocessor/variadic/elem.hpp>
  13. #include <boost/preprocessor/seq/for_each.hpp>
  14. #include <type_traits>
  15. #if !defined(BOOST_SPIRIT_X3_NO_RTTI)
  16. #include <typeinfo>
  17. #endif
  18. namespace boost { namespace spirit { namespace x3
  19. {
  20. // default parse_rule implementation
  21. template <typename ID, typename Attribute, typename Iterator
  22. , typename Context, typename ActualAttribute>
  23. inline detail::default_parse_rule_result
  24. parse_rule(
  25. rule<ID, Attribute> /* rule_ */
  26. , Iterator& first, Iterator const& last
  27. , Context const& context, ActualAttribute& attr)
  28. {
  29. static_assert(!is_same<decltype(get<ID>(context)), unused_type>::value,
  30. "BOOST_SPIRIT_DEFINE undefined for this rule.");
  31. return get<ID>(context).parse(first, last, context, unused, attr);
  32. }
  33. template <typename ID, typename RHS, typename Attribute, bool force_attribute_>
  34. struct rule_definition : parser<rule_definition<ID, RHS, Attribute, force_attribute_>>
  35. {
  36. typedef rule_definition<ID, RHS, Attribute, force_attribute_> this_type;
  37. typedef ID id;
  38. typedef RHS rhs_type;
  39. typedef rule<ID, Attribute> lhs_type;
  40. typedef Attribute attribute_type;
  41. static bool const has_attribute =
  42. !is_same<Attribute, unused_type>::value;
  43. static bool const handles_container =
  44. traits::is_container<Attribute>::value;
  45. static bool const force_attribute =
  46. force_attribute_;
  47. rule_definition(RHS const& rhs, char const* name)
  48. : rhs(rhs), name(name) {}
  49. template <typename Iterator, typename Context, typename Attribute_>
  50. bool parse(Iterator& first, Iterator const& last
  51. , Context const& context, unused_type, Attribute_& attr) const
  52. {
  53. return detail::rule_parser<attribute_type, ID>
  54. ::call_rule_definition(
  55. rhs, name, first, last
  56. , context
  57. , attr
  58. , mpl::bool_<force_attribute>());
  59. }
  60. RHS rhs;
  61. char const* name;
  62. };
  63. template <typename ID, typename Attribute, bool force_attribute_>
  64. struct rule : parser<rule<ID, Attribute>>
  65. {
  66. typedef ID id;
  67. typedef Attribute attribute_type;
  68. static bool const has_attribute =
  69. !std::is_same<std::remove_const_t<Attribute>, unused_type>::value;
  70. static bool const handles_container =
  71. traits::is_container<Attribute>::value;
  72. static bool const force_attribute = force_attribute_;
  73. #if !defined(BOOST_SPIRIT_X3_NO_RTTI)
  74. rule() : name(typeid(rule).name()) {}
  75. #else
  76. rule() : name("unnamed") {}
  77. #endif
  78. rule(char const* name)
  79. : name(name) {}
  80. template <typename RHS>
  81. rule_definition<
  82. ID, typename extension::as_parser<RHS>::value_type, Attribute, force_attribute_>
  83. operator=(RHS const& rhs) const
  84. {
  85. return { as_parser(rhs), name };
  86. }
  87. template <typename RHS>
  88. rule_definition<
  89. ID, typename extension::as_parser<RHS>::value_type, Attribute, true>
  90. operator%=(RHS const& rhs) const
  91. {
  92. return { as_parser(rhs), name };
  93. }
  94. template <typename Iterator, typename Context, typename Attribute_>
  95. bool parse(Iterator& first, Iterator const& last
  96. , Context const& context, unused_type, Attribute_& attr) const
  97. {
  98. static_assert(has_attribute,
  99. "The rule does not have an attribute. Check your parser.");
  100. using transform = traits::transform_attribute<
  101. Attribute_, attribute_type, parser_id>;
  102. using transform_attr = typename transform::type;
  103. transform_attr attr_ = transform::pre(attr);
  104. if (parse_rule(*this, first, last, context, attr_)) {
  105. transform::post(attr, std::forward<transform_attr>(attr_));
  106. return true;
  107. }
  108. return false;
  109. }
  110. template <typename Iterator, typename Context>
  111. bool parse(Iterator& first, Iterator const& last
  112. , Context const& context, unused_type, unused_type) const
  113. {
  114. // make sure we pass exactly the rule attribute type
  115. attribute_type no_attr;
  116. return parse_rule(*this, first, last, context, no_attr);
  117. }
  118. char const* name;
  119. };
  120. namespace traits
  121. {
  122. template <typename T, typename Enable = void>
  123. struct is_rule : mpl::false_ {};
  124. template <typename ID, typename Attribute>
  125. struct is_rule<rule<ID, Attribute>> : mpl::true_ {};
  126. template <typename ID, typename Attribute, typename RHS, bool force_attribute>
  127. struct is_rule<rule_definition<ID, RHS, Attribute, force_attribute>> : mpl::true_ {};
  128. }
  129. template <typename T>
  130. struct get_info<T, typename enable_if<traits::is_rule<T>>::type>
  131. {
  132. typedef std::string result_type;
  133. std::string operator()(T const& r) const
  134. {
  135. BOOST_ASSERT_MSG(r.name, "uninitialized rule"); // static initialization order fiasco
  136. return r.name? r.name : "uninitialized";
  137. }
  138. };
  139. #define BOOST_SPIRIT_DECLARE_(r, data, rule_type) \
  140. template <typename Iterator, typename Context> \
  141. bool parse_rule( \
  142. rule_type rule_ \
  143. , Iterator& first, Iterator const& last \
  144. , Context const& context, rule_type::attribute_type& attr); \
  145. /***/
  146. #define BOOST_SPIRIT_DECLARE(...) BOOST_PP_SEQ_FOR_EACH( \
  147. BOOST_SPIRIT_DECLARE_, _, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \
  148. /***/
  149. #if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
  150. #define BOOST_SPIRIT_DEFINE_(r, data, rule_name) \
  151. using BOOST_PP_CAT(rule_name, _synonym) = decltype(rule_name); \
  152. template <typename Iterator, typename Context> \
  153. inline bool parse_rule( \
  154. BOOST_PP_CAT(rule_name, _synonym) /* rule_ */ \
  155. , Iterator& first, Iterator const& last \
  156. , Context const& context, BOOST_PP_CAT(rule_name, _synonym)::attribute_type& attr) \
  157. { \
  158. using boost::spirit::x3::unused; \
  159. static auto const def_ = (rule_name = BOOST_PP_CAT(rule_name, _def)); \
  160. return def_.parse(first, last, context, unused, attr); \
  161. } \
  162. /***/
  163. #else
  164. #define BOOST_SPIRIT_DEFINE_(r, data, rule_name) \
  165. template <typename Iterator, typename Context> \
  166. inline bool parse_rule( \
  167. decltype(rule_name) /* rule_ */ \
  168. , Iterator& first, Iterator const& last \
  169. , Context const& context, decltype(rule_name)::attribute_type& attr) \
  170. { \
  171. using boost::spirit::x3::unused; \
  172. static auto const def_ = (rule_name = BOOST_PP_CAT(rule_name, _def)); \
  173. return def_.parse(first, last, context, unused, attr); \
  174. } \
  175. /***/
  176. #endif
  177. #define BOOST_SPIRIT_DEFINE(...) BOOST_PP_SEQ_FOR_EACH( \
  178. BOOST_SPIRIT_DEFINE_, _, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \
  179. /***/
  180. #define BOOST_SPIRIT_INSTANTIATE(rule_type, Iterator, Context) \
  181. template bool parse_rule<Iterator, Context>( \
  182. rule_type rule_ \
  183. , Iterator& first, Iterator const& last \
  184. , Context const& context, rule_type::attribute_type&); \
  185. /***/
  186. }}}
  187. #endif