9
3

rule.hpp 12 KB

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