EVOLUTION-MANAGER
Edit File: rule.hpp
/*============================================================================= Copyright (c) 2001-2011 Joel de Guzman Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ #if !defined(BOOST_SPIRIT_RULE_FEBRUARY_12_2007_1020AM) #define BOOST_SPIRIT_RULE_FEBRUARY_12_2007_1020AM #if defined(_MSC_VER) #pragma once #endif #include <boost/assert.hpp> #include <boost/static_assert.hpp> #include <boost/config.hpp> #include <boost/function.hpp> #include <boost/mpl/vector.hpp> #include <boost/type_traits/add_reference.hpp> #include <boost/type_traits/is_convertible.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/fusion/include/vector.hpp> #include <boost/fusion/include/size.hpp> #include <boost/fusion/include/make_vector.hpp> #include <boost/fusion/include/cons.hpp> #include <boost/fusion/include/as_list.hpp> #include <boost/fusion/include/as_vector.hpp> #include <boost/spirit/home/support/unused.hpp> #include <boost/spirit/home/support/argument.hpp> #include <boost/spirit/home/support/context.hpp> #include <boost/spirit/home/support/info.hpp> #include <boost/spirit/home/qi/detail/attributes.hpp> #include <boost/spirit/home/support/nonterminal/extract_param.hpp> #include <boost/spirit/home/support/nonterminal/locals.hpp> #include <boost/spirit/home/qi/reference.hpp> #include <boost/spirit/home/qi/nonterminal/detail/parameterized.hpp> #include <boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp> #include <boost/spirit/home/qi/nonterminal/nonterminal_fwd.hpp> #include <boost/spirit/home/qi/skip_over.hpp> #if defined(BOOST_MSVC) # pragma warning(push) # pragma warning(disable: 4355) // 'this' : used in base member initializer list warning # pragma warning(disable: 4127) // conditional expression is constant #endif namespace boost { namespace spirit { namespace qi { BOOST_PP_REPEAT(SPIRIT_ATTRIBUTES_LIMIT, SPIRIT_USING_ATTRIBUTE, _) using spirit::_pass_type; using spirit::_val_type; using spirit::_a_type; using spirit::_b_type; using spirit::_c_type; using spirit::_d_type; using spirit::_e_type; using spirit::_f_type; using spirit::_g_type; using spirit::_h_type; using spirit::_i_type; using spirit::_j_type; #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS using spirit::_pass; using spirit::_val; using spirit::_a; using spirit::_b; using spirit::_c; using spirit::_d; using spirit::_e; using spirit::_f; using spirit::_g; using spirit::_h; using spirit::_i; using spirit::_j; #endif using spirit::info; using spirit::locals; template < typename Iterator, typename T1, typename T2, typename T3 , typename T4> struct rule : proto::extends< typename proto::terminal< reference<rule<Iterator, T1, T2, T3, T4> const> >::type , rule<Iterator, T1, T2, T3, T4> > , parser<rule<Iterator, T1, T2, T3, T4> > { typedef Iterator iterator_type; typedef rule<Iterator, T1, T2, T3, T4> this_type; typedef reference<this_type const> reference_; typedef typename proto::terminal<reference_>::type terminal; typedef proto::extends<terminal, this_type> base_type; typedef mpl::vector<T1, T2, T3, T4> template_params; // The rule'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 rule's skip-parser type typedef typename spirit::detail::extract_component< qi::domain, template_params>::type skipper_type; // The rule's encoding type typedef typename spirit::detail::extract_encoding<template_params>::type encoding_type; // The rule's signature typedef typename spirit::detail::extract_sig<template_params, encoding_type, qi::domain>::type sig_type; // This is the rule's attribute type typedef typename spirit::detail::attr_from_sig<sig_type>::type attr_type; typedef typename add_reference<attr_type>::type attr_reference_type; // parameter_types is a sequence of types passed as parameters to the rule typedef typename spirit::detail::params_from_sig<sig_type>::type parameter_types; static size_t const params_size = fusion::result_of::size<parameter_types>::type::value; typedef context< fusion::cons<attr_reference_type, parameter_types> , locals_type> context_type; typedef function< bool(Iterator& first, Iterator const& last , context_type& context , skipper_type const& skipper )> function_type; typedef typename mpl::if_< is_same<encoding_type, unused_type> , unused_type , tag::char_code<tag::encoding, encoding_type> >::type encoding_modifier_type; explicit rule(std::string const& name = "unnamed-rule") : base_type(terminal::make(reference_(*this))) , name_(name) { } rule(rule const& rhs) : base_type(terminal::make(reference_(*this))) , name_(rhs.name_) , f(rhs.f) { } template <typename Auto, typename Expr> static void define(rule& /*lhs*/, Expr const& /*expr*/, mpl::false_) { // Report invalid expression error as early as possible. // If you got an error_invalid_expression error message here, // then the expression (expr) is not a valid spirit qi expression. BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr); } template <typename Auto, typename Expr> static void define(rule& lhs, Expr const& expr, mpl::true_) { lhs.f = detail::bind_parser<Auto>( compile<qi::domain>(expr, encoding_modifier_type())); } template <typename Expr> rule(Expr const& expr, std::string const& name = "unnamed-rule") : base_type(terminal::make(reference_(*this))) , name_(name) { define<mpl::false_>(*this, expr, traits::matches<qi::domain, Expr>()); } rule& operator=(rule const& rhs) { // The following assertion fires when you try to initialize a rule // from an uninitialized one. Did you mean to refer to the right // hand side rule instead of assigning from it? In this case you // should write lhs = rhs.alias(); BOOST_ASSERT(rhs.f && "Did you mean rhs.alias() instead of rhs?"); f = rhs.f; name_ = rhs.name_; return *this; } std::string const& name() const { return name_; } void name(std::string const& str) { name_ = str; } template <typename Expr> rule& operator=(Expr const& expr) { define<mpl::false_>(*this, expr, traits::matches<qi::domain, Expr>()); return *this; } // VC7.1 has problems to resolve 'rule' without explicit template parameters #if !BOOST_WORKAROUND(BOOST_MSVC, < 1400) // g++ 3.3 barfs if this is a member function :( template <typename Expr> friend rule& operator%=(rule& r, Expr const& expr) { define<mpl::true_>(r, expr, traits::matches<qi::domain, Expr>()); return r; } #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) // non-const version needed to suppress proto's %= kicking in template <typename Expr> friend rule& operator%=(rule& r, Expr& expr) { return r %= static_cast<Expr const&>(expr); } #else // for rvalue references template <typename Expr> friend rule& operator%=(rule& r, Expr&& expr) { define<mpl::true_>(r, expr, traits::matches<qi::domain, Expr>()); return r; } #endif #else // both friend functions have to be defined out of class as VC7.1 // will complain otherwise template <typename OutputIterator_, typename T1_, typename T2_ , typename T3_, typename T4_, typename Expr> friend rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=( rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr const& expr); // non-const version needed to suppress proto's %= kicking in template <typename OutputIterator_, typename T1_, typename T2_ , typename T3_, typename T4_, typename Expr> friend rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=( rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr& expr); #endif template <typename Context, typename Iterator_> struct attribute { typedef attr_type type; }; template <typename Context, typename Skipper, typename Attribute> bool parse(Iterator& first, Iterator const& last , Context& /*context*/, Skipper const& skipper , Attribute& attr_param) const { BOOST_STATIC_ASSERT_MSG((is_same<skipper_type, unused_type>::value || !is_same<Skipper, unused_type>::value), "The rule was instantiated with a skipper type but you have not pass any. " "Did you use `parse` instead of `phrase_parse`?"); BOOST_STATIC_ASSERT_MSG( (is_convertible<Skipper const&, skipper_type>::value), "The passed skipper is not compatible/convertible to one " "that the rule was instantiated with"); if (f) { // do a preskip if this is an implied lexeme if (is_same<skipper_type, unused_type>::value) qi::skip_over(first, last, skipper); // do down-stream transformation, provides attribute for // rhs parser typedef traits::transform_attribute< Attribute, attr_type, domain> transform; typename transform::type attr_ = transform::pre(attr_param); // If you are seeing a compilation error here, you are probably // trying to use a rule or a grammar which has inherited // attributes, without passing values for them. context_type context(attr_); // If you are seeing a compilation error here stating that the // fourth parameter can't be converted to a required target type // then you are probably trying to use a rule or a grammar with // an incompatible skipper type. if (f(first, last, context, skipper)) { // do up-stream transformation, this integrates the results // back into the original attribute value, if appropriate transform::post(attr_param, attr_); return true; } // inform attribute transformation of failed rhs transform::fail(attr_param); } return false; } template <typename Context, typename Skipper , typename Attribute, typename Params> bool parse(Iterator& first, Iterator const& last , Context& caller_context, Skipper const& skipper , Attribute& attr_param, Params const& params) const { BOOST_STATIC_ASSERT_MSG((is_same<skipper_type, unused_type>::value || !is_same<Skipper, unused_type>::value), "The rule was instantiated with a skipper type but you have not pass any. " "Did you use `parse` instead of `phrase_parse`?"); BOOST_STATIC_ASSERT_MSG( (is_convertible<Skipper const&, skipper_type>::value), "The passed skipper is not compatible/convertible to one " "that the rule was instantiated with"); if (f) { // do a preskip if this is an implied lexeme if (is_same<skipper_type, unused_type>::value) qi::skip_over(first, last, skipper); // do down-stream transformation, provides attribute for // rhs parser typedef traits::transform_attribute< Attribute, attr_type, domain> transform; typename transform::type attr_ = transform::pre(attr_param); // If you are seeing a compilation error here, you are probably // trying to use a rule or a grammar which has inherited // attributes, passing values of incompatible types for them. context_type context(attr_, params, caller_context); // If you are seeing a compilation error here stating that the // fourth parameter can't be converted to a required target type // then you are probably trying to use a rule or a grammar with // an incompatible skipper type. if (f(first, last, context, skipper)) { // do up-stream transformation, this integrates the results // back into the original attribute value, if appropriate transform::post(attr_param, attr_); return true; } // inform attribute transformation of failed rhs transform::fail(attr_param); } return false; } template <typename Context> info what(Context& /*context*/) const { return info(name_); } reference_ alias() const { return reference_(*this); } typename proto::terminal<this_type>::type copy() const { typename proto::terminal<this_type>::type result = {*this}; return result; } // bring in the operator() overloads rule const& get_parameterized_subject() const { return *this; } typedef rule parameterized_subject_type; #include <boost/spirit/home/qi/nonterminal/detail/fcall.hpp> std::string name_; function_type f; }; #if BOOST_WORKAROUND(BOOST_MSVC, < 1400) template <typename OutputIterator_, typename T1_, typename T2_ , typename T3_, typename T4_, typename Expr> rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=( rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr const& expr) { // Report invalid expression error as early as possible. // If you got an error_invalid_expression error message here, // then the expression (expr) is not a valid spirit qi expression. BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr); typedef typename rule<OutputIterator_, T1_, T2_, T3_, T4_>::encoding_modifier_type encoding_modifier_type; r.f = detail::bind_parser<mpl::true_>( compile<qi::domain>(expr, encoding_modifier_type())); return r; } template <typename Iterator_, typename T1_, typename T2_ , typename T3_, typename T4_, typename Expr> rule<Iterator_, T1_, T2_, T3_, T4_>& operator%=( rule<Iterator_, T1_, T2_, T3_, T4_>& r, Expr& expr) { return r %= static_cast<Expr const&>(expr); } #endif }}} namespace boost { namespace spirit { namespace traits { /////////////////////////////////////////////////////////////////////////// template < typename IteratorA, typename IteratorB, typename Attribute , typename Context, typename T1, typename T2, typename T3, typename T4> struct handles_container< qi::rule<IteratorA, T1, T2, T3, T4>, Attribute, Context, IteratorB> : traits::is_container< typename attribute_of< qi::rule<IteratorA, T1, T2, T3, T4>, Context, IteratorB >::type > {}; }}} #if defined(BOOST_MSVC) # pragma warning(pop) #endif #endif