]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | rule() : ptr() {} | |
125 | ~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 | rule& operator=(ParserT const& p) | |
136 | { | |
137 | ptr.reset(new impl::concrete_parser<ParserT, scanner_t, attr_t>(p)); | |
138 | 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 | get() const | |
158 | { | |
159 | 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 |