Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:52:30

0001 /*=============================================================================
0002     Copyright (c) 2009 Francois Barel
0003     Copyright (c) 2001-2011 Joel de Guzman
0004 
0005     Distributed under the Boost Software License, Version 1.0. (See accompanying
0006     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 ==============================================================================*/
0008 #if !defined(BOOST_SPIRIT_REPOSITORY_QI_SUBRULE_AUGUST_06_2009_0239AM)
0009 #define BOOST_SPIRIT_REPOSITORY_QI_SUBRULE_AUGUST_06_2009_0239AM
0010 
0011 #if defined(_MSC_VER)
0012 #pragma once
0013 #endif
0014 
0015 #include <boost/spirit/home/qi/domain.hpp>
0016 #include <boost/spirit/home/qi/meta_compiler.hpp>
0017 #include <boost/spirit/home/qi/parser.hpp>
0018 #include <boost/spirit/home/qi/reference.hpp>
0019 #include <boost/spirit/home/qi/nonterminal/detail/parameterized.hpp>
0020 #include <boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp>
0021 #include <boost/spirit/home/support/argument.hpp>
0022 #include <boost/spirit/home/support/assert_msg.hpp>
0023 #include <boost/spirit/home/qi/detail/attributes.hpp>
0024 #include <boost/spirit/home/support/info.hpp>
0025 #include <boost/spirit/home/support/unused.hpp>
0026 #include <boost/spirit/home/support/nonterminal/extract_param.hpp>
0027 #include <boost/spirit/home/support/nonterminal/locals.hpp>
0028 #include <boost/spirit/repository/home/support/subrule_context.hpp>
0029 
0030 #include <boost/static_assert.hpp>
0031 #include <boost/fusion/include/as_map.hpp>
0032 #include <boost/fusion/include/at_key.hpp>
0033 #include <boost/fusion/include/cons.hpp>
0034 #include <boost/fusion/include/front.hpp>
0035 #include <boost/fusion/include/has_key.hpp>
0036 #include <boost/fusion/include/join.hpp>
0037 #include <boost/fusion/include/make_map.hpp>
0038 #include <boost/fusion/include/make_vector.hpp>
0039 #include <boost/fusion/include/size.hpp>
0040 #include <boost/fusion/include/vector.hpp>
0041 #include <boost/mpl/bool.hpp>
0042 #include <boost/mpl/identity.hpp>
0043 #include <boost/mpl/int.hpp>
0044 #include <boost/mpl/vector.hpp>
0045 #include <boost/proto/extends.hpp>
0046 #include <boost/proto/traits.hpp>
0047 #include <boost/type_traits/is_reference.hpp>
0048 #include <boost/type_traits/is_same.hpp>
0049 #include <boost/type_traits/remove_reference.hpp>
0050 
0051 #if defined(BOOST_MSVC)
0052 # pragma warning(push)
0053 # pragma warning(disable: 4355) // 'this' : used in base member initializer list warning
0054 #endif
0055 
0056 ///////////////////////////////////////////////////////////////////////////////
0057 namespace boost { namespace spirit { namespace repository { namespace qi
0058 {
0059     ///////////////////////////////////////////////////////////////////////////
0060     // subrule_group_parser:
0061     // - parser representing a group of subrule definitions (one or more),
0062     //   invokes first subrule on entry,
0063     ///////////////////////////////////////////////////////////////////////////
0064     template <typename Defs>
0065     struct subrule_group_parser
0066       : spirit::qi::parser<subrule_group_parser<Defs> >
0067     {
0068         // Fusion associative sequence, associating each subrule ID in this
0069         // group (as an MPL integral constant) with its definition
0070         typedef Defs defs_type;
0071 
0072         typedef subrule_group_parser<Defs> this_type;
0073 
0074         explicit subrule_group_parser(Defs const& defs)
0075           : defs(defs)
0076         {
0077         }
0078 
0079         // from a subrule ID, get the type of a reference to its definition
0080         template <int ID>
0081         struct def_type
0082         {
0083             typedef mpl::int_<ID> id_type;
0084 
0085             // If you are seeing a compilation error here, you are trying
0086             // to use a subrule which was not defined in this group.
0087             BOOST_SPIRIT_ASSERT_MSG(
0088                 (fusion::result_of::has_key<
0089                     defs_type const, id_type>::type::value)
0090               , subrule_used_without_being_defined, (mpl::int_<ID>));
0091 
0092             typedef typename
0093                 fusion::result_of::at_key<defs_type const, id_type>::type
0094             type;
0095         };
0096 
0097         // from a subrule ID, get a reference to its definition
0098         template <int ID>
0099         typename def_type<ID>::type def() const
0100         {
0101             return fusion::at_key<mpl::int_<ID> >(defs);
0102         }
0103 
0104         template <typename Context, typename Iterator>
0105         struct attribute
0106             // Forward to first subrule.
0107           : mpl::identity<
0108                 typename remove_reference<
0109                     typename fusion::result_of::front<Defs>::type
0110                 >::type::second_type::attr_type> {};
0111 
0112         template <typename Iterator, typename Context
0113           , typename Skipper, typename Attribute>
0114         bool parse(Iterator& first, Iterator const& last
0115           , Context& context, Skipper const& skipper
0116           , Attribute& attr) const
0117         {
0118             // Forward to first subrule.
0119             return parse_subrule(fusion::front(defs).second
0120               , first, last, context, skipper, attr);
0121         }
0122 
0123         template <typename Iterator, typename Context
0124           , typename Skipper, typename Attribute, typename Params>
0125         bool parse(Iterator& first, Iterator const& last
0126           , Context& context, Skipper const& skipper
0127           , Attribute& attr, Params const& params) const
0128         {
0129             // Forward to first subrule.
0130             return parse_subrule(fusion::front(defs).second
0131               , first, last, context, skipper, attr, params);
0132         }
0133 
0134         template <int ID, typename Iterator, typename Context
0135           , typename Skipper, typename Attribute>
0136         bool parse_subrule_id(Iterator& first, Iterator const& last
0137           , Context& context, Skipper const& skipper
0138           , Attribute& attr) const
0139         {
0140             return parse_subrule(def<ID>()
0141               , first, last, context, skipper, attr);
0142         }
0143 
0144         template <int ID, typename Iterator, typename Context
0145           , typename Skipper, typename Attribute, typename Params>
0146         bool parse_subrule_id(Iterator& first, Iterator const& last
0147           , Context& context, Skipper const& skipper
0148           , Attribute& attr, Params const& params) const
0149         {
0150             return parse_subrule(def<ID>()
0151               , first, last, context, skipper, attr, params);
0152         }
0153 
0154         template <typename Def
0155           , typename Iterator, typename Context
0156           , typename Skipper, typename Attribute>
0157         bool parse_subrule(Def const& def
0158           , Iterator& first, Iterator const& last
0159           , Context& /*caller_context*/, Skipper const& skipper
0160           , Attribute& attr) const
0161         {
0162             // compute context type for this subrule
0163             typedef typename Def::locals_type subrule_locals_type;
0164             typedef typename Def::attr_type subrule_attr_type;
0165             typedef typename Def::attr_reference_type subrule_attr_reference_type;
0166             typedef typename Def::parameter_types subrule_parameter_types;
0167 
0168             typedef
0169                 subrule_context<
0170                     this_type
0171                   , fusion::cons<
0172                         subrule_attr_reference_type, subrule_parameter_types>
0173                   , subrule_locals_type
0174                 >
0175             context_type;
0176 
0177             // do down-stream transformation, provides attribute for 
0178             // rhs parser
0179             typedef traits::transform_attribute<
0180                 Attribute, subrule_attr_type, spirit::qi::domain> 
0181             transform;
0182 
0183             typename transform::type attr_ = transform::pre(attr);
0184 
0185             // If you are seeing a compilation error here, you are probably
0186             // trying to use a subrule which has inherited attributes,
0187             // without passing values for them.
0188             context_type context(*this, attr_);
0189 
0190             if (def.binder(first, last, context, skipper))
0191             {
0192                 // do up-stream transformation, this integrates the results 
0193                 // back into the original attribute value, if appropriate
0194                 transform::post(attr, attr_);
0195                 return true;
0196             }
0197 
0198             // inform attribute transformation of failed rhs
0199             transform::fail(attr);
0200             return false;
0201         }
0202 
0203         template <typename Def
0204           , typename Iterator, typename Context
0205           , typename Skipper, typename Attribute, typename Params>
0206         bool parse_subrule(Def const& def
0207           , Iterator& first, Iterator const& last
0208           , Context& caller_context, Skipper const& skipper
0209           , Attribute& attr, Params const& params) const
0210         {
0211             // compute context type for this subrule
0212             typedef typename Def::locals_type subrule_locals_type;
0213             typedef typename Def::attr_type subrule_attr_type;
0214             typedef typename Def::attr_reference_type subrule_attr_reference_type;
0215             typedef typename Def::parameter_types subrule_parameter_types;
0216 
0217             typedef
0218                 subrule_context<
0219                     this_type
0220                   , fusion::cons<
0221                         subrule_attr_reference_type, subrule_parameter_types>
0222                   , subrule_locals_type
0223                 >
0224             context_type;
0225 
0226             // do down-stream transformation, provides attribute for 
0227             // rhs parser
0228             typedef traits::transform_attribute<
0229                 Attribute, subrule_attr_type, spirit::qi::domain> 
0230             transform;
0231 
0232             typename transform::type attr_ = transform::pre(attr);
0233 
0234             // If you are seeing a compilation error here, you are probably
0235             // trying to use a subrule which has inherited attributes,
0236             // passing values of incompatible types for them.
0237             context_type context(*this, attr_, params, caller_context);
0238 
0239             if (def.binder(first, last, context, skipper))
0240             {
0241                 // do up-stream transformation, this integrates the results 
0242                 // back into the original attribute value, if appropriate
0243                 transform::post(attr, attr_);
0244                 return true;
0245             }
0246 
0247             // inform attribute transformation of failed rhs
0248             transform::fail(attr);
0249             return false;
0250         }
0251 
0252         template <typename Context>
0253         info what(Context& context) const
0254         {
0255             // Forward to first subrule.
0256             return fusion::front(defs).second.binder.p.what(context);
0257         }
0258 
0259         Defs defs;
0260     };
0261 
0262     ///////////////////////////////////////////////////////////////////////////
0263     // subrule_group:
0264     // - a Proto terminal, so that a group behaves like any Spirit
0265     //   expression.
0266     ///////////////////////////////////////////////////////////////////////////
0267     template <typename Defs>
0268     struct subrule_group
0269       : proto::extends<
0270             typename proto::terminal<
0271                 subrule_group_parser<Defs>
0272             >::type
0273           , subrule_group<Defs>
0274         >
0275     {
0276         typedef subrule_group_parser<Defs> parser_type;
0277         typedef typename proto::terminal<parser_type>::type terminal;
0278 
0279         static size_t const params_size =
0280             // Forward to first subrule.
0281             remove_reference<
0282                 typename fusion::result_of::front<Defs>::type
0283             >::type::second_type::params_size;
0284 
0285         explicit subrule_group(Defs const& defs)
0286           : subrule_group::proto_extends(terminal::make(parser_type(defs)))
0287         {
0288         }
0289 
0290         parser_type const& parser() const { return proto::value(*this); }
0291 
0292         Defs const& defs() const { return parser().defs; }
0293 
0294         template <typename Defs2>
0295         subrule_group<
0296             typename fusion::result_of::as_map<
0297                 typename fusion::result_of::join<
0298                     Defs const, Defs2 const>::type>::type>
0299         operator,(subrule_group<Defs2> const& other) const
0300         {
0301             typedef subrule_group<
0302                 typename fusion::result_of::as_map<
0303                     typename fusion::result_of::join<
0304                         Defs const, Defs2 const>::type>::type> result_type;
0305             return result_type(fusion::as_map(fusion::join(defs(), other.defs())));
0306         }
0307 
0308         // non-const versions needed to suppress proto's comma op kicking in
0309         template <typename Defs2>
0310         friend subrule_group<
0311             typename fusion::result_of::as_map<
0312                 typename fusion::result_of::join<
0313                     Defs const, Defs2 const>::type>::type>
0314 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0315         operator,(subrule_group&& left, subrule_group<Defs2>&& other)
0316 #else
0317         operator,(subrule_group& left, subrule_group<Defs2>& other)
0318 #endif
0319         {
0320             return static_cast<subrule_group const&>(left)
0321                 .operator,(static_cast<subrule_group<Defs2> const&>(other));
0322         }
0323 
0324         // bring in the operator() overloads
0325         parser_type const& get_parameterized_subject() const { return parser(); }
0326         typedef parser_type parameterized_subject_type;
0327         #include <boost/spirit/home/qi/nonterminal/detail/fcall.hpp>
0328     };
0329 
0330     ///////////////////////////////////////////////////////////////////////////
0331     // subrule_definition: holds one particular definition of a subrule
0332     ///////////////////////////////////////////////////////////////////////////
0333     template <
0334         int ID_
0335       , typename Locals
0336       , typename Attr
0337       , typename AttrRef
0338       , typename Parameters
0339       , size_t ParamsSize
0340       , typename Subject
0341       , bool Auto_
0342     >
0343     struct subrule_definition
0344     {
0345         typedef mpl::int_<ID_> id_type;
0346         BOOST_STATIC_CONSTANT(int, ID = ID_);
0347 
0348         typedef Locals locals_type;
0349         typedef Attr attr_type;
0350         typedef AttrRef attr_reference_type;
0351         typedef Parameters parameter_types;
0352         static size_t const params_size = ParamsSize;
0353 
0354         typedef Subject subject_type;
0355         typedef mpl::bool_<Auto_> auto_type;
0356         BOOST_STATIC_CONSTANT(bool, Auto = Auto_);
0357 
0358         typedef spirit::qi::detail::parser_binder<
0359             Subject, auto_type> binder_type;
0360 
0361         subrule_definition(Subject const& subject, std::string const& name)
0362           : binder(subject), name(name)
0363         {
0364         }
0365 
0366         binder_type const binder;
0367         std::string const name;
0368     };
0369 
0370     ///////////////////////////////////////////////////////////////////////////
0371     // subrule placeholder:
0372     // - on subrule definition: helper for creation of subrule_group,
0373     // - on subrule invocation: Proto terminal and parser.
0374     ///////////////////////////////////////////////////////////////////////////
0375     template <
0376         int ID_
0377       , typename T1 = unused_type
0378       , typename T2 = unused_type
0379     >
0380     struct subrule
0381       : proto::extends<
0382             typename proto::terminal<
0383                 spirit::qi::reference<subrule<ID_, T1, T2> const>
0384             >::type
0385           , subrule<ID_, T1, T2>
0386         >
0387       , spirit::qi::parser<subrule<ID_, T1, T2> >
0388     {
0389         typedef mpl::int_<ID_> id_type;
0390         BOOST_STATIC_CONSTANT(int, ID = ID_);
0391 
0392         typedef subrule<ID_, T1, T2> this_type;
0393         typedef spirit::qi::reference<this_type const> reference_;
0394         typedef typename proto::terminal<reference_>::type terminal;
0395         typedef proto::extends<terminal, this_type> base_type;
0396 
0397         typedef mpl::vector<T1, T2> template_params;
0398 
0399         // The subrule's locals_type: a sequence of types to be used as local variables
0400         typedef typename
0401             spirit::detail::extract_locals<template_params>::type
0402         locals_type;
0403 
0404         // The subrule's encoding type
0405         typedef typename
0406             spirit::detail::extract_encoding<template_params>::type
0407         encoding_type;
0408 
0409         // The subrule's signature
0410         typedef typename
0411             spirit::detail::extract_sig<template_params, encoding_type
0412               , spirit::qi::domain>::type
0413         sig_type;
0414 
0415         // This is the subrule's attribute type
0416         typedef typename
0417             spirit::detail::attr_from_sig<sig_type>::type
0418         attr_type;
0419         BOOST_STATIC_ASSERT_MSG(
0420             !is_reference<attr_type>::value,
0421             "Reference qualifier on Qi subrule attribute type is meaningless");
0422         typedef attr_type& attr_reference_type;
0423 
0424         // parameter_types is a sequence of types passed as parameters to the subrule
0425         typedef typename
0426             spirit::detail::params_from_sig<sig_type>::type
0427         parameter_types;
0428 
0429         static size_t const params_size =
0430             fusion::result_of::size<parameter_types>::type::value;
0431 
0432         explicit subrule(std::string const& name_ = "unnamed-subrule")
0433           : base_type(terminal::make(reference_(*this)))
0434           , name_(name_)
0435         {
0436         }
0437 
0438         // compute type of this subrule's definition for expr type Expr
0439         template <typename Expr, bool Auto>
0440         struct def_type_helper
0441         {
0442             // Report invalid expression error as early as possible.
0443             // If you got an error_invalid_expression error message here,
0444             // then the expression (Expr) is not a valid spirit qi expression.
0445             BOOST_SPIRIT_ASSERT_MATCH(spirit::qi::domain, Expr);
0446 
0447             typedef typename result_of::compile<
0448                 spirit::qi::domain, Expr>::type subject_type;
0449 
0450             typedef subrule_definition<
0451                 ID_
0452               , locals_type
0453               , attr_type
0454               , attr_reference_type
0455               , parameter_types
0456               , params_size
0457               , subject_type
0458               , Auto
0459             > const type;
0460         };
0461 
0462         // compute type of subrule group containing only this
0463         // subrule's definition for expr type Expr
0464         template <typename Expr, bool Auto>
0465         struct group_type_helper
0466         {
0467             typedef typename def_type_helper<Expr, Auto>::type def_type;
0468 
0469             // create Defs map with only one entry: (ID -> def)
0470             typedef typename
0471 #ifndef BOOST_FUSION_HAS_VARIADIC_MAP
0472                 fusion::result_of::make_map<id_type, def_type>::type
0473 #else
0474                 fusion::result_of::make_map<id_type>::template apply<def_type>::type
0475 #endif
0476             defs_type;
0477 
0478             typedef subrule_group<defs_type> type;
0479         };
0480 
0481         template <typename Expr>
0482         typename group_type_helper<Expr, false>::type
0483         operator=(Expr const& expr) const
0484         {
0485             typedef group_type_helper<Expr, false> helper;
0486             typedef typename helper::def_type def_type;
0487             typedef typename helper::type result_type;
0488             return result_type(fusion::make_map<id_type>(
0489                 def_type(compile<spirit::qi::domain>(expr), name_)));
0490         }
0491 
0492 #define BOOST_SPIRIT_SUBRULE_MODULUS_ASSIGN_OPERATOR(lhs_ref, rhs_ref)        \
0493         template <typename Expr>                                              \
0494         friend typename group_type_helper<Expr, true>::type                   \
0495         operator%=(subrule lhs_ref sr, Expr rhs_ref expr)                     \
0496         {                                                                     \
0497             typedef group_type_helper<Expr, true> helper;                     \
0498             typedef typename helper::def_type def_type;                       \
0499             typedef typename helper::type result_type;                        \
0500             return result_type(fusion::make_map<id_type>(                     \
0501                 def_type(compile<spirit::qi::domain>(expr), sr.name_)));      \
0502         }                                                                     \
0503         /**/
0504 
0505         // non-const versions needed to suppress proto's %= kicking in
0506         BOOST_SPIRIT_SUBRULE_MODULUS_ASSIGN_OPERATOR(const&, const&)
0507 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0508         BOOST_SPIRIT_SUBRULE_MODULUS_ASSIGN_OPERATOR(const&, &&)
0509 #else
0510         BOOST_SPIRIT_SUBRULE_MODULUS_ASSIGN_OPERATOR(const&, &)
0511 #endif
0512         BOOST_SPIRIT_SUBRULE_MODULUS_ASSIGN_OPERATOR(&, const&)
0513 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0514         BOOST_SPIRIT_SUBRULE_MODULUS_ASSIGN_OPERATOR(&, &&)
0515 #else
0516         BOOST_SPIRIT_SUBRULE_MODULUS_ASSIGN_OPERATOR(&, &)
0517 #endif
0518 
0519 #undef BOOST_SPIRIT_SUBRULE_MODULUS_ASSIGN_OPERATOR
0520 
0521         std::string const& name() const
0522         {
0523             return name_;
0524         }
0525 
0526         void name(std::string const& str)
0527         {
0528             name_ = str;
0529         }
0530 
0531         template <typename Context, typename Iterator>
0532         struct attribute
0533         {
0534             typedef attr_type type;
0535         };
0536 
0537         template <typename Iterator, typename Group
0538           , typename Attributes, typename Locals
0539           , typename Skipper, typename Attribute>
0540         bool parse(Iterator& first, Iterator const& last
0541           , subrule_context<Group, Attributes, Locals>& context
0542           , Skipper const& skipper, Attribute& attr) const
0543         {
0544             return context.group.template parse_subrule_id<ID_>(
0545                 first, last, context, skipper, attr);
0546         }
0547 
0548         template <typename Iterator, typename Context
0549           , typename Skipper, typename Attribute>
0550         bool parse(Iterator& /*first*/, Iterator const& /*last*/
0551           , Context& /*context*/
0552           , Skipper const& /*skipper*/, Attribute& /*attr*/) const
0553         {
0554             // If you are seeing a compilation error here, you are trying
0555             // to use a subrule as a parser outside of a subrule group.
0556             BOOST_SPIRIT_ASSERT_FAIL(Iterator
0557               , subrule_used_outside_subrule_group, (id_type));
0558 
0559             return false;
0560         }
0561 
0562         template <typename Iterator, typename Group
0563           , typename Attributes, typename Locals
0564           , typename Skipper, typename Attribute
0565           , typename Params>
0566         bool parse(Iterator& first, Iterator const& last
0567           , subrule_context<Group, Attributes, Locals>& context
0568           , Skipper const& skipper, Attribute& attr
0569           , Params const& params) const
0570         {
0571             return context.group.template parse_subrule_id<ID_>(
0572                 first, last, context, skipper, attr, params);
0573         }
0574 
0575         template <typename Iterator, typename Context
0576           , typename Skipper, typename Attribute
0577           , typename Params>
0578         bool parse(Iterator& /*first*/, Iterator const& /*last*/
0579           , Context& /*context*/
0580           , Skipper const& /*skipper*/, Attribute& /*attr*/
0581           , Params const& /*params*/) const
0582         {
0583             // If you are seeing a compilation error here, you are trying
0584             // to use a subrule as a parser outside of a subrule group.
0585             BOOST_SPIRIT_ASSERT_FAIL(Iterator
0586               , subrule_used_outside_subrule_group, (id_type));
0587 
0588             return false;
0589         }
0590 
0591         template <typename Context>
0592         info what(Context& /*context*/) const
0593         {
0594             return info(name_);
0595         }
0596 
0597         // bring in the operator() overloads
0598         this_type const& get_parameterized_subject() const { return *this; }
0599         typedef this_type parameterized_subject_type;
0600         #include <boost/spirit/home/qi/nonterminal/detail/fcall.hpp>
0601 
0602         std::string name_;
0603     };
0604 }}}}
0605 
0606 #if defined(BOOST_MSVC)
0607 # pragma warning(pop)
0608 #endif
0609 
0610 #endif