diff options
Diffstat (limited to 'boost/spirit/repository/home/qi/nonterminal/subrule.hpp')
-rw-r--r-- | boost/spirit/repository/home/qi/nonterminal/subrule.hpp | 166 |
1 files changed, 95 insertions, 71 deletions
diff --git a/boost/spirit/repository/home/qi/nonterminal/subrule.hpp b/boost/spirit/repository/home/qi/nonterminal/subrule.hpp index 4a29f44e65..23892e0dcf 100644 --- a/boost/spirit/repository/home/qi/nonterminal/subrule.hpp +++ b/boost/spirit/repository/home/qi/nonterminal/subrule.hpp @@ -54,46 +54,22 @@ namespace boost { namespace spirit { namespace repository { namespace qi { /////////////////////////////////////////////////////////////////////////// - // subrule_group: + // subrule_group_parser: // - parser representing a group of subrule definitions (one or more), // invokes first subrule on entry, - // - also a Proto terminal, so that a group behaves like any Spirit - // expression. /////////////////////////////////////////////////////////////////////////// template <typename Defs> - struct subrule_group - : proto::extends< - typename proto::terminal< - spirit::qi::reference<subrule_group<Defs> const> - >::type - , subrule_group<Defs> - > - , spirit::qi::parser<subrule_group<Defs> > + struct subrule_group_parser + : spirit::qi::parser<subrule_group_parser<Defs> > { // Fusion associative sequence, associating each subrule ID in this // group (as an MPL integral constant) with its definition typedef Defs defs_type; - typedef subrule_group<Defs> this_type; - typedef spirit::qi::reference<this_type const> reference_; - typedef typename proto::terminal<reference_>::type terminal; - typedef proto::extends<terminal, this_type> base_type; - - static size_t const params_size = - // Forward to first subrule. - remove_reference< - typename fusion::result_of::front<Defs>::type - >::type::second_type::params_size; + typedef subrule_group_parser<Defs> this_type; - subrule_group(subrule_group const& rhs) - : base_type(terminal::make(reference_(*this))) - , defs(rhs.defs) - { - } - - explicit subrule_group(Defs const& defs) - : base_type(terminal::make(reference_(*this))) - , defs(defs) + explicit subrule_group_parser(Defs const& defs) + : defs(defs) { } @@ -287,6 +263,41 @@ namespace boost { namespace spirit { namespace repository { namespace qi return fusion::front(defs).second.binder.p.what(context); } + Defs defs; + }; + + /////////////////////////////////////////////////////////////////////////// + // subrule_group: + // - a Proto terminal, so that a group behaves like any Spirit + // expression. + /////////////////////////////////////////////////////////////////////////// + template <typename Defs> + struct subrule_group + : proto::extends< + typename proto::terminal< + subrule_group_parser<Defs> + >::type + , subrule_group<Defs> + > + { + typedef subrule_group_parser<Defs> parser_type; + typedef typename proto::terminal<parser_type>::type terminal; + + static size_t const params_size = + // Forward to first subrule. + remove_reference< + typename fusion::result_of::front<Defs>::type + >::type::second_type::params_size; + + explicit subrule_group(Defs const& defs) + : subrule_group::proto_extends(terminal::make(parser_type(defs))) + { + } + + parser_type const& parser() const { return proto::value(*this); } + + Defs const& defs() const { return parser().defs; } + template <typename Defs2> subrule_group< typename fusion::result_of::as_map< @@ -298,15 +309,29 @@ namespace boost { namespace spirit { namespace repository { namespace qi typename fusion::result_of::as_map< typename fusion::result_of::join< Defs const, Defs2 const>::type>::type> result_type; - return result_type(fusion::as_map(fusion::join(defs, other.defs))); + return result_type(fusion::as_map(fusion::join(defs(), other.defs()))); + } + + // non-const versions needed to suppress proto's comma op kicking in + template <typename Defs2> + friend subrule_group< + typename fusion::result_of::as_map< + typename fusion::result_of::join< + Defs const, Defs2 const>::type>::type> +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + operator,(subrule_group&& left, subrule_group<Defs2>&& other) +#else + operator,(subrule_group& left, subrule_group<Defs2>& other) +#endif + { + return static_cast<subrule_group const&>(left) + .operator,(static_cast<subrule_group<Defs2> const&>(other)); } // bring in the operator() overloads - this_type const& get_parameterized_subject() const { return *this; } - typedef this_type parameterized_subject_type; + parser_type const& get_parameterized_subject() const { return parser(); } + typedef parser_type parameterized_subject_type; #include <boost/spirit/home/qi/nonterminal/detail/fcall.hpp> - - Defs defs; }; /////////////////////////////////////////////////////////////////////////// @@ -378,13 +403,20 @@ namespace boost { namespace spirit { namespace repository { namespace qi typedef mpl::vector<T1, T2> template_params; - // locals_type is a sequence of types to be used as local variables + // The subrule's locals_type: a sequence of types to be used as local variables typedef typename spirit::detail::extract_locals<template_params>::type locals_type; + // The subrule's encoding type typedef typename - spirit::detail::extract_sig<template_params>::type + spirit::detail::extract_encoding<template_params>::type + encoding_type; + + // The subrule's signature + typedef typename + spirit::detail::extract_sig<template_params, encoding_type + , spirit::qi::domain>::type sig_type; // This is the subrule's attribute type @@ -461,42 +493,34 @@ namespace boost { namespace spirit { namespace repository { namespace qi def_type(compile<spirit::qi::domain>(expr), name_))); } - template <typename Expr> - friend typename group_type_helper<Expr, true>::type - operator%=(subrule const& sr, Expr const& expr) - { - typedef group_type_helper<Expr, true> helper; - typedef typename helper::def_type def_type; - typedef typename helper::type result_type; - return result_type(fusion::make_map<id_type>( - def_type(compile<spirit::qi::domain>(expr), sr.name_))); - } +#define SUBRULE_MODULUS_ASSIGN_OPERATOR(lhs_ref, rhs_ref) \ + template <typename Expr> \ + friend typename group_type_helper<Expr, true>::type \ + operator%=(subrule lhs_ref sr, Expr rhs_ref expr) \ + { \ + typedef group_type_helper<Expr, true> helper; \ + typedef typename helper::def_type def_type; \ + typedef typename helper::type result_type; \ + return result_type(fusion::make_map<id_type>( \ + def_type(compile<spirit::qi::domain>(expr), sr.name_))); \ + } \ + /**/ // non-const versions needed to suppress proto's %= kicking in - template <typename Expr> - friend typename group_type_helper<Expr, true>::type - operator%=(subrule const& sr, Expr& expr) - { - return operator%=( - sr - , static_cast<Expr const&>(expr)); - } - template <typename Expr> - friend typename group_type_helper<Expr, true>::type - operator%=(subrule& sr, Expr const& expr) - { - return operator%=( - static_cast<subrule const&>(sr) - , expr); - } - template <typename Expr> - friend typename group_type_helper<Expr, true>::type - operator%=(subrule& sr, Expr& expr) - { - return operator%=( - static_cast<subrule const&>(sr) - , static_cast<Expr const&>(expr)); - } + SUBRULE_MODULUS_ASSIGN_OPERATOR(const&, const&) +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + SUBRULE_MODULUS_ASSIGN_OPERATOR(const&, &&) +#else + SUBRULE_MODULUS_ASSIGN_OPERATOR(const&, &) +#endif + SUBRULE_MODULUS_ASSIGN_OPERATOR(&, const&) +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + SUBRULE_MODULUS_ASSIGN_OPERATOR(&, &&) +#else + SUBRULE_MODULUS_ASSIGN_OPERATOR(&, &) +#endif + +#undef SUBRULE_MODULUS_ASSIGN_OPERATOR std::string const& name() const { |