lazy.hpp 10 KB

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