rule.hpp 12 KB

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