annotate DEPENDENCIES/generic/include/boost/spirit/home/qi/nonterminal/rule.hpp @ 65:d8563d4879f3

Merge
author Chris Cannam
date Mon, 22 Sep 2014 11:47:11 +0100
parents 2665513ce2d3
children c530137014c0
rev   line source
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_RULE_FEBRUARY_12_2007_1020AM)
Chris@16 8 #define BOOST_SPIRIT_RULE_FEBRUARY_12_2007_1020AM
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/assert.hpp>
Chris@16 15 #include <boost/config.hpp>
Chris@16 16 #include <boost/function.hpp>
Chris@16 17 #include <boost/mpl/vector.hpp>
Chris@16 18 #include <boost/type_traits/add_reference.hpp>
Chris@16 19 #include <boost/type_traits/is_same.hpp>
Chris@16 20
Chris@16 21 #include <boost/fusion/include/vector.hpp>
Chris@16 22 #include <boost/fusion/include/size.hpp>
Chris@16 23 #include <boost/fusion/include/make_vector.hpp>
Chris@16 24 #include <boost/fusion/include/cons.hpp>
Chris@16 25 #include <boost/fusion/include/as_list.hpp>
Chris@16 26 #include <boost/fusion/include/as_vector.hpp>
Chris@16 27
Chris@16 28 #include <boost/spirit/home/support/unused.hpp>
Chris@16 29 #include <boost/spirit/home/support/argument.hpp>
Chris@16 30 #include <boost/spirit/home/support/context.hpp>
Chris@16 31 #include <boost/spirit/home/support/info.hpp>
Chris@16 32 #include <boost/spirit/home/qi/detail/attributes.hpp>
Chris@16 33 #include <boost/spirit/home/support/nonterminal/extract_param.hpp>
Chris@16 34 #include <boost/spirit/home/support/nonterminal/locals.hpp>
Chris@16 35 #include <boost/spirit/home/qi/reference.hpp>
Chris@16 36 #include <boost/spirit/home/qi/nonterminal/detail/parameterized.hpp>
Chris@16 37 #include <boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp>
Chris@16 38 #include <boost/spirit/home/qi/nonterminal/nonterminal_fwd.hpp>
Chris@16 39 #include <boost/spirit/home/qi/skip_over.hpp>
Chris@16 40
Chris@16 41 #if defined(BOOST_MSVC)
Chris@16 42 # pragma warning(push)
Chris@16 43 # pragma warning(disable: 4355) // 'this' : used in base member initializer list warning
Chris@16 44 #endif
Chris@16 45
Chris@16 46 namespace boost { namespace spirit { namespace qi
Chris@16 47 {
Chris@16 48 BOOST_PP_REPEAT(SPIRIT_ATTRIBUTES_LIMIT, SPIRIT_USING_ATTRIBUTE, _)
Chris@16 49
Chris@16 50 using spirit::_pass_type;
Chris@16 51 using spirit::_val_type;
Chris@16 52 using spirit::_a_type;
Chris@16 53 using spirit::_b_type;
Chris@16 54 using spirit::_c_type;
Chris@16 55 using spirit::_d_type;
Chris@16 56 using spirit::_e_type;
Chris@16 57 using spirit::_f_type;
Chris@16 58 using spirit::_g_type;
Chris@16 59 using spirit::_h_type;
Chris@16 60 using spirit::_i_type;
Chris@16 61 using spirit::_j_type;
Chris@16 62
Chris@16 63 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
Chris@16 64
Chris@16 65 using spirit::_pass;
Chris@16 66 using spirit::_val;
Chris@16 67 using spirit::_a;
Chris@16 68 using spirit::_b;
Chris@16 69 using spirit::_c;
Chris@16 70 using spirit::_d;
Chris@16 71 using spirit::_e;
Chris@16 72 using spirit::_f;
Chris@16 73 using spirit::_g;
Chris@16 74 using spirit::_h;
Chris@16 75 using spirit::_i;
Chris@16 76 using spirit::_j;
Chris@16 77
Chris@16 78 #endif
Chris@16 79
Chris@16 80 using spirit::info;
Chris@16 81 using spirit::locals;
Chris@16 82
Chris@16 83 template <
Chris@16 84 typename Iterator, typename T1, typename T2, typename T3
Chris@16 85 , typename T4>
Chris@16 86 struct rule
Chris@16 87 : proto::extends<
Chris@16 88 typename proto::terminal<
Chris@16 89 reference<rule<Iterator, T1, T2, T3, T4> const>
Chris@16 90 >::type
Chris@16 91 , rule<Iterator, T1, T2, T3, T4>
Chris@16 92 >
Chris@16 93 , parser<rule<Iterator, T1, T2, T3, T4> >
Chris@16 94 {
Chris@16 95 typedef Iterator iterator_type;
Chris@16 96 typedef rule<Iterator, T1, T2, T3, T4> this_type;
Chris@16 97 typedef reference<this_type const> reference_;
Chris@16 98 typedef typename proto::terminal<reference_>::type terminal;
Chris@16 99 typedef proto::extends<terminal, this_type> base_type;
Chris@16 100 typedef mpl::vector<T1, T2, T3, T4> template_params;
Chris@16 101
Chris@16 102 // The rule's locals_type: a sequence of types to be used as local variables
Chris@16 103 typedef typename
Chris@16 104 spirit::detail::extract_locals<template_params>::type
Chris@16 105 locals_type;
Chris@16 106
Chris@16 107 // The rule's skip-parser type
Chris@16 108 typedef typename
Chris@16 109 spirit::detail::extract_component<
Chris@16 110 qi::domain, template_params>::type
Chris@16 111 skipper_type;
Chris@16 112
Chris@16 113 // The rule's signature
Chris@16 114 typedef typename
Chris@16 115 spirit::detail::extract_sig<template_params>::type
Chris@16 116 sig_type;
Chris@16 117
Chris@16 118 // The rule's encoding type
Chris@16 119 typedef typename
Chris@16 120 spirit::detail::extract_encoding<template_params>::type
Chris@16 121 encoding_type;
Chris@16 122
Chris@16 123 // This is the rule's attribute type
Chris@16 124 typedef typename
Chris@16 125 spirit::detail::attr_from_sig<sig_type>::type
Chris@16 126 attr_type;
Chris@16 127 typedef typename add_reference<attr_type>::type attr_reference_type;
Chris@16 128
Chris@16 129 // parameter_types is a sequence of types passed as parameters to the rule
Chris@16 130 typedef typename
Chris@16 131 spirit::detail::params_from_sig<sig_type>::type
Chris@16 132 parameter_types;
Chris@16 133
Chris@16 134 static size_t const params_size =
Chris@16 135 fusion::result_of::size<parameter_types>::type::value;
Chris@16 136
Chris@16 137 typedef context<
Chris@16 138 fusion::cons<attr_reference_type, parameter_types>
Chris@16 139 , locals_type>
Chris@16 140 context_type;
Chris@16 141
Chris@16 142 typedef function<
Chris@16 143 bool(Iterator& first, Iterator const& last
Chris@16 144 , context_type& context
Chris@16 145 , skipper_type const& skipper
Chris@16 146 )>
Chris@16 147 function_type;
Chris@16 148
Chris@16 149 typedef typename
Chris@16 150 mpl::if_<
Chris@16 151 is_same<encoding_type, unused_type>
Chris@16 152 , unused_type
Chris@16 153 , tag::char_code<tag::encoding, encoding_type>
Chris@16 154 >::type
Chris@16 155 encoding_modifier_type;
Chris@16 156
Chris@16 157 explicit rule(std::string const& name = "unnamed-rule")
Chris@16 158 : base_type(terminal::make(reference_(*this)))
Chris@16 159 , name_(name)
Chris@16 160 {
Chris@16 161 }
Chris@16 162
Chris@16 163 rule(rule const& rhs)
Chris@16 164 : base_type(terminal::make(reference_(*this)))
Chris@16 165 , name_(rhs.name_)
Chris@16 166 , f(rhs.f)
Chris@16 167 {
Chris@16 168 }
Chris@16 169
Chris@16 170 template <typename Auto, typename Expr>
Chris@16 171 static void define(rule& /*lhs*/, Expr const& /*expr*/, mpl::false_)
Chris@16 172 {
Chris@16 173 // Report invalid expression error as early as possible.
Chris@16 174 // If you got an error_invalid_expression error message here,
Chris@16 175 // then the expression (expr) is not a valid spirit qi expression.
Chris@16 176 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr);
Chris@16 177 }
Chris@16 178
Chris@16 179 template <typename Auto, typename Expr>
Chris@16 180 static void define(rule& lhs, Expr const& expr, mpl::true_)
Chris@16 181 {
Chris@16 182 lhs.f = detail::bind_parser<Auto>(
Chris@16 183 compile<qi::domain>(expr, encoding_modifier_type()));
Chris@16 184 }
Chris@16 185
Chris@16 186 template <typename Expr>
Chris@16 187 rule(Expr const& expr, std::string const& name = "unnamed-rule")
Chris@16 188 : base_type(terminal::make(reference_(*this)))
Chris@16 189 , name_(name)
Chris@16 190 {
Chris@16 191 define<mpl::false_>(*this, expr, traits::matches<qi::domain, Expr>());
Chris@16 192 }
Chris@16 193
Chris@16 194 rule& operator=(rule const& rhs)
Chris@16 195 {
Chris@16 196 // The following assertion fires when you try to initialize a rule
Chris@16 197 // from an uninitialized one. Did you mean to refer to the right
Chris@16 198 // hand side rule instead of assigning from it? In this case you
Chris@16 199 // should write lhs = rhs.alias();
Chris@16 200 BOOST_ASSERT(rhs.f && "Did you mean rhs.alias() instead of rhs?");
Chris@16 201
Chris@16 202 f = rhs.f;
Chris@16 203 name_ = rhs.name_;
Chris@16 204 return *this;
Chris@16 205 }
Chris@16 206
Chris@16 207 std::string const& name() const
Chris@16 208 {
Chris@16 209 return name_;
Chris@16 210 }
Chris@16 211
Chris@16 212 void name(std::string const& str)
Chris@16 213 {
Chris@16 214 name_ = str;
Chris@16 215 }
Chris@16 216
Chris@16 217 template <typename Expr>
Chris@16 218 rule& operator=(Expr const& expr)
Chris@16 219 {
Chris@16 220 define<mpl::false_>(*this, expr, traits::matches<qi::domain, Expr>());
Chris@16 221 return *this;
Chris@16 222 }
Chris@16 223
Chris@16 224 // VC7.1 has problems to resolve 'rule' without explicit template parameters
Chris@16 225 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1400)
Chris@16 226 // g++ 3.3 barfs if this is a member function :(
Chris@16 227 template <typename Expr>
Chris@16 228 friend rule& operator%=(rule& r, Expr const& expr)
Chris@16 229 {
Chris@16 230 define<mpl::true_>(r, expr, traits::matches<qi::domain, Expr>());
Chris@16 231 return r;
Chris@16 232 }
Chris@16 233
Chris@16 234 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
Chris@16 235 // non-const version needed to suppress proto's %= kicking in
Chris@16 236 template <typename Expr>
Chris@16 237 friend rule& operator%=(rule& r, Expr& expr)
Chris@16 238 {
Chris@16 239 return r %= static_cast<Expr const&>(expr);
Chris@16 240 }
Chris@16 241 #else
Chris@16 242 // for rvalue references
Chris@16 243 template <typename Expr>
Chris@16 244 friend rule& operator%=(rule& r, Expr&& expr)
Chris@16 245 {
Chris@16 246 define<mpl::true_>(r, expr, traits::matches<qi::domain, Expr>());
Chris@16 247 return r;
Chris@16 248 }
Chris@16 249 #endif
Chris@16 250
Chris@16 251 #else
Chris@16 252 // both friend functions have to be defined out of class as VC7.1
Chris@16 253 // will complain otherwise
Chris@16 254 template <typename OutputIterator_, typename T1_, typename T2_
Chris@16 255 , typename T3_, typename T4_, typename Expr>
Chris@16 256 friend rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=(
Chris@16 257 rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr const& expr);
Chris@16 258
Chris@16 259 // non-const version needed to suppress proto's %= kicking in
Chris@16 260 template <typename OutputIterator_, typename T1_, typename T2_
Chris@16 261 , typename T3_, typename T4_, typename Expr>
Chris@16 262 friend rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=(
Chris@16 263 rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr& expr);
Chris@16 264 #endif
Chris@16 265
Chris@16 266 template <typename Context, typename Iterator_>
Chris@16 267 struct attribute
Chris@16 268 {
Chris@16 269 typedef attr_type type;
Chris@16 270 };
Chris@16 271
Chris@16 272 template <typename Context, typename Skipper, typename Attribute>
Chris@16 273 bool parse(Iterator& first, Iterator const& last
Chris@16 274 , Context& /*context*/, Skipper const& skipper
Chris@16 275 , Attribute& attr_param) const
Chris@16 276 {
Chris@16 277 if (f)
Chris@16 278 {
Chris@16 279 // do a preskip if this is an implied lexeme
Chris@16 280 if (is_same<skipper_type, unused_type>::value)
Chris@16 281 qi::skip_over(first, last, skipper);
Chris@16 282
Chris@16 283 typedef traits::make_attribute<attr_type, Attribute> make_attribute;
Chris@16 284
Chris@16 285 // do down-stream transformation, provides attribute for
Chris@16 286 // rhs parser
Chris@16 287 typedef traits::transform_attribute<
Chris@16 288 typename make_attribute::type, attr_type, domain>
Chris@16 289 transform;
Chris@16 290
Chris@16 291 typename make_attribute::type made_attr = make_attribute::call(attr_param);
Chris@16 292 typename transform::type attr_ = transform::pre(made_attr);
Chris@16 293
Chris@16 294 // If you are seeing a compilation error here, you are probably
Chris@16 295 // trying to use a rule or a grammar which has inherited
Chris@16 296 // attributes, without passing values for them.
Chris@16 297 context_type context(attr_);
Chris@16 298
Chris@16 299 // If you are seeing a compilation error here stating that the
Chris@16 300 // fourth parameter can't be converted to a required target type
Chris@16 301 // then you are probably trying to use a rule or a grammar with
Chris@16 302 // an incompatible skipper type.
Chris@16 303 if (f(first, last, context, skipper))
Chris@16 304 {
Chris@16 305 // do up-stream transformation, this integrates the results
Chris@16 306 // back into the original attribute value, if appropriate
Chris@16 307 traits::post_transform(attr_param, attr_);
Chris@16 308 return true;
Chris@16 309 }
Chris@16 310
Chris@16 311 // inform attribute transformation of failed rhs
Chris@16 312 traits::fail_transform(attr_param, attr_);
Chris@16 313 }
Chris@16 314 return false;
Chris@16 315 }
Chris@16 316
Chris@16 317 template <typename Context, typename Skipper
Chris@16 318 , typename Attribute, typename Params>
Chris@16 319 bool parse(Iterator& first, Iterator const& last
Chris@16 320 , Context& caller_context, Skipper const& skipper
Chris@16 321 , Attribute& attr_param, Params const& params) const
Chris@16 322 {
Chris@16 323 if (f)
Chris@16 324 {
Chris@16 325 // do a preskip if this is an implied lexeme
Chris@16 326 if (is_same<skipper_type, unused_type>::value)
Chris@16 327 qi::skip_over(first, last, skipper);
Chris@16 328
Chris@16 329 typedef traits::make_attribute<attr_type, Attribute> make_attribute;
Chris@16 330
Chris@16 331 // do down-stream transformation, provides attribute for
Chris@16 332 // rhs parser
Chris@16 333 typedef traits::transform_attribute<
Chris@16 334 typename make_attribute::type, attr_type, domain>
Chris@16 335 transform;
Chris@16 336
Chris@16 337 typename make_attribute::type made_attr = make_attribute::call(attr_param);
Chris@16 338 typename transform::type attr_ = transform::pre(made_attr);
Chris@16 339
Chris@16 340 // If you are seeing a compilation error here, you are probably
Chris@16 341 // trying to use a rule or a grammar which has inherited
Chris@16 342 // attributes, passing values of incompatible types for them.
Chris@16 343 context_type context(attr_, params, caller_context);
Chris@16 344
Chris@16 345 // If you are seeing a compilation error here stating that the
Chris@16 346 // fourth parameter can't be converted to a required target type
Chris@16 347 // then you are probably trying to use a rule or a grammar with
Chris@16 348 // an incompatible skipper type.
Chris@16 349 if (f(first, last, context, skipper))
Chris@16 350 {
Chris@16 351 // do up-stream transformation, this integrates the results
Chris@16 352 // back into the original attribute value, if appropriate
Chris@16 353 traits::post_transform(attr_param, attr_);
Chris@16 354 return true;
Chris@16 355 }
Chris@16 356
Chris@16 357 // inform attribute transformation of failed rhs
Chris@16 358 traits::fail_transform(attr_param, attr_);
Chris@16 359 }
Chris@16 360 return false;
Chris@16 361 }
Chris@16 362
Chris@16 363 template <typename Context>
Chris@16 364 info what(Context& /*context*/) const
Chris@16 365 {
Chris@16 366 return info(name_);
Chris@16 367 }
Chris@16 368
Chris@16 369 reference_ alias() const
Chris@16 370 {
Chris@16 371 return reference_(*this);
Chris@16 372 }
Chris@16 373
Chris@16 374 typename proto::terminal<this_type>::type copy() const
Chris@16 375 {
Chris@16 376 typename proto::terminal<this_type>::type result = {*this};
Chris@16 377 return result;
Chris@16 378 }
Chris@16 379
Chris@16 380 // bring in the operator() overloads
Chris@16 381 rule const& get_parameterized_subject() const { return *this; }
Chris@16 382 typedef rule parameterized_subject_type;
Chris@16 383 #include <boost/spirit/home/qi/nonterminal/detail/fcall.hpp>
Chris@16 384
Chris@16 385 std::string name_;
Chris@16 386 function_type f;
Chris@16 387 };
Chris@16 388
Chris@16 389 #if BOOST_WORKAROUND(BOOST_MSVC, < 1400)
Chris@16 390 template <typename OutputIterator_, typename T1_, typename T2_
Chris@16 391 , typename T3_, typename T4_, typename Expr>
Chris@16 392 rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=(
Chris@16 393 rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr const& expr)
Chris@16 394 {
Chris@16 395 // Report invalid expression error as early as possible.
Chris@16 396 // If you got an error_invalid_expression error message here,
Chris@16 397 // then the expression (expr) is not a valid spirit qi expression.
Chris@16 398 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr);
Chris@16 399
Chris@16 400 typedef typename
Chris@16 401 rule<OutputIterator_, T1_, T2_, T3_, T4_>::encoding_modifier_type
Chris@16 402 encoding_modifier_type;
Chris@16 403
Chris@16 404 r.f = detail::bind_parser<mpl::true_>(
Chris@16 405 compile<qi::domain>(expr, encoding_modifier_type()));
Chris@16 406 return r;
Chris@16 407 }
Chris@16 408
Chris@16 409 template <typename Iterator_, typename T1_, typename T2_
Chris@16 410 , typename T3_, typename T4_, typename Expr>
Chris@16 411 rule<Iterator_, T1_, T2_, T3_, T4_>& operator%=(
Chris@16 412 rule<Iterator_, T1_, T2_, T3_, T4_>& r, Expr& expr)
Chris@16 413 {
Chris@16 414 return r %= static_cast<Expr const&>(expr);
Chris@16 415 }
Chris@16 416 #endif
Chris@16 417 }}}
Chris@16 418
Chris@16 419 namespace boost { namespace spirit { namespace traits
Chris@16 420 {
Chris@16 421 ///////////////////////////////////////////////////////////////////////////
Chris@16 422 template <
Chris@16 423 typename IteratorA, typename IteratorB, typename Attribute
Chris@16 424 , typename Context, typename T1, typename T2, typename T3, typename T4>
Chris@16 425 struct handles_container<
Chris@16 426 qi::rule<IteratorA, T1, T2, T3, T4>, Attribute, Context, IteratorB>
Chris@16 427 : traits::is_container<
Chris@16 428 typename attribute_of<
Chris@16 429 qi::rule<IteratorA, T1, T2, T3, T4>, Context, IteratorB
Chris@16 430 >::type
Chris@16 431 >
Chris@16 432 {};
Chris@16 433 }}}
Chris@16 434
Chris@16 435 #if defined(BOOST_MSVC)
Chris@16 436 # pragma warning(pop)
Chris@16 437 #endif
Chris@16 438
Chris@16 439 #endif