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