Back to home page

EIC code displayed by LXR

 
 

    


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

0001 /*=============================================================================
0002     Copyright (c) 2001-2011 Joel de Guzman
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_RULE_FEBRUARY_12_2007_1020AM)
0008 #define BOOST_SPIRIT_RULE_FEBRUARY_12_2007_1020AM
0009 
0010 #if defined(_MSC_VER)
0011 #pragma once
0012 #endif
0013 
0014 #include <boost/assert.hpp>
0015 #include <boost/static_assert.hpp>
0016 #include <boost/config.hpp>
0017 #include <boost/function.hpp>
0018 #include <boost/mpl/vector.hpp>
0019 #include <boost/type_traits/is_convertible.hpp>
0020 #include <boost/type_traits/is_same.hpp>
0021 
0022 #include <boost/fusion/include/vector.hpp>
0023 #include <boost/fusion/include/size.hpp>
0024 #include <boost/fusion/include/make_vector.hpp>
0025 #include <boost/fusion/include/cons.hpp>
0026 #include <boost/fusion/include/as_list.hpp>
0027 #include <boost/fusion/include/as_vector.hpp>
0028 
0029 #include <boost/spirit/home/support/unused.hpp>
0030 #include <boost/spirit/home/support/argument.hpp>
0031 #include <boost/spirit/home/support/context.hpp>
0032 #include <boost/spirit/home/support/info.hpp>
0033 #include <boost/spirit/home/qi/detail/attributes.hpp>
0034 #include <boost/spirit/home/support/nonterminal/extract_param.hpp>
0035 #include <boost/spirit/home/support/nonterminal/locals.hpp>
0036 #include <boost/spirit/home/qi/reference.hpp>
0037 #include <boost/spirit/home/qi/nonterminal/detail/parameterized.hpp>
0038 #include <boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp>
0039 #include <boost/spirit/home/qi/nonterminal/nonterminal_fwd.hpp>
0040 #include <boost/spirit/home/qi/skip_over.hpp>
0041 
0042 #include <boost/proto/extends.hpp>
0043 #include <boost/proto/traits.hpp>
0044 #include <boost/type_traits/is_reference.hpp>
0045 
0046 #if defined(BOOST_MSVC)
0047 # pragma warning(push)
0048 # pragma warning(disable: 4355) // 'this' : used in base member initializer list warning
0049 # pragma warning(disable: 4127) // conditional expression is constant
0050 #endif
0051 
0052 namespace boost { namespace spirit { namespace qi
0053 {
0054     BOOST_PP_REPEAT(SPIRIT_ATTRIBUTES_LIMIT, SPIRIT_USING_ATTRIBUTE, _)
0055 
0056     using spirit::_pass_type;
0057     using spirit::_val_type;
0058     using spirit::_a_type;
0059     using spirit::_b_type;
0060     using spirit::_c_type;
0061     using spirit::_d_type;
0062     using spirit::_e_type;
0063     using spirit::_f_type;
0064     using spirit::_g_type;
0065     using spirit::_h_type;
0066     using spirit::_i_type;
0067     using spirit::_j_type;
0068 
0069 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
0070 
0071     using spirit::_pass;
0072     using spirit::_val;
0073     using spirit::_a;
0074     using spirit::_b;
0075     using spirit::_c;
0076     using spirit::_d;
0077     using spirit::_e;
0078     using spirit::_f;
0079     using spirit::_g;
0080     using spirit::_h;
0081     using spirit::_i;
0082     using spirit::_j;
0083 
0084 #endif
0085 
0086     using spirit::info;
0087     using spirit::locals;
0088 
0089     template <
0090         typename Iterator, typename T1, typename T2, typename T3
0091       , typename T4>
0092     struct rule
0093       : proto::extends<
0094             typename proto::terminal<
0095                 reference<rule<Iterator, T1, T2, T3, T4> const>
0096             >::type
0097           , rule<Iterator, T1, T2, T3, T4>
0098         >
0099       , parser<rule<Iterator, T1, T2, T3, T4> >
0100     {
0101         typedef Iterator iterator_type;
0102         typedef rule<Iterator, T1, T2, T3, T4> this_type;
0103         typedef reference<this_type const> reference_;
0104         typedef typename proto::terminal<reference_>::type terminal;
0105         typedef proto::extends<terminal, this_type> base_type;
0106         typedef mpl::vector<T1, T2, T3, T4> template_params;
0107 
0108         // The rule's locals_type: a sequence of types to be used as local variables
0109         typedef typename
0110             spirit::detail::extract_locals<template_params>::type
0111         locals_type;
0112 
0113         // The rule's skip-parser type
0114         typedef typename
0115             spirit::detail::extract_component<
0116                 qi::domain, template_params>::type
0117         skipper_type;
0118 
0119         // The rule's encoding type
0120         typedef typename
0121             spirit::detail::extract_encoding<template_params>::type
0122         encoding_type;
0123 
0124         // The rule's signature
0125         typedef typename
0126             spirit::detail::extract_sig<template_params, encoding_type, qi::domain>::type
0127         sig_type;
0128 
0129         // This is the rule's attribute type
0130         typedef typename
0131             spirit::detail::attr_from_sig<sig_type>::type
0132         attr_type;
0133         BOOST_STATIC_ASSERT_MSG(
0134             !is_reference<attr_type>::value,
0135             "Reference qualifier on Qi rule attribute is meaningless");
0136         typedef attr_type& attr_reference_type;
0137 
0138         // parameter_types is a sequence of types passed as parameters to the rule
0139         typedef typename
0140             spirit::detail::params_from_sig<sig_type>::type
0141         parameter_types;
0142 
0143         static size_t const params_size =
0144             fusion::result_of::size<parameter_types>::type::value;
0145 
0146         typedef context<
0147             fusion::cons<attr_reference_type, parameter_types>
0148           , locals_type>
0149         context_type;
0150 
0151         typedef function<
0152             bool(Iterator& first, Iterator const& last
0153               , context_type& context
0154               , skipper_type const& skipper
0155             )>
0156         function_type;
0157 
0158         typedef typename
0159             mpl::if_<
0160                 is_same<encoding_type, unused_type>
0161               , unused_type
0162               , tag::char_code<tag::encoding, encoding_type>
0163             >::type
0164         encoding_modifier_type;
0165 
0166         explicit rule(std::string const& name = "unnamed-rule")
0167           : base_type(terminal::make(reference_(*this)))
0168           , name_(name)
0169         {
0170         }
0171 
0172         rule(rule const& rhs)
0173           : base_type(terminal::make(reference_(*this)))
0174           , name_(rhs.name_)
0175           , f(rhs.f)
0176         {
0177         }
0178 
0179         template <typename Auto, typename Expr>
0180         static void define(rule& /*lhs*/, Expr const& /*expr*/, mpl::false_)
0181         {
0182             // Report invalid expression error as early as possible.
0183             // If you got an error_invalid_expression error message here,
0184             // then the expression (expr) is not a valid spirit qi expression.
0185             BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr);
0186         }
0187 
0188         template <typename Auto, typename Expr>
0189         static void define(rule& lhs, Expr const& expr, mpl::true_)
0190         {
0191             lhs.f = detail::bind_parser<Auto>(
0192                 compile<qi::domain>(expr, encoding_modifier_type()));
0193         }
0194 
0195         template <typename Expr>
0196         rule(Expr const& expr, std::string const& name = "unnamed-rule")
0197           : base_type(terminal::make(reference_(*this)))
0198           , name_(name)
0199         {
0200             define<mpl::false_>(*this, expr, traits::matches<qi::domain, Expr>());
0201         }
0202 
0203         rule& operator=(rule const& rhs)
0204         {
0205             // The following assertion fires when you try to initialize a rule
0206             // from an uninitialized one. Did you mean to refer to the right
0207             // hand side rule instead of assigning from it? In this case you
0208             // should write lhs = rhs.alias();
0209             BOOST_ASSERT(rhs.f && "Did you mean rhs.alias() instead of rhs?");
0210 
0211             f = rhs.f;
0212             name_ = rhs.name_;
0213             return *this;
0214         }
0215 
0216         std::string const& name() const
0217         {
0218             return name_;
0219         }
0220 
0221         void name(std::string const& str)
0222         {
0223             name_ = str;
0224         }
0225 
0226         template <typename Expr>
0227         rule& operator=(Expr const& expr)
0228         {
0229             define<mpl::false_>(*this, expr, traits::matches<qi::domain, Expr>());
0230             return *this;
0231         }
0232 
0233 // VC7.1 has problems to resolve 'rule' without explicit template parameters
0234 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1400)
0235         // g++ 3.3 barfs if this is a member function :(
0236         template <typename Expr>
0237         friend rule& operator%=(rule& r, Expr const& expr)
0238         {
0239             define<mpl::true_>(r, expr, traits::matches<qi::domain, Expr>());
0240             return r;
0241         }
0242 
0243 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0244         // non-const version needed to suppress proto's %= kicking in
0245         template <typename Expr>
0246         friend rule& operator%=(rule& r, Expr& expr)
0247         {
0248             return r %= static_cast<Expr const&>(expr);
0249         }
0250 #else
0251         // for rvalue references
0252         template <typename Expr>
0253         friend rule& operator%=(rule& r, Expr&& expr)
0254         {
0255             define<mpl::true_>(r, expr, traits::matches<qi::domain, Expr>());
0256             return r;
0257         }
0258 #endif
0259 
0260 #else
0261         // both friend functions have to be defined out of class as VC7.1
0262         // will complain otherwise
0263         template <typename OutputIterator_, typename T1_, typename T2_
0264           , typename T3_, typename T4_, typename Expr>
0265         friend rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=(
0266             rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr const& expr);
0267 
0268         // non-const version needed to suppress proto's %= kicking in
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& expr);
0273 #endif
0274 
0275         template <typename Context, typename Iterator_>
0276         struct attribute
0277         {
0278             typedef attr_type type;
0279         };
0280 
0281         template <typename Context, typename Skipper, typename Attribute>
0282         bool parse(Iterator& first, Iterator const& last
0283           , Context& /*context*/, Skipper const& skipper
0284           , Attribute& attr_param) const
0285         {
0286             BOOST_STATIC_ASSERT_MSG((is_same<skipper_type, unused_type>::value ||
0287                 !is_same<Skipper, unused_type>::value),
0288                 "The rule was instantiated with a skipper type but you have not pass any. "
0289                 "Did you use `parse` instead of `phrase_parse`?");
0290             BOOST_STATIC_ASSERT_MSG(
0291                 (is_convertible<Skipper const&, skipper_type>::value),
0292                 "The passed skipper is not compatible/convertible to one "
0293                 "that the rule was instantiated with");
0294             if (f)
0295             {
0296                 // do a preskip if this is an implied lexeme
0297                 if (is_same<skipper_type, unused_type>::value)
0298                     qi::skip_over(first, last, skipper);
0299 
0300                 // do down-stream transformation, provides attribute for
0301                 // rhs parser
0302                 typedef traits::transform_attribute<
0303                     Attribute, attr_type, domain>
0304                 transform;
0305 
0306                 typename transform::type attr_ = transform::pre(attr_param);
0307 
0308                 // If you are seeing a compilation error here, you are probably
0309                 // trying to use a rule or a grammar which has inherited
0310                 // attributes, without passing values for them.
0311                 context_type context(attr_);
0312 
0313                 // If you are seeing a compilation error here stating that the
0314                 // fourth parameter can't be converted to a required target type
0315                 // then you are probably trying to use a rule or a grammar with
0316                 // an incompatible skipper type.
0317                 if (f(first, last, context, skipper))
0318                 {
0319                     // do up-stream transformation, this integrates the results
0320                     // back into the original attribute value, if appropriate
0321                     transform::post(attr_param, attr_);
0322                     return true;
0323                 }
0324 
0325                 // inform attribute transformation of failed rhs
0326                 transform::fail(attr_param);
0327             }
0328             return false;
0329         }
0330 
0331         template <typename Context, typename Skipper
0332           , typename Attribute, typename Params>
0333         bool parse(Iterator& first, Iterator const& last
0334           , Context& caller_context, Skipper const& skipper
0335           , Attribute& attr_param, Params const& params) const
0336         {
0337             BOOST_STATIC_ASSERT_MSG((is_same<skipper_type, unused_type>::value ||
0338                 !is_same<Skipper, unused_type>::value),
0339                 "The rule was instantiated with a skipper type but you have not pass any. "
0340                 "Did you use `parse` instead of `phrase_parse`?");
0341             BOOST_STATIC_ASSERT_MSG(
0342                 (is_convertible<Skipper const&, skipper_type>::value),
0343                 "The passed skipper is not compatible/convertible to one "
0344                 "that the rule was instantiated with");
0345             if (f)
0346             {
0347                 // do a preskip if this is an implied lexeme
0348                 if (is_same<skipper_type, unused_type>::value)
0349                     qi::skip_over(first, last, skipper);
0350 
0351                 // do down-stream transformation, provides attribute for
0352                 // rhs parser
0353                 typedef traits::transform_attribute<
0354                     Attribute, attr_type, domain>
0355                 transform;
0356 
0357                 typename transform::type attr_ = transform::pre(attr_param);
0358 
0359                 // If you are seeing a compilation error here, you are probably
0360                 // trying to use a rule or a grammar which has inherited
0361                 // attributes, passing values of incompatible types for them.
0362                 context_type context(attr_, params, caller_context);
0363 
0364                 // If you are seeing a compilation error here stating that the
0365                 // fourth parameter can't be converted to a required target type
0366                 // then you are probably trying to use a rule or a grammar with
0367                 // an incompatible skipper type.
0368                 if (f(first, last, context, skipper))
0369                 {
0370                     // do up-stream transformation, this integrates the results
0371                     // back into the original attribute value, if appropriate
0372                     transform::post(attr_param, attr_);
0373                     return true;
0374                 }
0375 
0376                 // inform attribute transformation of failed rhs
0377                 transform::fail(attr_param);
0378             }
0379             return false;
0380         }
0381 
0382         template <typename Context>
0383         info what(Context& /*context*/) const
0384         {
0385             return info(name_);
0386         }
0387 
0388         reference_ alias() const
0389         {
0390             return reference_(*this);
0391         }
0392 
0393         typename proto::terminal<this_type>::type copy() const
0394         {
0395             typename proto::terminal<this_type>::type result = {*this};
0396             return result;
0397         }
0398 
0399         // bring in the operator() overloads
0400         rule const& get_parameterized_subject() const { return *this; }
0401         typedef rule parameterized_subject_type;
0402         #include <boost/spirit/home/qi/nonterminal/detail/fcall.hpp>
0403 
0404         std::string name_;
0405         function_type f;
0406     };
0407 
0408 #if BOOST_WORKAROUND(BOOST_MSVC, < 1400)
0409     template <typename OutputIterator_, typename T1_, typename T2_
0410       , typename T3_, typename T4_, typename Expr>
0411     rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=(
0412         rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr const& expr)
0413     {
0414         // Report invalid expression error as early as possible.
0415         // If you got an error_invalid_expression error message here,
0416         // then the expression (expr) is not a valid spirit qi expression.
0417         BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr);
0418 
0419         typedef typename
0420             rule<OutputIterator_, T1_, T2_, T3_, T4_>::encoding_modifier_type
0421         encoding_modifier_type;
0422 
0423         r.f = detail::bind_parser<mpl::true_>(
0424             compile<qi::domain>(expr, encoding_modifier_type()));
0425         return r;
0426     }
0427 
0428     template <typename Iterator_, typename T1_, typename T2_
0429       , typename T3_, typename T4_, typename Expr>
0430     rule<Iterator_, T1_, T2_, T3_, T4_>& operator%=(
0431         rule<Iterator_, T1_, T2_, T3_, T4_>& r, Expr& expr)
0432     {
0433         return r %= static_cast<Expr const&>(expr);
0434     }
0435 #endif
0436 }}}
0437 
0438 namespace boost { namespace spirit { namespace traits
0439 {
0440     ///////////////////////////////////////////////////////////////////////////
0441     template <
0442         typename IteratorA, typename IteratorB, typename Attribute
0443       , typename Context, typename T1, typename T2, typename T3, typename T4>
0444     struct handles_container<
0445         qi::rule<IteratorA, T1, T2, T3, T4>, Attribute, Context, IteratorB>
0446       : traits::is_container<
0447           typename attribute_of<
0448               qi::rule<IteratorA, T1, T2, T3, T4>, Context, IteratorB
0449           >::type
0450         >
0451     {};
0452 }}}
0453 
0454 #if defined(BOOST_MSVC)
0455 # pragma warning(pop)
0456 #endif
0457 
0458 #endif