lazy.hpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. // Copyright (c) 2001-2011 Hartmut Kaiser
  2. // Copyright (c) 2001-2011 Joel de Guzman
  3. //
  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. #if !defined(BOOST_SPIRIT_KARMA_LAZY_MARCH_27_2007_1231PM)
  7. #define BOOST_SPIRIT_KARMA_LAZY_MARCH_27_2007_1231PM
  8. #if defined(_MSC_VER)
  9. #pragma once
  10. #endif
  11. #include <boost/spirit/home/karma/domain.hpp>
  12. #include <boost/spirit/home/karma/delimit_out.hpp>
  13. #include <boost/spirit/home/karma/meta_compiler.hpp>
  14. #include <boost/spirit/home/karma/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<karma::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 karma
  36. {
  37. using spirit::lazy;
  38. typedef modify<karma::domain> karma_modify;
  39. namespace detail
  40. {
  41. template <typename Generator, typename OutputIterator, typename Context
  42. , typename Delimiter, typename Attribute>
  43. bool lazy_generate_impl(Generator const& g, OutputIterator& sink
  44. , Context& context, Delimiter const& delim
  45. , Attribute const& attr, mpl::false_)
  46. {
  47. return g.generate(sink, context, delim, attr);
  48. }
  49. template <typename Generator, typename OutputIterator, typename Context
  50. , typename Delimiter, typename Attribute>
  51. bool lazy_generate_impl(Generator const& g, OutputIterator& sink
  52. , Context& context, Delimiter const& delim
  53. , Attribute const& /* attr */, mpl::true_)
  54. {
  55. // If DeducedAuto is false (semantic actions is present), the
  56. // component's attribute is unused.
  57. return g.generate(sink, context, delim, unused);
  58. }
  59. template <typename Generator, typename OutputIterator, typename Context
  60. , typename Delimiter, typename Attribute>
  61. bool lazy_generate_impl_main(Generator const& g, OutputIterator& sink
  62. , Context& context, Delimiter const& delim, Attribute const& attr)
  63. {
  64. // If DeducedAuto is true (no semantic action), we pass the parser's
  65. // attribute on to the component.
  66. typedef typename traits::has_semantic_action<Generator>::type auto_rule;
  67. return lazy_generate_impl(g, sink, context, delim, attr, auto_rule());
  68. }
  69. }
  70. template <typename Function, typename Modifiers>
  71. struct lazy_generator : generator<lazy_generator<Function, Modifiers> >
  72. {
  73. typedef mpl::int_<generator_properties::all_properties> properties;
  74. template <typename Context, typename Iterator>
  75. struct attribute
  76. {
  77. typedef typename
  78. boost::result_of<karma_modify(tag::lazy_eval, Modifiers)>::type
  79. modifier;
  80. typedef typename
  81. remove_reference<
  82. typename boost::result_of<Function(unused_type, Context)>::type
  83. >::type
  84. expr_type;
  85. // If you got an error_invalid_expression error message here,
  86. // then the expression (expr_type) is not a valid spirit karma
  87. // expression.
  88. BOOST_SPIRIT_ASSERT_MATCH(karma::domain, expr_type);
  89. typedef typename
  90. result_of::compile<karma::domain, expr_type, modifier>::type
  91. generator_type;
  92. typedef typename
  93. traits::attribute_of<generator_type, Context, Iterator>::type
  94. type;
  95. };
  96. lazy_generator(Function const& func, Modifiers const& modifiers)
  97. : func(func), modifiers(modifiers) {}
  98. template <
  99. typename OutputIterator, typename Context,
  100. typename Delimiter, typename Attribute
  101. >
  102. bool generate(OutputIterator& sink, Context& context,
  103. Delimiter const& d, Attribute const& attr) const
  104. {
  105. return detail::lazy_generate_impl_main(
  106. compile<karma::domain>(func(unused, context)
  107. , karma_modify()(tag::lazy_eval(), modifiers))
  108. , sink, context, d, attr);
  109. }
  110. template <typename Context>
  111. info what(Context& context) const
  112. {
  113. return info("lazy"
  114. , compile<karma::domain>(func(unused, context)
  115. , karma_modify()(tag::lazy_eval(), modifiers))
  116. .what(context)
  117. );
  118. }
  119. Function func;
  120. Modifiers modifiers;
  121. // silence MSVC warning C4512: assignment operator could not be generated
  122. BOOST_DELETED_FUNCTION(lazy_generator& operator= (lazy_generator const&))
  123. };
  124. ///////////////////////////////////////////////////////////////////////////
  125. template <typename Function, typename Subject, typename Modifiers>
  126. struct lazy_directive
  127. : unary_generator<lazy_directive<Function, Subject, Modifiers> >
  128. {
  129. typedef mpl::int_<generator_properties::all_properties> properties;
  130. typedef Subject subject_type;
  131. template <typename Context, typename Iterator>
  132. struct attribute
  133. {
  134. typedef typename
  135. boost::result_of<karma_modify(tag::lazy_eval, Modifiers)>::type
  136. modifier;
  137. typedef typename
  138. remove_reference<
  139. typename boost::result_of<Function(unused_type, Context)>::type
  140. >::type
  141. directive_expr_type;
  142. typedef typename
  143. proto::result_of::make_expr<
  144. proto::tag::subscript
  145. , directive_expr_type
  146. , Subject
  147. >::type
  148. expr_type;
  149. // If you got an error_invalid_expression error message here,
  150. // then the expression (expr_type) is not a valid spirit karma
  151. // expression.
  152. BOOST_SPIRIT_ASSERT_MATCH(karma::domain, expr_type);
  153. typedef typename
  154. result_of::compile<karma::domain, expr_type, modifier>::type
  155. generator_type;
  156. typedef typename
  157. traits::attribute_of<generator_type, Context, Iterator>::type
  158. type;
  159. };
  160. lazy_directive(Function const& function, Subject const& subject
  161. , Modifiers const& modifiers)
  162. : function(function), subject(subject), modifiers(modifiers) {}
  163. template <typename OutputIterator, typename Context, typename Delimiter
  164. , typename Attribute>
  165. bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
  166. , Attribute const& attr) const
  167. {
  168. return detail::lazy_generate_impl_main(compile<karma::domain>(
  169. proto::make_expr<proto::tag::subscript>(
  170. function(unused, ctx), subject)
  171. , karma_modify()(tag::lazy_eval(), modifiers))
  172. , sink, ctx, d, attr);
  173. }
  174. template <typename Context>
  175. info what(Context& ctx) const
  176. {
  177. return info("lazy-directive"
  178. , compile<karma::domain>(
  179. proto::make_expr<proto::tag::subscript>(
  180. function(unused, ctx), subject)
  181. , karma_modify()(tag::lazy_eval(), modifiers))
  182. .what(ctx)
  183. );
  184. }
  185. Function function;
  186. Subject subject;
  187. Modifiers modifiers;
  188. };
  189. ///////////////////////////////////////////////////////////////////////////
  190. // Generator generators: make_xxx function (objects)
  191. ///////////////////////////////////////////////////////////////////////////
  192. template <typename Eval, typename Modifiers>
  193. struct make_primitive<phoenix::actor<Eval>, Modifiers>
  194. {
  195. typedef lazy_generator<phoenix::actor<Eval>, Modifiers> result_type;
  196. result_type operator()(phoenix::actor<Eval> const& f
  197. , Modifiers const& modifiers) const
  198. {
  199. return result_type(f, modifiers);
  200. }
  201. };
  202. template <typename Terminal, typename Actor, int Arity, typename Modifiers>
  203. struct make_primitive<lazy_terminal<Terminal, Actor, Arity>, Modifiers>
  204. {
  205. typedef lazy_generator<Actor, Modifiers> result_type;
  206. result_type operator()(
  207. lazy_terminal<Terminal, Actor, Arity> const& lt
  208. , Modifiers const& modifiers) const
  209. {
  210. return result_type(lt.actor, modifiers);
  211. }
  212. };
  213. template <
  214. typename Terminal, typename Actor, int Arity, typename Subject
  215. , typename Modifiers>
  216. struct make_directive<lazy_terminal<Terminal, Actor, Arity>
  217. , 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. #endif