1 /*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
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 ==============================================================================*/
7 #if !defined(BOOST_SPIRIT_LAZY_MARCH_27_2007_1002AM)
8 #define BOOST_SPIRIT_LAZY_MARCH_27_2007_1002AM
14 #include <boost/spirit/home/qi/domain.hpp>
15 #include <boost/spirit/home/qi/skip_over.hpp>
16 #include <boost/spirit/home/qi/meta_compiler.hpp>
17 #include <boost/spirit/home/qi/detail/attributes.hpp>
18 #include <boost/spirit/home/support/unused.hpp>
19 #include <boost/spirit/home/support/info.hpp>
20 #include <boost/spirit/home/support/lazy.hpp>
21 #include <boost/spirit/include/phoenix_core.hpp>
22 #include <boost/fusion/include/at.hpp>
23 #include <boost/utility/result_of.hpp>
24 #include <boost/type_traits/remove_reference.hpp>
25 #include <boost/mpl/not.hpp>
27 namespace boost { namespace spirit
29 ///////////////////////////////////////////////////////////////////////////
31 ///////////////////////////////////////////////////////////////////////////
32 template <typename Eval>
33 struct use_terminal<qi::domain, phoenix::actor<Eval> > // enables phoenix actors
36 // forward declaration
37 template <typename Terminal, typename Actor, int Arity>
41 namespace boost { namespace spirit { namespace qi
44 typedef modify<qi::domain> qi_modify;
48 template <typename Parser, typename Iterator, typename Context
49 , typename Skipper, typename Attribute>
50 bool lazy_parse_impl(Parser const& p
51 , Iterator& first, Iterator const& last
52 , Context& context, Skipper const& skipper
53 , Attribute& attr, mpl::false_)
55 return p.parse(first, last, context, skipper, attr);
58 template <typename Parser, typename Iterator, typename Context
59 , typename Skipper, typename Attribute>
60 bool lazy_parse_impl(Parser const& p
61 , Iterator& first, Iterator const& last
62 , Context& context, Skipper const& skipper
63 , Attribute& /*attr*/, mpl::true_)
65 // If DeducedAuto is false (semantic actions is present), the
66 // component's attribute is unused.
67 return p.parse(first, last, context, skipper, unused);
70 template <typename Parser, typename Iterator, typename Context
71 , typename Skipper, typename Attribute>
72 bool lazy_parse_impl_main(Parser const& p
73 , Iterator& first, Iterator const& last
74 , Context& context, Skipper const& skipper
77 // If DeducedAuto is true (no semantic action), we pass the parser's
78 // attribute on to the component.
79 typedef typename traits::has_semantic_action<Parser>::type auto_rule;
80 return lazy_parse_impl(p, first, last, context, skipper, attr, auto_rule());
84 template <typename Function, typename Modifiers>
85 struct lazy_parser : parser<lazy_parser<Function, Modifiers> >
87 template <typename Context, typename Iterator>
91 boost::result_of<qi_modify(tag::lazy_eval, Modifiers)>::type
96 typename boost::result_of<Function(unused_type, Context)>::type
100 // If you got an error_invalid_expression error message here,
101 // then the expression (expr_type) is not a valid spirit qi
103 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, expr_type);
106 result_of::compile<qi::domain, expr_type, modifier>::type
110 traits::attribute_of<parser_type, Context, Iterator>::type
114 lazy_parser(Function const& function_, Modifiers const& modifiers_)
115 : function(function_), modifiers(modifiers_) {}
117 template <typename Iterator, typename Context
118 , typename Skipper, typename Attribute>
119 bool parse(Iterator& first, Iterator const& last
120 , Context& context, Skipper const& skipper
121 , Attribute& attr) const
123 return detail::lazy_parse_impl_main(
124 compile<qi::domain>(function(unused, context)
125 , qi_modify()(tag::lazy_eval(), modifiers))
126 , first, last, context, skipper, attr);
129 template <typename Context>
130 info what(Context& context) const
133 , compile<qi::domain>(function(unused, context)
134 , qi_modify()(tag::lazy_eval(), modifiers))
144 template <typename Function, typename Subject, typename Modifiers>
145 struct lazy_directive
146 : unary_parser<lazy_directive<Function, Subject, Modifiers> >
148 typedef Subject subject_type;
150 template <typename Context, typename Iterator>
154 boost::result_of<qi_modify(tag::lazy_eval, Modifiers)>::type
159 typename boost::result_of<Function(unused_type, Context)>::type
164 proto::result_of::make_expr<
165 proto::tag::subscript
166 , directive_expr_type
171 // If you got an error_invalid_expression error message here,
172 // then the expression (expr_type) is not a valid spirit qi
174 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, expr_type);
177 result_of::compile<qi::domain, expr_type, modifier>::type
181 traits::attribute_of<parser_type, Context, Iterator>::type
186 Function const& function_
187 , Subject const& subject_
188 , Modifiers const& modifiers_)
189 : function(function_), subject(subject_), modifiers(modifiers_) {}
191 template <typename Iterator, typename Context
192 , typename Skipper, typename Attribute>
193 bool parse(Iterator& first, Iterator const& last
194 , Context& context, Skipper const& skipper
195 , Attribute& attr) const
197 return detail::lazy_parse_impl_main(compile<qi::domain>(
198 proto::make_expr<proto::tag::subscript>(
199 function(unused, context)
201 , qi_modify()(tag::lazy_eval(), modifiers))
202 , first, last, context, skipper, attr);
205 template <typename Context>
206 info what(Context& context) const
208 return info("lazy-directive"
209 , compile<qi::domain>(
210 proto::make_expr<proto::tag::subscript>(
211 function(unused, context)
213 ), qi_modify()(tag::lazy_eval(), modifiers))
223 ///////////////////////////////////////////////////////////////////////////
224 // Parser generators: make_xxx function (objects)
225 ///////////////////////////////////////////////////////////////////////////
226 template <typename Eval, typename Modifiers>
227 struct make_primitive<phoenix::actor<Eval>, Modifiers>
229 typedef lazy_parser<phoenix::actor<Eval>, Modifiers> result_type;
230 result_type operator()(phoenix::actor<Eval> const& f
231 , Modifiers const& modifiers) const
233 return result_type(f, modifiers);
237 template <typename Terminal, typename Actor, int Arity, typename Modifiers>
238 struct make_primitive<lazy_terminal<Terminal, Actor, Arity>, Modifiers>
240 typedef lazy_parser<Actor, Modifiers> result_type;
241 result_type operator()(
242 lazy_terminal<Terminal, Actor, Arity> const& lt
243 , Modifiers const& modifiers) const
245 return result_type(lt.actor, modifiers);
249 template <typename Terminal, typename Actor, int Arity, typename Subject, typename Modifiers>
250 struct make_directive<lazy_terminal<Terminal, Actor, Arity>, Subject, Modifiers>
252 typedef lazy_directive<Actor, Subject, Modifiers> result_type;
253 result_type operator()(
254 lazy_terminal<Terminal, Actor, Arity> const& lt
255 , Subject const& subject, Modifiers const& modifiers) const
257 return result_type(lt.actor, subject, modifiers);
262 namespace boost { namespace spirit { namespace traits
264 ///////////////////////////////////////////////////////////////////////////
265 template <typename Actor, typename Modifiers, typename Attribute
266 , typename Context, typename Iterator>
267 struct handles_container<
268 qi::lazy_parser<Actor, Modifiers>, Attribute, Context, Iterator>
270 typename qi::lazy_parser<Actor, Modifiers>::template
271 attribute<Context, Iterator>::parser_type
272 , Attribute, Context, Iterator>
275 template <typename Subject, typename Actor, typename Modifiers
276 , typename Attribute, typename Context, typename Iterator>
277 struct handles_container<
278 qi::lazy_directive<Actor, Subject, Modifiers>, Attribute
281 typename qi::lazy_directive<Actor, Subject, Modifiers>::template
282 attribute<Context, Iterator>::parser_type
283 , Attribute, Context, Iterator>