rule.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  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_DETAIL_RULE_JAN_08_2012_0326PM)
  7. #define BOOST_SPIRIT_X3_DETAIL_RULE_JAN_08_2012_0326PM
  8. #include <boost/core/ignore_unused.hpp>
  9. #include <boost/spirit/home/x3/auxiliary/guard.hpp>
  10. #include <boost/spirit/home/x3/core/parser.hpp>
  11. #include <boost/spirit/home/x3/core/skip_over.hpp>
  12. #include <boost/spirit/home/x3/directive/expect.hpp>
  13. #include <boost/spirit/home/x3/nonterminal/detail/transform_attribute.hpp>
  14. #include <boost/utility/addressof.hpp>
  15. #if defined(BOOST_SPIRIT_X3_DEBUG)
  16. #include <boost/spirit/home/x3/nonterminal/simple_trace.hpp>
  17. #endif
  18. #include <type_traits>
  19. namespace boost { namespace spirit { namespace x3
  20. {
  21. template <typename ID>
  22. struct identity;
  23. template <typename ID, typename Attribute = unused_type, bool force_attribute = false>
  24. struct rule;
  25. struct parse_pass_context_tag;
  26. namespace detail
  27. {
  28. template <typename ID>
  29. struct rule_id {};
  30. // we use this so we can detect if the default parse_rule
  31. // is the being called.
  32. struct default_parse_rule_result
  33. {
  34. default_parse_rule_result(bool r)
  35. : r(r) {}
  36. operator bool() const { return r; }
  37. bool r;
  38. };
  39. }
  40. // default parse_rule implementation
  41. template <typename ID, typename Iterator
  42. , typename Context, typename ActualAttribute>
  43. inline detail::default_parse_rule_result
  44. parse_rule(
  45. detail::rule_id<ID>
  46. , Iterator& first, Iterator const& last
  47. , Context const& context, ActualAttribute& attr);
  48. }}}
  49. namespace boost { namespace spirit { namespace x3 { namespace detail
  50. {
  51. #if defined(BOOST_SPIRIT_X3_DEBUG)
  52. template <typename Iterator, typename Attribute>
  53. struct context_debug
  54. {
  55. context_debug(
  56. char const* rule_name
  57. , Iterator const& first, Iterator const& last
  58. , Attribute const& attr
  59. , bool const& ok_parse //was parse successful?
  60. )
  61. : ok_parse(ok_parse), rule_name(rule_name)
  62. , first(first), last(last)
  63. , attr(attr)
  64. , f(detail::get_simple_trace())
  65. {
  66. f(first, last, attr, pre_parse, rule_name);
  67. }
  68. ~context_debug()
  69. {
  70. auto status = ok_parse ? successful_parse : failed_parse ;
  71. f(first, last, attr, status, rule_name);
  72. }
  73. bool const& ok_parse;
  74. char const* rule_name;
  75. Iterator const& first;
  76. Iterator const& last;
  77. Attribute const& attr;
  78. detail::simple_trace_type& f;
  79. };
  80. #endif
  81. template <typename ID, typename Iterator, typename Context, typename Enable = void>
  82. struct has_on_error : mpl::false_ {};
  83. template <typename ID, typename Iterator, typename Context>
  84. struct has_on_error<ID, Iterator, Context,
  85. decltype(void(
  86. std::declval<ID>().on_error(
  87. std::declval<Iterator&>()
  88. , std::declval<Iterator>()
  89. , std::declval<expectation_failure<Iterator>>()
  90. , std::declval<Context>()
  91. )
  92. ))
  93. >
  94. : mpl::true_
  95. {};
  96. template <typename ID, typename Iterator, typename Attribute, typename Context, typename Enable = void>
  97. struct has_on_success : mpl::false_ {};
  98. template <typename ID, typename Iterator, typename Attribute, typename Context>
  99. struct has_on_success<ID, Iterator, Context, Attribute,
  100. decltype(void(
  101. std::declval<ID>().on_success(
  102. std::declval<Iterator&>()
  103. , std::declval<Iterator&>()
  104. , std::declval<Attribute&>()
  105. , std::declval<Context>()
  106. )
  107. ))
  108. >
  109. : mpl::true_
  110. {};
  111. template <typename ID>
  112. struct make_id
  113. {
  114. typedef identity<ID> type;
  115. };
  116. template <typename ID>
  117. struct make_id<identity<ID>>
  118. {
  119. typedef identity<ID> type;
  120. };
  121. template <typename ID, typename RHS, typename Context>
  122. Context const&
  123. make_rule_context(RHS const& /* rhs */, Context const& context
  124. , mpl::false_ /* is_default_parse_rule */)
  125. {
  126. return context;
  127. }
  128. template <typename ID, typename RHS, typename Context>
  129. auto make_rule_context(RHS const& rhs, Context const& context
  130. , mpl::true_ /* is_default_parse_rule */ )
  131. {
  132. return make_unique_context<ID>(rhs, context);
  133. }
  134. template <typename Attribute, typename ID, bool skip_definition_injection = false>
  135. struct rule_parser
  136. {
  137. template <typename Iterator, typename Context, typename ActualAttribute>
  138. static bool call_on_success(
  139. Iterator& /* before */, Iterator& /* after */
  140. , Context const& /* context */, ActualAttribute& /* attr */
  141. , mpl::false_ /* No on_success handler */ )
  142. {
  143. return true;
  144. }
  145. template <typename Iterator, typename Context, typename ActualAttribute>
  146. static bool call_on_success(
  147. Iterator& before, Iterator& after
  148. , Context const& context, ActualAttribute& attr
  149. , mpl::true_ /* Has on_success handler */)
  150. {
  151. x3::skip_over(before, after, context);
  152. bool pass = true;
  153. ID().on_success(
  154. before
  155. , after
  156. , attr
  157. , make_context<parse_pass_context_tag>(pass, context)
  158. );
  159. return pass;
  160. }
  161. template <typename RHS, typename Iterator, typename Context
  162. , typename RContext, typename ActualAttribute>
  163. static bool parse_rhs_main(
  164. RHS const& rhs
  165. , Iterator& first, Iterator const& last
  166. , Context const& context, RContext& rcontext, ActualAttribute& attr
  167. , mpl::false_)
  168. {
  169. // see if the user has a BOOST_SPIRIT_DEFINE for this rule
  170. typedef
  171. decltype(parse_rule(
  172. detail::rule_id<ID>{}, first, last
  173. , make_unique_context<ID>(rhs, context), std::declval<Attribute&>()))
  174. parse_rule_result;
  175. // If there is no BOOST_SPIRIT_DEFINE for this rule,
  176. // we'll make a context for this rule tagged by its ID
  177. // so we can extract the rule later on in the default
  178. // (generic) parse_rule function.
  179. typedef
  180. is_same<parse_rule_result, default_parse_rule_result>
  181. is_default_parse_rule;
  182. Iterator start = first;
  183. bool r = rhs.parse(
  184. first
  185. , last
  186. , make_rule_context<ID>(rhs, context, std::conditional_t<skip_definition_injection, mpl::false_, is_default_parse_rule>())
  187. , rcontext
  188. , attr
  189. );
  190. if (r)
  191. {
  192. r = call_on_success(start, first, context, attr
  193. , has_on_success<ID, Iterator, Context, ActualAttribute>());
  194. }
  195. return r;
  196. }
  197. template <typename RHS, typename Iterator, typename Context
  198. , typename RContext, typename ActualAttribute>
  199. static bool parse_rhs_main(
  200. RHS const& rhs
  201. , Iterator& first, Iterator const& last
  202. , Context const& context, RContext& rcontext, ActualAttribute& attr
  203. , mpl::true_ /* on_error is found */)
  204. {
  205. for (;;)
  206. {
  207. try
  208. {
  209. return parse_rhs_main(
  210. rhs, first, last, context, rcontext, attr, mpl::false_());
  211. }
  212. catch (expectation_failure<Iterator> const& x)
  213. {
  214. switch (ID().on_error(first, last, x, context))
  215. {
  216. case error_handler_result::fail:
  217. return false;
  218. case error_handler_result::retry:
  219. continue;
  220. case error_handler_result::accept:
  221. return true;
  222. case error_handler_result::rethrow:
  223. throw;
  224. }
  225. }
  226. }
  227. }
  228. template <typename RHS, typename Iterator
  229. , typename Context, typename RContext, typename ActualAttribute>
  230. static bool parse_rhs_main(
  231. RHS const& rhs
  232. , Iterator& first, Iterator const& last
  233. , Context const& context, RContext& rcontext, ActualAttribute& attr)
  234. {
  235. return parse_rhs_main(
  236. rhs, first, last, context, rcontext, attr
  237. , has_on_error<ID, Iterator, Context>()
  238. );
  239. }
  240. template <typename RHS, typename Iterator
  241. , typename Context, typename RContext, typename ActualAttribute>
  242. static bool parse_rhs(
  243. RHS const& rhs
  244. , Iterator& first, Iterator const& last
  245. , Context const& context, RContext& rcontext, ActualAttribute& attr
  246. , mpl::false_)
  247. {
  248. return parse_rhs_main(rhs, first, last, context, rcontext, attr);
  249. }
  250. template <typename RHS, typename Iterator
  251. , typename Context, typename RContext, typename ActualAttribute>
  252. static bool parse_rhs(
  253. RHS const& rhs
  254. , Iterator& first, Iterator const& last
  255. , Context const& context, RContext& rcontext, ActualAttribute& /* attr */
  256. , mpl::true_)
  257. {
  258. return parse_rhs_main(rhs, first, last, context, rcontext, unused);
  259. }
  260. template <typename RHS, typename Iterator, typename Context
  261. , typename ActualAttribute, typename ExplicitAttrPropagation>
  262. static bool call_rule_definition(
  263. RHS const& rhs
  264. , char const* rule_name
  265. , Iterator& first, Iterator const& last
  266. , Context const& context, ActualAttribute& attr
  267. , ExplicitAttrPropagation)
  268. {
  269. boost::ignore_unused(rule_name);
  270. // do down-stream transformation, provides attribute for
  271. // rhs parser
  272. typedef traits::transform_attribute<
  273. ActualAttribute, Attribute, parser_id>
  274. transform;
  275. typedef typename transform::type transform_attr;
  276. transform_attr attr_ = transform::pre(attr);
  277. bool ok_parse
  278. //Creates a place to hold the result of parse_rhs
  279. //called inside the following scope.
  280. ;
  281. {
  282. // Create a scope to cause the dbg variable below (within
  283. // the #if...#endif) to call it's DTOR before any
  284. // modifications are made to the attribute, attr_ passed
  285. // to parse_rhs (such as might be done in
  286. // transform::post when, for example,
  287. // ActualAttribute is a recursive variant).
  288. #if defined(BOOST_SPIRIT_X3_DEBUG)
  289. context_debug<Iterator, transform_attr>
  290. dbg(rule_name, first, last, attr_, ok_parse);
  291. #endif
  292. ok_parse = parse_rhs(rhs, first, last, context, attr_, attr_
  293. , mpl::bool_
  294. < ( RHS::has_action
  295. && !ExplicitAttrPropagation::value
  296. )
  297. >()
  298. );
  299. }
  300. if (ok_parse)
  301. {
  302. // do up-stream transformation, this integrates the results
  303. // back into the original attribute value, if appropriate
  304. transform::post(attr, std::forward<transform_attr>(attr_));
  305. }
  306. return ok_parse;
  307. }
  308. };
  309. }}}}
  310. #endif