]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Copyright (c) 2001-2003 Joel de Guzman | |
3 | Copyright (c) 2002-2003 Martin Wille | |
4 | Copyright (c) 2003 Hartmut Kaiser | |
5 | http://spirit.sourceforge.net/ | |
6 | ||
7 | Use, modification and distribution is subject to the Boost Software | |
8 | License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
9 | http://www.boost.org/LICENSE_1_0.txt) | |
10 | =============================================================================*/ | |
11 | #if !defined BOOST_SPIRIT_GRAMMAR_IPP | |
12 | #define BOOST_SPIRIT_GRAMMAR_IPP | |
13 | ||
14 | #if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) | |
15 | #include <boost/spirit/home/classic/core/non_terminal/impl/object_with_id.ipp> | |
16 | #include <algorithm> | |
17 | #include <functional> | |
18 | #include <memory> // for std::auto_ptr | |
19 | #include <boost/weak_ptr.hpp> | |
20 | #endif | |
21 | ||
22 | #ifdef BOOST_SPIRIT_THREADSAFE | |
23 | #include <boost/spirit/home/classic/core/non_terminal/impl/static.hpp> | |
24 | #include <boost/thread/tss.hpp> | |
25 | #include <boost/thread/mutex.hpp> | |
26 | #include <boost/thread/lock_types.hpp> | |
27 | #endif | |
28 | ||
29 | /////////////////////////////////////////////////////////////////////////////// | |
30 | namespace boost { namespace spirit { | |
31 | ||
32 | BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN | |
33 | ||
34 | template <typename DerivedT, typename ContextT> | |
35 | struct grammar; | |
36 | ||
37 | ||
38 | ////////////////////////////////// | |
39 | template <typename GrammarT, typename ScannerT> | |
40 | struct grammar_definition | |
41 | { | |
42 | typedef typename GrammarT::template definition<ScannerT> type; | |
43 | }; | |
44 | ||
45 | ||
46 | namespace impl | |
47 | { | |
48 | ||
49 | #if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) | |
50 | struct grammar_tag {}; | |
51 | ||
52 | ////////////////////////////////// | |
53 | template <typename GrammarT> | |
54 | struct grammar_helper_base | |
55 | { | |
56 | virtual int undefine(GrammarT *) = 0; | |
57 | virtual ~grammar_helper_base() {} | |
58 | }; | |
59 | ||
60 | ////////////////////////////////// | |
61 | template <typename GrammarT> | |
62 | struct grammar_helper_list | |
63 | { | |
64 | typedef GrammarT grammar_t; | |
65 | typedef grammar_helper_base<GrammarT> helper_t; | |
66 | typedef std::vector<helper_t*> vector_t; | |
67 | ||
68 | grammar_helper_list() {} | |
69 | grammar_helper_list(grammar_helper_list const& /*x*/) | |
70 | { // Does _not_ copy the helpers member ! | |
71 | } | |
72 | ||
73 | grammar_helper_list& operator=(grammar_helper_list const& x) | |
74 | { // Does _not_ copy the helpers member ! | |
75 | return *this; | |
76 | } | |
77 | ||
78 | void push_back(helper_t *helper) | |
79 | { helpers.push_back(helper); } | |
80 | ||
81 | void pop_back() | |
82 | { helpers.pop_back(); } | |
83 | ||
84 | typename vector_t::size_type | |
85 | size() const | |
86 | { return helpers.size(); } | |
87 | ||
88 | typename vector_t::reverse_iterator | |
89 | rbegin() | |
90 | { return helpers.rbegin(); } | |
91 | ||
92 | typename vector_t::reverse_iterator | |
93 | rend() | |
94 | { return helpers.rend(); } | |
95 | ||
96 | #ifdef BOOST_SPIRIT_THREADSAFE | |
97 | boost::mutex & mutex() | |
98 | { return m; } | |
99 | #endif | |
100 | ||
101 | private: | |
102 | ||
103 | vector_t helpers; | |
104 | #ifdef BOOST_SPIRIT_THREADSAFE | |
105 | boost::mutex m; | |
106 | #endif | |
107 | }; | |
108 | ||
109 | ////////////////////////////////// | |
110 | struct grammartract_helper_list; | |
111 | ||
112 | #if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) | |
113 | ||
114 | struct grammartract_helper_list | |
115 | { | |
116 | template<typename GrammarT> | |
117 | static grammar_helper_list<GrammarT>& | |
118 | do_(GrammarT const* g) | |
119 | { | |
120 | return g->helpers; | |
121 | } | |
122 | }; | |
123 | ||
124 | #endif | |
125 | ||
126 | ////////////////////////////////// | |
127 | template <typename GrammarT, typename DerivedT, typename ScannerT> | |
128 | struct grammar_helper : private grammar_helper_base<GrammarT> | |
129 | { | |
130 | typedef GrammarT grammar_t; | |
131 | typedef ScannerT scanner_t; | |
132 | typedef DerivedT derived_t; | |
133 | typedef typename grammar_definition<DerivedT, ScannerT>::type definition_t; | |
134 | ||
135 | typedef grammar_helper<grammar_t, derived_t, scanner_t> helper_t; | |
136 | typedef boost::shared_ptr<helper_t> helper_ptr_t; | |
137 | typedef boost::weak_ptr<helper_t> helper_weak_ptr_t; | |
138 | ||
139 | grammar_helper* | |
140 | this_() { return this; } | |
141 | ||
142 | grammar_helper(helper_weak_ptr_t& p) | |
143 | : definitions_cnt(0) | |
144 | , self(this_()) | |
145 | { p = self; } | |
146 | ||
147 | definition_t& | |
148 | define(grammar_t const* target_grammar) | |
149 | { | |
150 | grammar_helper_list<GrammarT> &helpers = | |
151 | grammartract_helper_list::do_(target_grammar); | |
152 | typename grammar_t::object_id id = target_grammar->get_object_id(); | |
153 | ||
154 | if (definitions.size()<=id) | |
155 | definitions.resize(id*3/2+1); | |
156 | if (definitions[id]!=0) | |
157 | return *definitions[id]; | |
158 | ||
159 | std::auto_ptr<definition_t> | |
160 | result(new definition_t(target_grammar->derived())); | |
161 | ||
162 | #ifdef BOOST_SPIRIT_THREADSAFE | |
163 | boost::unique_lock<boost::mutex> lock(helpers.mutex()); | |
164 | #endif | |
165 | helpers.push_back(this); | |
166 | ||
167 | ++definitions_cnt; | |
168 | definitions[id] = result.get(); | |
169 | return *(result.release()); | |
170 | } | |
171 | ||
172 | int | |
173 | undefine(grammar_t* target_grammar) | |
174 | { | |
175 | typename grammar_t::object_id id = target_grammar->get_object_id(); | |
176 | ||
177 | if (definitions.size()<=id) | |
178 | return 0; | |
179 | delete definitions[id]; | |
180 | definitions[id] = 0; | |
181 | if (--definitions_cnt==0) | |
182 | self.reset(); | |
183 | return 0; | |
184 | } | |
185 | ||
186 | private: | |
187 | ||
188 | std::vector<definition_t*> definitions; | |
189 | unsigned long definitions_cnt; | |
190 | helper_ptr_t self; | |
191 | }; | |
192 | ||
193 | #endif /* defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) */ | |
194 | ||
195 | #ifdef BOOST_SPIRIT_THREADSAFE | |
196 | class get_definition_static_data_tag | |
197 | { | |
198 | template<typename DerivedT, typename ContextT, typename ScannerT> | |
199 | friend typename DerivedT::template definition<ScannerT> & | |
200 | get_definition(grammar<DerivedT, ContextT> const* self); | |
201 | ||
202 | get_definition_static_data_tag() {} | |
203 | }; | |
204 | #endif | |
205 | ||
206 | template<typename DerivedT, typename ContextT, typename ScannerT> | |
207 | inline typename DerivedT::template definition<ScannerT> & | |
208 | get_definition(grammar<DerivedT, ContextT> const* self) | |
209 | { | |
210 | #if defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) | |
211 | ||
212 | typedef typename DerivedT::template definition<ScannerT> definition_t; | |
213 | static definition_t def(self->derived()); | |
214 | return def; | |
215 | #else | |
216 | typedef grammar<DerivedT, ContextT> self_t; | |
217 | typedef impl::grammar_helper<self_t, DerivedT, ScannerT> helper_t; | |
218 | typedef typename helper_t::helper_weak_ptr_t ptr_t; | |
219 | ||
220 | # ifdef BOOST_SPIRIT_THREADSAFE | |
221 | boost::thread_specific_ptr<ptr_t> & tld_helper | |
222 | = static_<boost::thread_specific_ptr<ptr_t>, | |
223 | get_definition_static_data_tag>(get_definition_static_data_tag()); | |
224 | ||
225 | if (!tld_helper.get()) | |
226 | tld_helper.reset(new ptr_t); | |
227 | ptr_t &helper = *tld_helper; | |
228 | # else | |
229 | static ptr_t helper; | |
230 | # endif | |
231 | if (helper.expired()) | |
232 | new helper_t(helper); | |
233 | return helper.lock()->define(self); | |
234 | #endif | |
235 | } | |
236 | ||
237 | template <int N> | |
238 | struct call_helper { | |
239 | ||
240 | template <typename RT, typename DefinitionT, typename ScannerT> | |
241 | static void | |
242 | do_ (RT &result, DefinitionT &def, ScannerT const &scan) | |
243 | { | |
244 | result = def.template get_start_parser<N>()->parse(scan); | |
245 | } | |
246 | }; | |
247 | ||
248 | template <> | |
249 | struct call_helper<0> { | |
250 | ||
251 | template <typename RT, typename DefinitionT, typename ScannerT> | |
252 | static void | |
253 | do_ (RT &result, DefinitionT &def, ScannerT const &scan) | |
254 | { | |
255 | result = def.start().parse(scan); | |
256 | } | |
257 | }; | |
258 | ||
259 | ////////////////////////////////// | |
260 | template<int N, typename DerivedT, typename ContextT, typename ScannerT> | |
261 | inline typename parser_result<grammar<DerivedT, ContextT>, ScannerT>::type | |
262 | grammar_parser_parse( | |
263 | grammar<DerivedT, ContextT> const* self, | |
264 | ScannerT const &scan) | |
265 | { | |
266 | typedef | |
267 | typename parser_result<grammar<DerivedT, ContextT>, ScannerT>::type | |
268 | result_t; | |
269 | typedef typename DerivedT::template definition<ScannerT> definition_t; | |
270 | ||
271 | result_t result; | |
272 | definition_t &def = get_definition<DerivedT, ContextT, ScannerT>(self); | |
273 | ||
274 | call_helper<N>::do_(result, def, scan); | |
275 | return result; | |
276 | } | |
277 | ||
278 | ////////////////////////////////// | |
279 | template<typename GrammarT> | |
280 | inline void | |
281 | grammar_destruct(GrammarT* self) | |
282 | { | |
283 | #if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) | |
284 | typedef grammar_helper_list<GrammarT> helper_list_t; | |
285 | ||
286 | helper_list_t& helpers = | |
287 | grammartract_helper_list::do_(self); | |
288 | ||
289 | # if defined(BOOST_INTEL_CXX_VERSION) | |
290 | typedef typename helper_list_t::vector_t::reverse_iterator iterator_t; | |
291 | ||
292 | for (iterator_t i = helpers.rbegin(); i != helpers.rend(); ++i) | |
293 | (*i)->undefine(self); | |
294 | # else | |
295 | typedef impl::grammar_helper_base<GrammarT> helper_base_t; | |
296 | ||
297 | std::for_each(helpers.rbegin(), helpers.rend(), | |
298 | std::bind2nd(std::mem_fun(&helper_base_t::undefine), self)); | |
299 | # endif | |
300 | ||
301 | #else | |
302 | (void)self; | |
303 | #endif | |
304 | } | |
305 | ||
306 | /////////////////////////////////////////////////////////////////////////// | |
307 | // | |
308 | // entry_grammar class | |
309 | // | |
310 | /////////////////////////////////////////////////////////////////////////// | |
311 | template <typename DerivedT, int N, typename ContextT> | |
312 | class entry_grammar | |
313 | : public parser<entry_grammar<DerivedT, N, ContextT> > | |
314 | { | |
315 | ||
316 | public: | |
317 | typedef entry_grammar<DerivedT, N, ContextT> self_t; | |
318 | typedef self_t embed_t; | |
319 | typedef typename ContextT::context_linker_t context_t; | |
320 | typedef typename context_t::attr_t attr_t; | |
321 | ||
322 | template <typename ScannerT> | |
323 | struct result | |
324 | { | |
325 | typedef typename match_result<ScannerT, attr_t>::type type; | |
326 | }; | |
327 | ||
328 | entry_grammar(DerivedT const &p) : target_grammar(p) {} | |
329 | ||
330 | template <typename ScannerT> | |
331 | typename parser_result<self_t, ScannerT>::type | |
332 | parse_main(ScannerT const& scan) const | |
333 | { return impl::grammar_parser_parse<N>(&target_grammar, scan); } | |
334 | ||
335 | template <typename ScannerT> | |
336 | typename parser_result<self_t, ScannerT>::type | |
337 | parse(ScannerT const& scan) const | |
338 | { | |
339 | typedef typename parser_result<self_t, ScannerT>::type result_t; | |
340 | typedef parser_scanner_linker<ScannerT> scanner_t; | |
341 | BOOST_SPIRIT_CONTEXT_PARSE(scan, target_grammar, scanner_t, | |
342 | context_t, result_t) | |
343 | } | |
344 | ||
345 | private: | |
346 | DerivedT const &target_grammar; | |
347 | }; | |
348 | ||
349 | } // namespace impl | |
350 | ||
351 | /////////////////////////////////////// | |
352 | #if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) | |
353 | #define BOOST_SPIRIT_GRAMMAR_ID , public impl::object_with_id<impl::grammar_tag> | |
354 | #else | |
355 | #define BOOST_SPIRIT_GRAMMAR_ID | |
356 | #endif | |
357 | ||
358 | /////////////////////////////////////// | |
359 | #if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) | |
360 | #define BOOST_SPIRIT_GRAMMAR_STATE \ | |
361 | private: \ | |
362 | friend struct impl::grammartract_helper_list; \ | |
363 | mutable impl::grammar_helper_list<self_t> helpers; | |
364 | #else | |
365 | #define BOOST_SPIRIT_GRAMMAR_STATE | |
366 | #endif | |
367 | ||
368 | /////////////////////////////////////////////////////////////////////////////// | |
369 | BOOST_SPIRIT_CLASSIC_NAMESPACE_END | |
370 | ||
371 | }} // namespace boost::spirit | |
372 | ||
373 | #endif |