/*============================================================================= Copyright (c) 1998-2003 Joel de Guzman http://spirit.sourceforge.net/ 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_HPP) #define BOOST_SPIRIT_RULE_HPP #include /////////////////////////////////////////////////////////////////////////////// // // Spirit predefined maximum number of simultaneously usable different // scanner types. // // This limit defines the maximum number of of possible different scanner // types for which a specific rule<> may be used. If this isn't defined, a // rule<> may be used with one scanner type only (multiple scanner support // is disabled). // /////////////////////////////////////////////////////////////////////////////// #if !defined(BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT) # define BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT 1 #endif // Ensure a meaningful maximum number of simultaneously usable scanner types BOOST_STATIC_ASSERT(BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 0); #include #include #include #if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1 # include #endif /////////////////////////////////////////////////////////////////////////////// namespace boost { namespace spirit { BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN #if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1 /////////////////////////////////////////////////////////////////////////// // // scanner_list (a fake scanner) // // Typically, rules are tied to a specific scanner type and // a particular rule cannot be used with anything else. Sometimes // there's a need for rules that can accept more than one scanner // type. The scanner_list can be used as a template // parameter to the rule class to specify up to the number of // scanner types defined by the BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT // constant. Example: // // rule > r; // // *** This feature is available only to compilers that support // partial template specialization. *** // /////////////////////////////////////////////////////////////////////////// template < BOOST_PP_ENUM_PARAMS( BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT, typename ScannerT ) > struct scanner_list : scanner_base {}; #endif /////////////////////////////////////////////////////////////////////////// // // rule class // // The rule is a polymorphic parser that acts as a named place- // holder capturing the behavior of an EBNF expression assigned to // it. // // The rule is a template class parameterized by: // // 1) scanner (scanner_t, see scanner.hpp), // 2) the rule's context (context_t, see parser_context.hpp) // 3) an arbitrary tag (tag_t, see parser_id.hpp) that allows // a rule to be tagged for identification. // // These template parameters may be specified in any order. The // scanner will default to scanner<> when it is not specified. // The context will default to parser_context when not specified. // The tag will default to parser_address_tag when not specified. // // The definition of the rule (its right hand side, RHS) held by // the rule through a scoped_ptr. When a rule is seen in the RHS // of an assignment or copy construction EBNF expression, the rule // is held by the LHS rule by reference. // /////////////////////////////////////////////////////////////////////////// template < typename T0 = nil_t , typename T1 = nil_t , typename T2 = nil_t > class rule : public impl::rule_base< rule , rule const& , T0, T1, T2> { public: typedef rule self_t; typedef impl::rule_base< self_t , self_t const& , T0, T1, T2> base_t; typedef typename base_t::scanner_t scanner_t; typedef typename base_t::attr_t attr_t; typedef impl::abstract_parser abstract_parser_t; rule() : ptr() {} ~rule() {} rule(rule const& r) : ptr(new impl::concrete_parser(r)) {} template rule(ParserT const& p) : ptr(new impl::concrete_parser(p)) {} template rule& operator=(ParserT const& p) { ptr.reset(new impl::concrete_parser(p)); return *this; } rule& operator=(rule const& r) { ptr.reset(new impl::concrete_parser(r)); return *this; } rule copy() const { return rule(ptr.get() ? ptr->clone() : 0); } private: friend class impl::rule_base_access; abstract_parser_t* get() const { return ptr.get(); } rule(abstract_parser_t* ptr_) : ptr(ptr_) {} rule(abstract_parser_t const* ptr_) : ptr(ptr_) {} scoped_ptr ptr; }; BOOST_SPIRIT_CLASSIC_NAMESPACE_END }} // namespace BOOST_SPIRIT_CLASSIC_NS #endif