rule.hpp 8.1 KB

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