Line data Source code
1 : /*============================================================================= 2 : Copyright (c) 1998-2003 Joel de Guzman 3 : http://spirit.sourceforge.net/ 4 : 5 : Distributed under the Boost Software License, Version 1.0. (See accompanying 6 : file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 : =============================================================================*/ 8 : #if !defined(BOOST_SPIRIT_RULE_HPP) 9 : #define BOOST_SPIRIT_RULE_HPP 10 : 11 : #include <boost/static_assert.hpp> 12 : 13 : /////////////////////////////////////////////////////////////////////////////// 14 : // 15 : // Spirit predefined maximum number of simultaneously usable different 16 : // scanner types. 17 : // 18 : // This limit defines the maximum number of possible different scanner 19 : // types for which a specific rule<> may be used. If this isn't defined, a 20 : // rule<> may be used with one scanner type only (multiple scanner support 21 : // is disabled). 22 : // 23 : /////////////////////////////////////////////////////////////////////////////// 24 : #if !defined(BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT) 25 : # define BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT 1 26 : #endif 27 : 28 : // Ensure a meaningful maximum number of simultaneously usable scanner types 29 : BOOST_STATIC_ASSERT(BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 0); 30 : 31 : #include <boost/scoped_ptr.hpp> 32 : #include <boost/spirit/home/classic/namespace.hpp> 33 : #include <boost/spirit/home/classic/core/non_terminal/impl/rule.ipp> 34 : 35 : #if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1 36 : # include <boost/preprocessor/enum_params.hpp> 37 : #endif 38 : 39 : /////////////////////////////////////////////////////////////////////////////// 40 : namespace boost { namespace spirit { 41 : 42 : BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN 43 : 44 : #if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1 45 : 46 : /////////////////////////////////////////////////////////////////////////// 47 : // 48 : // scanner_list (a fake scanner) 49 : // 50 : // Typically, rules are tied to a specific scanner type and 51 : // a particular rule cannot be used with anything else. Sometimes 52 : // there's a need for rules that can accept more than one scanner 53 : // type. The scanner_list<S0, ...SN> can be used as a template 54 : // parameter to the rule class to specify up to the number of 55 : // scanner types defined by the BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT 56 : // constant. Example: 57 : // 58 : // rule<scanner_list<ScannerT0, ScannerT1> > r; 59 : // 60 : // *** This feature is available only to compilers that support 61 : // partial template specialization. *** 62 : // 63 : /////////////////////////////////////////////////////////////////////////// 64 : template < 65 : BOOST_PP_ENUM_PARAMS( 66 : BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT, 67 : typename ScannerT 68 : ) 69 : > 70 : struct scanner_list : scanner_base {}; 71 : 72 : #endif 73 : 74 : /////////////////////////////////////////////////////////////////////////// 75 : // 76 : // rule class 77 : // 78 : // The rule is a polymorphic parser that acts as a named place- 79 : // holder capturing the behavior of an EBNF expression assigned to 80 : // it. 81 : // 82 : // The rule is a template class parameterized by: 83 : // 84 : // 1) scanner (scanner_t, see scanner.hpp), 85 : // 2) the rule's context (context_t, see parser_context.hpp) 86 : // 3) an arbitrary tag (tag_t, see parser_id.hpp) that allows 87 : // a rule to be tagged for identification. 88 : // 89 : // These template parameters may be specified in any order. The 90 : // scanner will default to scanner<> when it is not specified. 91 : // The context will default to parser_context when not specified. 92 : // The tag will default to parser_address_tag when not specified. 93 : // 94 : // The definition of the rule (its right hand side, RHS) held by 95 : // the rule through a scoped_ptr. When a rule is seen in the RHS 96 : // of an assignment or copy construction EBNF expression, the rule 97 : // is held by the LHS rule by reference. 98 : // 99 : /////////////////////////////////////////////////////////////////////////// 100 : template < 101 : typename T0 = nil_t 102 : , typename T1 = nil_t 103 : , typename T2 = nil_t 104 : > 105 : class rule 106 : : public impl::rule_base< 107 : rule<T0, T1, T2> 108 : , rule<T0, T1, T2> const& 109 : , T0, T1, T2> 110 : { 111 : public: 112 : 113 : typedef rule<T0, T1, T2> self_t; 114 : typedef impl::rule_base< 115 : self_t 116 : , self_t const& 117 : , T0, T1, T2> 118 : base_t; 119 : 120 : typedef typename base_t::scanner_t scanner_t; 121 : typedef typename base_t::attr_t attr_t; 122 : typedef impl::abstract_parser<scanner_t, attr_t> abstract_parser_t; 123 : 124 0 : rule() : ptr() {} 125 0 : ~rule() {} 126 : 127 : rule(rule const& r) 128 : : ptr(new impl::concrete_parser<rule, scanner_t, attr_t>(r)) {} 129 : 130 : template <typename ParserT> 131 : rule(ParserT const& p) 132 : : ptr(new impl::concrete_parser<ParserT, scanner_t, attr_t>(p)) {} 133 : 134 : template <typename ParserT> 135 0 : rule& operator=(ParserT const& p) 136 : { 137 0 : ptr.reset(new impl::concrete_parser<ParserT, scanner_t, attr_t>(p)); 138 0 : return *this; 139 : } 140 : 141 : rule& operator=(rule const& r) 142 : { 143 : ptr.reset(new impl::concrete_parser<rule, scanner_t, attr_t>(r)); 144 : return *this; 145 : } 146 : 147 : rule<T0, T1, T2> 148 : copy() const 149 : { 150 : return rule<T0, T1, T2>(ptr.get() ? ptr->clone() : 0); 151 : } 152 : 153 : private: 154 : friend class impl::rule_base_access; 155 : 156 : abstract_parser_t* 157 0 : get() const 158 : { 159 0 : return ptr.get(); 160 : } 161 : 162 : rule(abstract_parser_t* ptr_) 163 : : ptr(ptr_) {} 164 : 165 : rule(abstract_parser_t const* ptr_) 166 : : ptr(ptr_) {} 167 : 168 : scoped_ptr<abstract_parser_t> ptr; 169 : }; 170 : 171 : BOOST_SPIRIT_CLASSIC_NAMESPACE_END 172 : 173 : }} // namespace BOOST_SPIRIT_CLASSIC_NS 174 : 175 : #endif