lazy.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 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_LAZY_MARCH_27_2007_1002AM)
  7. #define BOOST_SPIRIT_LAZY_MARCH_27_2007_1002AM
  8. #if defined(_MSC_VER)
  9. #pragma once
  10. #endif
  11. #include <boost/spirit/home/qi/domain.hpp>
  12. #include <boost/spirit/home/qi/skip_over.hpp>
  13. #include <boost/spirit/home/qi/meta_compiler.hpp>
  14. #include <boost/spirit/home/qi/detail/attributes.hpp>
  15. #include <boost/spirit/home/support/unused.hpp>
  16. #include <boost/spirit/home/support/info.hpp>
  17. #include <boost/spirit/home/support/lazy.hpp>
  18. #include <boost/spirit/include/phoenix_core.hpp>
  19. #include <boost/fusion/include/at.hpp>
  20. #include <boost/utility/result_of.hpp>
  21. #include <boost/type_traits/remove_reference.hpp>
  22. #include <boost/mpl/not.hpp>
  23. namespace boost { namespace spirit
  24. {
  25. ///////////////////////////////////////////////////////////////////////////
  26. // Enablers
  27. ///////////////////////////////////////////////////////////////////////////
  28. template <typename Eval>
  29. struct use_terminal<qi::domain, phoenix::actor<Eval> > // enables phoenix actors
  30. : mpl::true_ {};
  31. // forward declaration
  32. template <typename Terminal, typename Actor, int Arity>
  33. struct lazy_terminal;
  34. }}
  35. namespace boost { namespace spirit { namespace qi
  36. {
  37. using spirit::lazy;
  38. typedef modify<qi::domain> qi_modify;
  39. namespace detail
  40. {
  41. template <typename Parser, typename Iterator, typename Context
  42. , typename Skipper, typename Attribute>
  43. bool lazy_parse_impl(Parser const& p
  44. , Iterator& first, Iterator const& last
  45. , Context& context, Skipper const& skipper
  46. , Attribute& attr, mpl::false_)
  47. {
  48. return p.parse(first, last, context, skipper, attr);
  49. }
  50. template <typename Parser, typename Iterator, typename Context
  51. , typename Skipper, typename Attribute>
  52. bool lazy_parse_impl(Parser const& p
  53. , Iterator& first, Iterator const& last
  54. , Context& context, Skipper const& skipper
  55. , Attribute& /*attr*/, mpl::true_)
  56. {
  57. // If DeducedAuto is false (semantic actions is present), the
  58. // component's attribute is unused.
  59. return p.parse(first, last, context, skipper, unused);
  60. }
  61. template <typename Parser, typename Iterator, typename Context
  62. , typename Skipper, typename Attribute>
  63. bool lazy_parse_impl_main(Parser const& p
  64. , Iterator& first, Iterator const& last
  65. , Context& context, Skipper const& skipper
  66. , Attribute& attr)
  67. {
  68. // If DeducedAuto is true (no semantic action), we pass the parser's
  69. // attribute on to the component.
  70. typedef typename traits::has_semantic_action<Parser>::type auto_rule;
  71. return lazy_parse_impl(p, first, last, context, skipper, attr, auto_rule());
  72. }
  73. }
  74. template <typename Function, typename Modifiers>
  75. struct lazy_parser : parser<lazy_parser<Function, Modifiers> >
  76. {
  77. template <typename Context, typename Iterator>
  78. struct attribute
  79. {
  80. typedef typename
  81. boost::result_of<qi_modify(tag::lazy_eval, Modifiers)>::type
  82. modifier;
  83. typedef typename
  84. remove_reference<
  85. typename boost::result_of<Function(unused_type, Context)>::type
  86. >::type
  87. expr_type;
  88. // If you got an error_invalid_expression error message here,
  89. // then the expression (expr_type) is not a valid spirit qi
  90. // expression.
  91. BOOST_SPIRIT_ASSERT_MATCH(qi::domain, expr_type);
  92. typedef typename
  93. result_of::compile<qi::domain, expr_type, modifier>::type
  94. parser_type;
  95. typedef typename
  96. traits::attribute_of<parser_type, Context, Iterator>::type
  97. type;
  98. };
  99. lazy_parser(Function const& function_, Modifiers const& modifiers_)
  100. : function(function_), modifiers(modifiers_) {}
  101. template <typename Iterator, typename Context
  102. , typename Skipper, typename Attribute>
  103. bool parse(Iterator& first, Iterator const& last
  104. , Context& context, Skipper const& skipper
  105. , Attribute& attr) const
  106. {
  107. return detail::lazy_parse_impl_main(
  108. compile<qi::domain>(function(unused, context)
  109. , qi_modify()(tag::lazy_eval(), modifiers))
  110. , first, last, context, skipper, attr);
  111. }
  112. template <typename Context>
  113. info what(Context& context) const
  114. {
  115. return info("lazy"
  116. , compile<qi::domain>(function(unused, context)
  117. , qi_modify()(tag::lazy_eval(), modifiers))
  118. .what(context)
  119. );
  120. }
  121. Function function;
  122. Modifiers modifiers;
  123. };
  124. template <typename Function, typename Subject, typename Modifiers>
  125. struct lazy_directive
  126. : unary_parser<lazy_directive<Function, Subject, Modifiers> >
  127. {
  128. typedef Subject subject_type;
  129. template <typename Context, typename Iterator>
  130. struct attribute
  131. {
  132. typedef typename
  133. boost::result_of<qi_modify(tag::lazy_eval, Modifiers)>::type
  134. modifier;
  135. typedef typename
  136. remove_reference<
  137. typename boost::result_of<Function(unused_type, Context)>::type
  138. >::type
  139. directive_expr_type;
  140. typedef typename
  141. proto::result_of::make_expr<
  142. proto::tag::subscript
  143. , directive_expr_type
  144. , Subject
  145. >::type
  146. expr_type;
  147. // If you got an error_invalid_expression error message here,
  148. // then the expression (expr_type) is not a valid spirit qi
  149. // expression.
  150. BOOST_SPIRIT_ASSERT_MATCH(qi::domain, expr_type);
  151. typedef typename
  152. result_of::compile<qi::domain, expr_type, modifier>::type
  153. parser_type;
  154. typedef typename
  155. traits::attribute_of<parser_type, Context, Iterator>::type
  156. type;
  157. };
  158. lazy_directive(
  159. Function const& function_
  160. , Subject const& subject_
  161. , Modifiers const& modifiers_)
  162. : function(function_), subject(subject_), modifiers(modifiers_) {}
  163. template <typename Iterator, typename Context
  164. , typename Skipper, typename Attribute>
  165. bool parse(Iterator& first, Iterator const& last
  166. , Context& context, Skipper const& skipper
  167. , Attribute& attr) const
  168. {
  169. return detail::lazy_parse_impl_main(compile<qi::domain>(
  170. proto::make_expr<proto::tag::subscript>(
  171. function(unused, context)
  172. , subject)
  173. , qi_modify()(tag::lazy_eval(), modifiers))
  174. , first, last, context, skipper, attr);
  175. }
  176. template <typename Context>
  177. info what(Context& context) const
  178. {
  179. return info("lazy-directive"
  180. , compile<qi::domain>(
  181. proto::make_expr<proto::tag::subscript>(
  182. function(unused, context)
  183. , subject
  184. ), qi_modify()(tag::lazy_eval(), modifiers))
  185. .what(context)
  186. );
  187. }
  188. Function function;
  189. Subject subject;
  190. Modifiers modifiers;
  191. };
  192. ///////////////////////////////////////////////////////////////////////////
  193. // Parser generators: make_xxx function (objects)
  194. ///////////////////////////////////////////////////////////////////////////
  195. template <typename Eval, typename Modifiers>
  196. struct make_primitive<phoenix::actor<Eval>, Modifiers>
  197. {
  198. typedef lazy_parser<phoenix::actor<Eval>, Modifiers> result_type;
  199. result_type operator()(phoenix::actor<Eval> const& f
  200. , Modifiers const& modifiers) const
  201. {
  202. return result_type(f, modifiers);
  203. }
  204. };
  205. template <typename Terminal, typename Actor, int Arity, typename Modifiers>
  206. struct make_primitive<lazy_terminal<Terminal, Actor, Arity>, Modifiers>
  207. {
  208. typedef lazy_parser<Actor, Modifiers> result_type;
  209. result_type operator()(
  210. lazy_terminal<Terminal, Actor, Arity> const& lt
  211. , Modifiers const& modifiers) const
  212. {
  213. return result_type(lt.actor, modifiers);
  214. }
  215. };
  216. template <typename Terminal, typename Actor, int Arity, typename Subject, typename Modifiers>
  217. struct make_directive<lazy_terminal<Terminal, Actor, Arity>, Subject, Modifiers>
  218. {
  219. typedef lazy_directive<Actor, Subject, Modifiers> result_type;
  220. result_type operator()(
  221. lazy_terminal<Terminal, Actor, Arity> const& lt
  222. , Subject const& subject, Modifiers const& modifiers) const
  223. {
  224. return result_type(lt.actor, subject, modifiers);
  225. }
  226. };
  227. }}}
  228. namespace boost { namespace spirit { namespace traits
  229. {
  230. ///////////////////////////////////////////////////////////////////////////
  231. template <typename Actor, typename Modifiers, typename Attribute
  232. , typename Context, typename Iterator>
  233. struct handles_container<
  234. qi::lazy_parser<Actor, Modifiers>, Attribute, Context, Iterator>
  235. : handles_container<
  236. typename qi::lazy_parser<Actor, Modifiers>::template
  237. attribute<Context, Iterator>::parser_type
  238. , Attribute, Context, Iterator>
  239. {};
  240. template <typename Subject, typename Actor, typename Modifiers
  241. , typename Attribute, typename Context, typename Iterator>
  242. struct handles_container<
  243. qi::lazy_directive<Actor, Subject, Modifiers>, Attribute
  244. , Context, Iterator>
  245. : handles_container<
  246. typename qi::lazy_directive<Actor, Subject, Modifiers>::template
  247. attribute<Context, Iterator>::parser_type
  248. , Attribute, Context, Iterator>
  249. {};
  250. }}}
  251. #endif