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