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