Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-19 09:47:37

0001 //  Copyright (c) 2001-2011 Joel de Guzman
0002 //  Copyright (c) 2001-2011 Hartmut Kaiser
0003 //
0004 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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) // conditional expression is constant
0050 # pragma warning(disable: 4355) // 'this' : used in base member initializer list warning
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         // the output iterator is always wrapped by karma
0112         typedef detail::output_iterator<OutputIterator, properties>
0113             output_iterator;
0114 
0115         // locals_type is a sequence of types to be used as local variables
0116         typedef typename
0117             spirit::detail::extract_locals<template_params>::type
0118         locals_type;
0119 
0120         // The delimiter-generator type
0121         typedef typename
0122             spirit::detail::extract_component<
0123                 karma::domain, template_params>::type
0124         delimiter_type;
0125 
0126         // The rule's encoding type
0127         typedef typename
0128             spirit::detail::extract_encoding<template_params>::type
0129         encoding_type;
0130 
0131         // The rule's signature
0132         typedef typename
0133             spirit::detail::extract_sig<template_params, encoding_type, karma::domain>::type
0134         sig_type;
0135 
0136         // This is the rule's attribute type
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         // parameter_types is a sequence of types passed as parameters to the rule
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         // the context passed to the right hand side of a rule contains
0154         // the attribute and the parameters for this particular rule invocation
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& /* lhs */, Expr const& /* expr */, mpl::false_)
0187         {
0188             // Report invalid expression error as early as possible.
0189             // If you got an error_invalid_expression error message here,
0190             // then the expression (expr) is not a valid spirit karma expression.
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             // The following assertion fires when you try to initialize a rule
0212             // from an uninitialized one. Did you mean to refer to the right
0213             // hand side rule instead of assigning from it? In this case you
0214             // should write lhs = rhs.alias();
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 // VC7.1 has problems to resolve 'rule' without explicit template parameters
0240 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1400)
0241         // g++ 3.3 barfs if this is a member function :(
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         // non-const version needed to suppress proto's %= kicking in
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         // for rvalue references
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         // both friend functions have to be defined out of class as VC7.1
0268         // will complain otherwise
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         // non-const version needed to suppress proto's %= kicking in
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                 // Create an attribute if none is supplied.
0294                 typedef traits::transform_attribute<
0295                     Attribute const, attr_type, domain>
0296                 transform;
0297 
0298                 typename transform::type attr_ = transform::pre(attr);
0299 
0300                 // If you are seeing a compilation error here, you are probably
0301                 // trying to use a rule or a grammar which has inherited
0302                 // attributes, without passing values for them.
0303                 context_type context(attr_);
0304 
0305                 // If you are seeing a compilation error here stating that the
0306                 // third parameter can't be converted to a karma::reference
0307                 // then you are probably trying to use a rule or a grammar with
0308                 // an incompatible delimiter type.
0309                 if (f(sink, context, delim))
0310                 {
0311                     // do a post-delimit if this is an implied verbatim
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                 // Create an attribute if none is supplied.
0330                 typedef traits::transform_attribute<
0331                     Attribute const, attr_type, domain>
0332                 transform;
0333 
0334                 typename transform::type attr_ = transform::pre(attr);
0335 
0336                 // If you are seeing a compilation error here, you are probably
0337                 // trying to use a rule or a grammar which has inherited
0338                 // attributes, passing values of incompatible types for them.
0339                 context_type context(attr_, params, caller_context);
0340 
0341                 // If you are seeing a compilation error here stating that the
0342                 // third parameter can't be converted to a karma::reference
0343                 // then you are probably trying to use a rule or a grammar with
0344                 // an incompatible delimiter type.
0345                 if (f(sink, context, delim))
0346                 {
0347                     // do a post-delimit if this is an implied verbatim
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& /*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         // bring in the operator() overloads
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         // Report invalid expression error as early as possible.
0390         // If you got an error_invalid_expression error message here, then
0391         // the expression (expr) is not a valid spirit karma expression.
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     // non-const version needed to suppress proto's %= kicking in
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