/*============================================================================= Copyright (c) 2001-2007 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_FEB_12_2007_1020AM) #define BOOST_SPIRIT_RULE_FEB_12_2007_1020AM #include #include #include #include #include #include #include #include #include #if defined(BOOST_MSVC) # pragma warning(push) # pragma warning(disable: 4355) // 'this' : used in base member initializer list warning #endif namespace boost { namespace spirit { namespace qi { namespace detail { struct rule_decorator; } template < typename Iterator , typename T0 = unused_type , typename T1 = unused_type , typename T2 = unused_type > struct rule : make_nonterminal, T0, T1, T2>::type { typedef make_nonterminal, T0, T1, T2> make_nonterminal_; typedef typename make_nonterminal_::skipper_type skipper_type; typedef typename make_nonterminal_::type base_type; typedef Iterator iterator_type; typedef rule self_type; typedef virtual_component_base< Iterator , typename base_type::context_type , skipper_type > virtual_component; typedef intrusive_ptr pointer_type; rule(std::string const& name_ = std::string()) : name_(name_) {} ~rule() {} rule(rule const& rhs) : ptr(rhs.ptr) , name_(rhs.name_) { } rule& operator=(rule const& rhs) { ptr = rhs.ptr; name_ = rhs.name_; return *this; } template rule& operator=(Expr const& xpr) { typedef spirit::traits::is_component is_component; // report invalid expression error as early as possible // BOOST_MPL_ASSERT_MSG( // is_component::value, // xpr_is_not_convertible_to_a_parser, ()); // temp workaround for mpl problem BOOST_STATIC_ASSERT(is_component::value); define(xpr, mpl::false_()); return *this; } template friend rule& operator%=(rule& r, Expr const& xpr) { typedef spirit::traits::is_component is_component; // report invalid expression error as early as possible //~ BOOST_MPL_ASSERT_MSG( //~ is_component::value, //~ xpr_is_not_convertible_to_a_parser, ()); // temp workaround for mpl problem BOOST_STATIC_ASSERT(is_component::value); r.define(xpr, mpl::true_()); return r; } self_type alias() const { self_type result; result.define(*this, mpl::false_()); return result; } typename make_nonterminal_holder< nonterminal_object , self_type >::type copy() const { typename make_nonterminal_holder< nonterminal_object , self_type >::type result = {{*this}}; return result; } std::string const& name() const { return name_; } void name(std::string const& str) { name_ = str; } private: template friend struct grammar; friend struct detail::rule_decorator; template void define(Expr const& xpr, Auto) { typedef typename result_of::as_component::type component; typedef detail::virtual_component< Iterator , component , typename base_type::context_type , skipper_type , Auto > virtual_component; ptr = new virtual_component(spirit::as_component(qi::domain(), xpr)); } template bool parse( Iterator_& first, Iterator_ const& last , Context& context, Skipper const& skipper) const { // If the following line produces a compilation error stating the // 4th parameter is not convertible to the expected type, then you // are probably trying to use this rule instance with a skipper // which is not compatible with the skipper type used while // defining the type of this rule instance. return ptr->parse(first, last, context, skipper); } std::string what() const { if (name_.empty()) { if (ptr) { return "unnamed-rule"; } else { return "empty-rule"; } } else { return name_; } } friend struct nonterminal_director; pointer_type ptr; std::string name_; }; // Decoration support: create a new virtual component and link it as // first element in the chain of virtual components associated with this // rule. Returns the previous topmost virtual component in the chain. // We provide support from 1 to 5 arguments. namespace detail { struct rule_decorator { template typename Rule::pointer_type static call(Rule& r, A1 const& a1) { typename Rule::pointer_type old (r.ptr); r.ptr.reset(new Decorator(r.ptr, a1)); return old; } template typename Rule::pointer_type static call(Rule& r, A1 const& a1, A2 const& a2) { typename Rule::pointer_type old (r.ptr); r.ptr.reset(new Decorator(r.ptr, a1, a2)); return old; } template typename Rule::pointer_type static call(Rule& r , A1 const& a1, A2 const& a2, A3 const& a3) { typename Rule::pointer_type old (r.ptr); r.ptr.reset(new Decorator(r.ptr, a1, a2, a3)); return old; } template typename Rule::pointer_type static call(Rule& r , A1 const& a1, A2 const& a2 , A3 const& a3, A4 const& a4) { typename Rule::pointer_type old (r.ptr); r.ptr.reset(new Decorator(r.ptr, a1, a2, a3, a4)); return old; } template typename Rule::pointer_type static call(Rule& r , A1 const& a1, A2 const& a2 , A3 const& a3, A4 const& a4, A5 const& a5) { typename Rule::pointer_type old (r.ptr); r.ptr.reset(new Decorator(r.ptr, a1, a2, a3, a4, a5)); return old; } }; } template typename rule::pointer_type decorate(rule& r , A1 const& a1) { return detail::rule_decorator:: template call(r, a1); } template typename rule::pointer_type decorate(rule& r , A1 const& a1, A2 const& a2) { return detail::rule_decorator:: template call(r, a1, a2); } template typename rule::pointer_type decorate(rule& r , A1 const& a1, A2 const& a2, A3 const& a3) { return detail::rule_decorator:: template call(r, a1, a2, a3); } template typename rule::pointer_type decorate(rule& r , A1 const& a1, A2 const& a2 , A3 const& a3, A4 const& a4) { return detail::rule_decorator:: template call(r, a1, a2, a3, a4); } template typename rule::pointer_type decorate(rule& r , A1 const& a1, A2 const& a2 , A3 const& a3, A4 const& a4, A5 const& a5) { return detail::rule_decorator:: template call(r, a1, a2, a3, a4, a5); } // Error handling support template < error_handler_result action , typename Iterator, typename T0, typename T1, typename T2 , typename F> void on_error(rule& r, F f) { typedef rule rule_type; typedef detail::error_handler< Iterator , typename rule_type::base_type::context_type , typename rule_type::skipper_type , F , action> error_handler; decorate(r, f); } // Error handling support when is not // specified. We will default to . template void on_error(rule& r, F f) { on_error(r, f); } }}} #if defined(BOOST_MSVC) # pragma warning(pop) #endif #endif