annotate DEPENDENCIES/generic/include/boost/spirit/home/qi/nonterminal/rule.hpp @ 133:4acb5d8d80b6 tip

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