parser.hpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*=============================================================================
  2. Copyright (c) 2001-2014 Joel de Guzman
  3. Copyright (c) 2013 Agustin Berge
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. ==============================================================================*/
  7. #if !defined(BOOST_SPIRIT_X3_PARSER_OCTOBER_16_2008_0254PM)
  8. #define BOOST_SPIRIT_X3_PARSER_OCTOBER_16_2008_0254PM
  9. #include <boost/mpl/bool.hpp>
  10. #include <boost/type_traits/is_base_of.hpp>
  11. #include <boost/type_traits/remove_cv.hpp>
  12. #include <boost/type_traits/remove_reference.hpp>
  13. #include <boost/utility/declval.hpp>
  14. #include <boost/utility/enable_if.hpp>
  15. #include <boost/spirit/home/x3/support/unused.hpp>
  16. #include <boost/spirit/home/x3/support/context.hpp>
  17. #include <boost/spirit/home/x3/support/traits/has_attribute.hpp>
  18. #include <boost/spirit/home/x3/support/utility/sfinae.hpp>
  19. #include <boost/core/ignore_unused.hpp>
  20. #include <boost/assert.hpp>
  21. #include <string>
  22. #if !defined(BOOST_SPIRIT_X3_NO_RTTI)
  23. #include <typeinfo>
  24. #endif
  25. namespace boost { namespace spirit { namespace x3
  26. {
  27. template <typename Subject, typename Action>
  28. struct action;
  29. template <typename Subject, typename Handler>
  30. struct guard;
  31. struct parser_base {};
  32. struct parser_id;
  33. template <typename Derived>
  34. struct parser : parser_base
  35. {
  36. typedef Derived derived_type;
  37. static bool const handles_container = false;
  38. static bool const is_pass_through_unary = false;
  39. static bool const has_action = false;
  40. Derived const& derived() const
  41. {
  42. return *static_cast<Derived const*>(this);
  43. }
  44. template <typename Action>
  45. action<Derived, Action> operator[](Action f) const
  46. {
  47. return { this->derived(), f };
  48. }
  49. template <typename Handler>
  50. guard<Derived, Handler> on_error(Handler f) const
  51. {
  52. return { this->derived(), f };
  53. }
  54. };
  55. namespace detail {
  56. template <typename Parser>
  57. static void assert_initialized_rule(Parser const& p) {
  58. boost::ignore_unused(p);
  59. // Assert that we are not copying an unitialized static rule. If
  60. // the static is in another TU, it may be initialized after we copy
  61. // it. If so, its name member will be nullptr.
  62. //
  63. // Rather than hardcoding behaviour for rule-type subject parsers,
  64. // we simply allow get_info<> to do the check in debug builds.
  65. #ifndef NDEBUG
  66. what(p); // note: allows get_info<> to diagnose the issue
  67. #endif
  68. }
  69. }
  70. struct unary_category;
  71. struct binary_category;
  72. template <typename Subject, typename Derived>
  73. struct unary_parser : parser<Derived>
  74. {
  75. typedef unary_category category;
  76. typedef Subject subject_type;
  77. static bool const has_action = Subject::has_action;
  78. unary_parser(Subject const& subject)
  79. : subject(subject) { detail::assert_initialized_rule(subject); }
  80. unary_parser const& get_unary() const { return *this; }
  81. Subject subject;
  82. };
  83. template <typename Left, typename Right, typename Derived>
  84. struct binary_parser : parser<Derived>
  85. {
  86. typedef binary_category category;
  87. typedef Left left_type;
  88. typedef Right right_type;
  89. static bool const has_action =
  90. left_type::has_action || right_type::has_action;
  91. binary_parser(Left const& left, Right const& right)
  92. : left(left), right(right)
  93. {
  94. detail::assert_initialized_rule(left);
  95. detail::assert_initialized_rule(right);
  96. }
  97. binary_parser const& get_binary() const { return *this; }
  98. Left left;
  99. Right right;
  100. };
  101. ///////////////////////////////////////////////////////////////////////////
  102. // as_parser: convert a type, T, into a parser.
  103. ///////////////////////////////////////////////////////////////////////////
  104. namespace extension
  105. {
  106. namespace detail
  107. {
  108. namespace as_parser_guard
  109. {
  110. void as_spirit_parser(...);
  111. template<typename T, typename R =
  112. decltype(as_spirit_parser(boost::declval<T const&>()))>
  113. struct deduce_as_parser
  114. {
  115. typedef R type;
  116. typedef typename
  117. boost::remove_cv<
  118. typename boost::remove_reference<R>::type
  119. >::type
  120. value_type;
  121. static type call(T const& v)
  122. {
  123. return as_spirit_parser(v);
  124. }
  125. };
  126. template<typename T>
  127. struct deduce_as_parser<T, void>
  128. {};
  129. }
  130. using as_parser_guard::deduce_as_parser;
  131. }
  132. template <typename T, typename Enable = void>
  133. struct as_parser : detail::deduce_as_parser<T> {};
  134. template <>
  135. struct as_parser<unused_type>
  136. {
  137. typedef unused_type type;
  138. typedef unused_type value_type;
  139. static type call(unused_type)
  140. {
  141. return unused;
  142. }
  143. };
  144. template <typename Derived>
  145. struct as_parser<Derived
  146. , typename enable_if<is_base_of<parser_base, Derived>>::type>
  147. {
  148. typedef Derived const& type;
  149. typedef Derived value_type;
  150. static type call(Derived const& p)
  151. {
  152. return p;
  153. }
  154. };
  155. template <typename Derived>
  156. struct as_parser<parser<Derived>>
  157. {
  158. typedef Derived const& type;
  159. typedef Derived value_type;
  160. static type call(parser<Derived> const& p)
  161. {
  162. return p.derived();
  163. }
  164. };
  165. }
  166. template <typename T>
  167. inline typename extension::as_parser<T>::type
  168. as_parser(T const& x)
  169. {
  170. return extension::as_parser<T>::call(x);
  171. }
  172. template <typename Derived>
  173. inline Derived const&
  174. as_parser(parser<Derived> const& p)
  175. {
  176. return p.derived();
  177. }
  178. ///////////////////////////////////////////////////////////////////////////
  179. // The main what function
  180. //
  181. // Note: unlike Spirit2, spirit parsers are no longer required to have a
  182. // "what" member function. In X3, we specialize the get_info struct
  183. // below where needed. If a specialization is not provided, the default
  184. // below will be used. The default "what" result will be the typeid
  185. // name of the parser if BOOST_SPIRIT_X3_NO_RTTI is not defined, otherwise
  186. // "undefined"
  187. ///////////////////////////////////////////////////////////////////////////
  188. template <typename Parser, typename Enable = void>
  189. struct get_info
  190. {
  191. typedef std::string result_type;
  192. std::string operator()(Parser const&) const
  193. {
  194. #if !defined(BOOST_SPIRIT_X3_NO_RTTI)
  195. return typeid(Parser).name();
  196. #else
  197. return "undefined";
  198. #endif
  199. }
  200. };
  201. template <typename Parser>
  202. std::string what(Parser const& p)
  203. {
  204. return get_info<Parser>()(p);
  205. }
  206. }}}
  207. namespace boost { namespace spirit { namespace x3 { namespace traits
  208. {
  209. template <typename Subject, typename Derived, typename Context>
  210. struct has_attribute<x3::unary_parser<Subject, Derived>, Context>
  211. : has_attribute<Subject, Context> {};
  212. template <typename Left, typename Right, typename Derived, typename Context>
  213. struct has_attribute<x3::binary_parser<Left, Right, Derived>, Context>
  214. : mpl::bool_<has_attribute<Left, Context>::value ||
  215. has_attribute<Right, Context>::value> {};
  216. }}}}
  217. #endif