File indexing completed on 2025-01-19 09:47:37
0001
0002
0003
0004
0005
0006
0007 #if !defined(BOOST_SPIRIT_KARMA_RULE_MAR_05_2007_0455PM)
0008 #define BOOST_SPIRIT_KARMA_RULE_MAR_05_2007_0455PM
0009
0010 #if defined(_MSC_VER)
0011 #pragma once
0012 #endif
0013
0014 #include <boost/assert.hpp>
0015 #include <boost/config.hpp>
0016 #include <boost/function.hpp>
0017 #include <boost/mpl/vector.hpp>
0018 #include <boost/type_traits/is_same.hpp>
0019
0020 #include <boost/fusion/include/vector.hpp>
0021 #include <boost/fusion/include/size.hpp>
0022 #include <boost/fusion/include/make_vector.hpp>
0023 #include <boost/fusion/include/cons.hpp>
0024 #include <boost/fusion/include/as_list.hpp>
0025 #include <boost/fusion/include/as_vector.hpp>
0026
0027 #include <boost/spirit/home/support/unused.hpp>
0028 #include <boost/spirit/home/support/argument.hpp>
0029 #include <boost/spirit/home/support/context.hpp>
0030 #include <boost/spirit/home/support/info.hpp>
0031 #include <boost/spirit/home/karma/delimit_out.hpp>
0032 #include <boost/spirit/home/karma/detail/attributes.hpp>
0033 #include <boost/spirit/home/support/nonterminal/extract_param.hpp>
0034 #include <boost/spirit/home/support/nonterminal/locals.hpp>
0035 #include <boost/spirit/home/karma/reference.hpp>
0036 #include <boost/spirit/home/karma/detail/output_iterator.hpp>
0037 #include <boost/spirit/home/karma/nonterminal/nonterminal_fwd.hpp>
0038 #include <boost/spirit/home/karma/nonterminal/detail/generator_binder.hpp>
0039 #include <boost/spirit/home/karma/nonterminal/detail/parameterized.hpp>
0040
0041 #include <boost/static_assert.hpp>
0042 #include <boost/proto/extends.hpp>
0043 #include <boost/proto/traits.hpp>
0044 #include <boost/type_traits/is_const.hpp>
0045 #include <boost/type_traits/is_reference.hpp>
0046
0047 #if defined(BOOST_MSVC)
0048 # pragma warning(push)
0049 # pragma warning(disable: 4127)
0050 # pragma warning(disable: 4355)
0051 #endif
0052
0053 namespace boost { namespace spirit { namespace karma
0054 {
0055 BOOST_PP_REPEAT(SPIRIT_ATTRIBUTES_LIMIT, SPIRIT_USING_ATTRIBUTE, _)
0056
0057 using spirit::_pass_type;
0058 using spirit::_val_type;
0059 using spirit::_a_type;
0060 using spirit::_b_type;
0061 using spirit::_c_type;
0062 using spirit::_d_type;
0063 using spirit::_e_type;
0064 using spirit::_f_type;
0065 using spirit::_g_type;
0066 using spirit::_h_type;
0067 using spirit::_i_type;
0068 using spirit::_j_type;
0069
0070 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
0071
0072 using spirit::_pass;
0073 using spirit::_val;
0074 using spirit::_a;
0075 using spirit::_b;
0076 using spirit::_c;
0077 using spirit::_d;
0078 using spirit::_e;
0079 using spirit::_f;
0080 using spirit::_g;
0081 using spirit::_h;
0082 using spirit::_i;
0083 using spirit::_j;
0084
0085 #endif
0086
0087 using spirit::info;
0088 using spirit::locals;
0089
0090 template <
0091 typename OutputIterator, typename T1, typename T2, typename T3
0092 , typename T4>
0093 struct rule
0094 : proto::extends<
0095 typename proto::terminal<
0096 reference<rule<OutputIterator, T1, T2, T3, T4> const>
0097 >::type
0098 , rule<OutputIterator, T1, T2, T3, T4>
0099 >
0100 , generator<rule<OutputIterator, T1, T2, T3, T4> >
0101 {
0102 typedef mpl::int_<generator_properties::all_properties> properties;
0103
0104 typedef OutputIterator iterator_type;
0105 typedef rule<OutputIterator, T1, T2, T3, T4> this_type;
0106 typedef reference<this_type const> reference_;
0107 typedef typename proto::terminal<reference_>::type terminal;
0108 typedef proto::extends<terminal, this_type> base_type;
0109 typedef mpl::vector<T1, T2, T3, T4> template_params;
0110
0111
0112 typedef detail::output_iterator<OutputIterator, properties>
0113 output_iterator;
0114
0115
0116 typedef typename
0117 spirit::detail::extract_locals<template_params>::type
0118 locals_type;
0119
0120
0121 typedef typename
0122 spirit::detail::extract_component<
0123 karma::domain, template_params>::type
0124 delimiter_type;
0125
0126
0127 typedef typename
0128 spirit::detail::extract_encoding<template_params>::type
0129 encoding_type;
0130
0131
0132 typedef typename
0133 spirit::detail::extract_sig<template_params, encoding_type, karma::domain>::type
0134 sig_type;
0135
0136
0137 typedef typename
0138 spirit::detail::attr_from_sig<sig_type>::type
0139 attr_type;
0140 BOOST_STATIC_ASSERT_MSG(
0141 !is_reference<attr_type>::value && !is_const<attr_type>::value,
0142 "Const/reference qualifiers on Karma rule attribute are meaningless");
0143 typedef attr_type const& attr_reference_type;
0144
0145
0146 typedef typename
0147 spirit::detail::params_from_sig<sig_type>::type
0148 parameter_types;
0149
0150 static size_t const params_size =
0151 fusion::result_of::size<parameter_types>::type::value;
0152
0153
0154
0155 typedef context<
0156 fusion::cons<attr_reference_type, parameter_types>
0157 , locals_type>
0158 context_type;
0159
0160 typedef function<
0161 bool(output_iterator&, context_type&, delimiter_type const&)>
0162 function_type;
0163
0164 typedef typename
0165 mpl::if_<
0166 is_same<encoding_type, unused_type>
0167 , unused_type
0168 , tag::char_code<tag::encoding, encoding_type>
0169 >::type
0170 encoding_modifier_type;
0171
0172 explicit rule(std::string const& name_ = "unnamed-rule")
0173 : base_type(terminal::make(reference_(*this)))
0174 , name_(name_)
0175 {
0176 }
0177
0178 rule(rule const& rhs)
0179 : base_type(terminal::make(reference_(*this)))
0180 , name_(rhs.name_)
0181 , f(rhs.f)
0182 {
0183 }
0184
0185 template <typename Auto, typename Expr>
0186 static void define(rule& , Expr const& , mpl::false_)
0187 {
0188
0189
0190
0191 BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
0192 }
0193
0194 template <typename Auto, typename Expr>
0195 static void define(rule& lhs, Expr const& expr, mpl::true_)
0196 {
0197 lhs.f = detail::bind_generator<Auto>(
0198 compile<karma::domain>(expr, encoding_modifier_type()));
0199 }
0200
0201 template <typename Expr>
0202 rule (Expr const& expr, std::string const& name_ = "unnamed-rule")
0203 : base_type(terminal::make(reference_(*this)))
0204 , name_(name_)
0205 {
0206 define<mpl::false_>(*this, expr, traits::matches<karma::domain, Expr>());
0207 }
0208
0209 rule& operator=(rule const& rhs)
0210 {
0211
0212
0213
0214
0215 BOOST_ASSERT(rhs.f && "Did you mean rhs.alias() instead of rhs?");
0216
0217 f = rhs.f;
0218 name_ = rhs.name_;
0219 return *this;
0220 }
0221
0222 std::string const& name() const
0223 {
0224 return name_;
0225 }
0226
0227 void name(std::string const& str)
0228 {
0229 name_ = str;
0230 }
0231
0232 template <typename Expr>
0233 rule& operator=(Expr const& expr)
0234 {
0235 define<mpl::false_>(*this, expr, traits::matches<karma::domain, Expr>());
0236 return *this;
0237 }
0238
0239
0240 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1400)
0241
0242 template <typename Expr>
0243 friend rule& operator%=(rule& r, Expr const& expr)
0244 {
0245 define<mpl::true_>(r, expr, traits::matches<karma::domain, Expr>());
0246 return r;
0247 }
0248
0249 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0250
0251 template <typename Expr>
0252 friend rule& operator%=(rule& r, Expr& expr)
0253 {
0254 return r %= static_cast<Expr const&>(expr);
0255 }
0256 #else
0257
0258 template <typename Expr>
0259 friend rule& operator%=(rule& r, Expr&& expr)
0260 {
0261 define<mpl::true_>(r, expr, traits::matches<karma::domain, Expr>());
0262 return r;
0263 }
0264 #endif
0265
0266 #else
0267
0268
0269 template <typename OutputIterator_, typename T1_, typename T2_
0270 , typename T3_, typename T4_, typename Expr>
0271 friend rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=(
0272 rule<OutputIterator_, T1_, T2_, T3_, T4_>&r, Expr const& expr);
0273
0274
0275 template <typename OutputIterator_, typename T1_, typename T2_
0276 , typename T3_, typename T4_, typename Expr>
0277 friend rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=(
0278 rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr& expr);
0279 #endif
0280
0281 template <typename Context, typename Unused>
0282 struct attribute
0283 {
0284 typedef attr_type type;
0285 };
0286
0287 template <typename Context, typename Delimiter, typename Attribute>
0288 bool generate(output_iterator& sink, Context&, Delimiter const& delim
0289 , Attribute const& attr) const
0290 {
0291 if (f)
0292 {
0293
0294 typedef traits::transform_attribute<
0295 Attribute const, attr_type, domain>
0296 transform;
0297
0298 typename transform::type attr_ = transform::pre(attr);
0299
0300
0301
0302
0303 context_type context(attr_);
0304
0305
0306
0307
0308
0309 if (f(sink, context, delim))
0310 {
0311
0312 if (is_same<delimiter_type, unused_type>::value)
0313 karma::delimit_out(sink, delim);
0314
0315 return true;
0316 }
0317 }
0318 return false;
0319 }
0320
0321 template <typename Context, typename Delimiter, typename Attribute
0322 , typename Params>
0323 bool generate(output_iterator& sink, Context& caller_context
0324 , Delimiter const& delim, Attribute const& attr
0325 , Params const& params) const
0326 {
0327 if (f)
0328 {
0329
0330 typedef traits::transform_attribute<
0331 Attribute const, attr_type, domain>
0332 transform;
0333
0334 typename transform::type attr_ = transform::pre(attr);
0335
0336
0337
0338
0339 context_type context(attr_, params, caller_context);
0340
0341
0342
0343
0344
0345 if (f(sink, context, delim))
0346 {
0347
0348 if (is_same<delimiter_type, unused_type>::value)
0349 karma::delimit_out(sink, delim);
0350
0351 return true;
0352 }
0353 }
0354 return false;
0355 }
0356
0357 template <typename Context>
0358 info what(Context& ) const
0359 {
0360 return info(name_);
0361 }
0362
0363 reference_ alias() const
0364 {
0365 return reference_(*this);
0366 }
0367
0368 typename proto::terminal<this_type>::type copy() const
0369 {
0370 typename proto::terminal<this_type>::type result = {*this};
0371 return result;
0372 }
0373
0374
0375 rule const& get_parameterized_subject() const { return *this; }
0376 typedef rule parameterized_subject_type;
0377 #include <boost/spirit/home/karma/nonterminal/detail/fcall.hpp>
0378
0379 std::string name_;
0380 function_type f;
0381 };
0382
0383 #if BOOST_WORKAROUND(BOOST_MSVC, < 1400)
0384 template <typename OutputIterator_, typename T1_, typename T2_
0385 , typename T3_, typename T4_, typename Expr>
0386 rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=(
0387 rule<OutputIterator_, T1_, T2_, T3_, T4_>&r, Expr const& expr)
0388 {
0389
0390
0391
0392 BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
0393
0394 typedef typename
0395 rule<OutputIterator_, T1_, T2_, T3_, T4_>::encoding_modifier_type
0396 encoding_modifier_type;
0397
0398 r.f = detail::bind_generator<mpl::true_>(
0399 compile<karma::domain>(expr, encoding_modifier_type()));
0400 return r;
0401 }
0402
0403
0404 template <typename OutputIterator_, typename T1_, typename T2_
0405 , typename T3_, typename T4_, typename Expr>
0406 rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=(
0407 rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr& expr)
0408 {
0409 return r %= static_cast<Expr const&>(expr);
0410 }
0411 #endif
0412 }}}
0413
0414 namespace boost { namespace spirit { namespace traits
0415 {
0416 namespace detail
0417 {
0418 template <typename RuleAttribute, typename Attribute>
0419 struct nonterminal_handles_container
0420 : mpl::and_<
0421 traits::is_container<RuleAttribute>
0422 , is_convertible<Attribute, RuleAttribute> >
0423 {};
0424 }
0425
0426
0427 template <
0428 typename IteratorA, typename IteratorB, typename Attribute
0429 , typename Context, typename T1, typename T2, typename T3, typename T4>
0430 struct handles_container<
0431 karma::rule<IteratorA, T1, T2, T3, T4>, Attribute, Context
0432 , IteratorB>
0433 : detail::nonterminal_handles_container<
0434 typename attribute_of<
0435 karma::rule<IteratorA, T1, T2, T3, T4>
0436 , Context, IteratorB
0437 >::type, Attribute>
0438 {};
0439 }}}
0440
0441 #if defined(BOOST_MSVC)
0442 # pragma warning(pop)
0443 #endif
0444
0445 #endif