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/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> 26 27 namespace boost { namespace spirit 28 { 29 /////////////////////////////////////////////////////////////////////////// 30 // Enablers 31 /////////////////////////////////////////////////////////////////////////// 32 template <typename Eval> 33 struct use_terminal<qi::domain, phoenix::actor<Eval> > // enables phoenix actors 34 : mpl::true_ {}; 35 36 // forward declaration 37 template <typename Terminal, typename Actor, int Arity> 38 struct lazy_terminal; 39 }} 40 41 namespace boost { namespace spirit { namespace qi 42 { 43 using spirit::lazy; 44 typedef modify<qi::domain> qi_modify; 45 46 namespace detail 47 { 48 template <typename Parser, typename Iterator, typename Context 49 , typename Skipper, typename Attribute> lazy_parse_impl(Parser const & p,Iterator & first,Iterator const & last,Context & context,Skipper const & skipper,Attribute & attr,mpl::false_)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_) 54 { 55 return p.parse(first, last, context, skipper, attr); 56 } 57 58 template <typename Parser, typename Iterator, typename Context 59 , typename Skipper, typename Attribute> lazy_parse_impl(Parser const & p,Iterator & first,Iterator const & last,Context & context,Skipper const & skipper,Attribute &,mpl::true_)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_) 64 { 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); 68 } 69 70 template <typename Parser, typename Iterator, typename Context 71 , typename Skipper, typename Attribute> lazy_parse_impl_main(Parser const & p,Iterator & first,Iterator const & last,Context & context,Skipper const & skipper,Attribute & attr)72 bool lazy_parse_impl_main(Parser const& p 73 , Iterator& first, Iterator const& last 74 , Context& context, Skipper const& skipper 75 , Attribute& attr) 76 { 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()); 81 } 82 } 83 84 template <typename Function, typename Modifiers> 85 struct lazy_parser : parser<lazy_parser<Function, Modifiers> > 86 { 87 template <typename Context, typename Iterator> 88 struct attribute 89 { 90 typedef typename 91 boost::result_of<qi_modify(tag::lazy_eval, Modifiers)>::type 92 modifier; 93 94 typedef typename 95 remove_reference< 96 typename boost::result_of<Function(unused_type, Context)>::type 97 >::type 98 expr_type; 99 100 // If you got an error_invalid_expression error message here, 101 // then the expression (expr_type) is not a valid spirit qi 102 // expression. 103 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, expr_type); 104 105 typedef typename 106 result_of::compile<qi::domain, expr_type, modifier>::type 107 parser_type; 108 109 typedef typename 110 traits::attribute_of<parser_type, Context, Iterator>::type 111 type; 112 }; 113 lazy_parserboost::spirit::qi::lazy_parser114 lazy_parser(Function const& function_, Modifiers const& modifiers_) 115 : function(function_), modifiers(modifiers_) {} 116 117 template <typename Iterator, typename Context 118 , typename Skipper, typename Attribute> parseboost::spirit::qi::lazy_parser119 bool parse(Iterator& first, Iterator const& last 120 , Context& context, Skipper const& skipper 121 , Attribute& attr) const 122 { 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); 127 } 128 129 template <typename Context> whatboost::spirit::qi::lazy_parser130 info what(Context& context) const 131 { 132 return info("lazy" 133 , compile<qi::domain>(function(unused, context) 134 , qi_modify()(tag::lazy_eval(), modifiers)) 135 .what(context) 136 ); 137 } 138 139 Function function; 140 Modifiers modifiers; 141 }; 142 143 144 template <typename Function, typename Subject, typename Modifiers> 145 struct lazy_directive 146 : unary_parser<lazy_directive<Function, Subject, Modifiers> > 147 { 148 typedef Subject subject_type; 149 150 template <typename Context, typename Iterator> 151 struct attribute 152 { 153 typedef typename 154 boost::result_of<qi_modify(tag::lazy_eval, Modifiers)>::type 155 modifier; 156 157 typedef typename 158 remove_reference< 159 typename boost::result_of<Function(unused_type, Context)>::type 160 >::type 161 directive_expr_type; 162 163 typedef typename 164 proto::result_of::make_expr< 165 proto::tag::subscript 166 , directive_expr_type 167 , Subject 168 >::type 169 expr_type; 170 171 // If you got an error_invalid_expression error message here, 172 // then the expression (expr_type) is not a valid spirit qi 173 // expression. 174 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, expr_type); 175 176 typedef typename 177 result_of::compile<qi::domain, expr_type, modifier>::type 178 parser_type; 179 180 typedef typename 181 traits::attribute_of<parser_type, Context, Iterator>::type 182 type; 183 }; 184 lazy_directiveboost::spirit::qi::lazy_directive185 lazy_directive( 186 Function const& function_ 187 , Subject const& subject_ 188 , Modifiers const& modifiers_) 189 : function(function_), subject(subject_), modifiers(modifiers_) {} 190 191 template <typename Iterator, typename Context 192 , typename Skipper, typename Attribute> parseboost::spirit::qi::lazy_directive193 bool parse(Iterator& first, Iterator const& last 194 , Context& context, Skipper const& skipper 195 , Attribute& attr) const 196 { 197 return detail::lazy_parse_impl_main(compile<qi::domain>( 198 proto::make_expr<proto::tag::subscript>( 199 function(unused, context) 200 , subject) 201 , qi_modify()(tag::lazy_eval(), modifiers)) 202 , first, last, context, skipper, attr); 203 } 204 205 template <typename Context> whatboost::spirit::qi::lazy_directive206 info what(Context& context) const 207 { 208 return info("lazy-directive" 209 , compile<qi::domain>( 210 proto::make_expr<proto::tag::subscript>( 211 function(unused, context) 212 , subject 213 ), qi_modify()(tag::lazy_eval(), modifiers)) 214 .what(context) 215 ); 216 } 217 218 Function function; 219 Subject subject; 220 Modifiers modifiers; 221 }; 222 223 /////////////////////////////////////////////////////////////////////////// 224 // Parser generators: make_xxx function (objects) 225 /////////////////////////////////////////////////////////////////////////// 226 template <typename Eval, typename Modifiers> 227 struct make_primitive<phoenix::actor<Eval>, Modifiers> 228 { 229 typedef lazy_parser<phoenix::actor<Eval>, Modifiers> result_type; operator ()boost::spirit::qi::make_primitive230 result_type operator()(phoenix::actor<Eval> const& f 231 , Modifiers const& modifiers) const 232 { 233 return result_type(f, modifiers); 234 } 235 }; 236 237 template <typename Terminal, typename Actor, int Arity, typename Modifiers> 238 struct make_primitive<lazy_terminal<Terminal, Actor, Arity>, Modifiers> 239 { 240 typedef lazy_parser<Actor, Modifiers> result_type; operator ()boost::spirit::qi::make_primitive241 result_type operator()( 242 lazy_terminal<Terminal, Actor, Arity> const& lt 243 , Modifiers const& modifiers) const 244 { 245 return result_type(lt.actor, modifiers); 246 } 247 }; 248 249 template <typename Terminal, typename Actor, int Arity, typename Subject, typename Modifiers> 250 struct make_directive<lazy_terminal<Terminal, Actor, Arity>, Subject, Modifiers> 251 { 252 typedef lazy_directive<Actor, Subject, Modifiers> result_type; operator ()boost::spirit::qi::make_directive253 result_type operator()( 254 lazy_terminal<Terminal, Actor, Arity> const& lt 255 , Subject const& subject, Modifiers const& modifiers) const 256 { 257 return result_type(lt.actor, subject, modifiers); 258 } 259 }; 260 }}} 261 262 namespace boost { namespace spirit { namespace traits 263 { 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> 269 : handles_container< 270 typename qi::lazy_parser<Actor, Modifiers>::template 271 attribute<Context, Iterator>::parser_type 272 , Attribute, Context, Iterator> 273 {}; 274 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 279 , Context, Iterator> 280 : handles_container< 281 typename qi::lazy_directive<Actor, Subject, Modifiers>::template 282 attribute<Context, Iterator>::parser_type 283 , Attribute, Context, Iterator> 284 {}; 285 }}} 286 287 #endif 288