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