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/
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
14 #if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE)
15 #include <boost/spirit/home/classic/core/non_terminal/impl/object_with_id.ipp>
18 #include <memory> // for std::auto_ptr
19 #include <boost/weak_ptr.hpp>
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>
28 ///////////////////////////////////////////////////////////////////////////////
29 namespace boost { namespace spirit {
31 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
33 template <typename DerivedT, typename ContextT>
37 //////////////////////////////////
38 template <typename GrammarT, typename ScannerT>
39 struct grammar_definition
41 typedef typename GrammarT::template definition<ScannerT> type;
48 #if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE)
49 struct grammar_tag {};
51 //////////////////////////////////
52 template <typename GrammarT>
53 struct grammar_helper_base
55 virtual int undefine(GrammarT *) = 0;
56 virtual ~grammar_helper_base() {}
59 //////////////////////////////////
60 template <typename GrammarT>
61 struct grammar_helper_list
63 typedef GrammarT grammar_t;
64 typedef grammar_helper_base<GrammarT> helper_t;
65 typedef std::vector<helper_t*> vector_t;
67 grammar_helper_list() {}
68 grammar_helper_list(grammar_helper_list const& /*x*/)
69 { // Does _not_ copy the helpers member !
72 grammar_helper_list& operator=(grammar_helper_list const& x)
73 { // Does _not_ copy the helpers member !
77 void push_back(helper_t *helper)
78 { helpers.push_back(helper); }
81 { helpers.pop_back(); }
83 typename vector_t::size_type
85 { return helpers.size(); }
87 typename vector_t::reverse_iterator
89 { return helpers.rbegin(); }
91 typename vector_t::reverse_iterator
93 { return helpers.rend(); }
95 #ifdef BOOST_SPIRIT_THREADSAFE
96 boost::mutex & mutex()
103 #ifdef BOOST_SPIRIT_THREADSAFE
108 //////////////////////////////////
109 struct grammartract_helper_list;
111 #if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE)
113 struct grammartract_helper_list
115 template<typename GrammarT>
116 static grammar_helper_list<GrammarT>&
117 do_(GrammarT const* g)
125 //////////////////////////////////
126 template <typename GrammarT, typename DerivedT, typename ScannerT>
127 struct grammar_helper : private grammar_helper_base<GrammarT>
129 typedef GrammarT grammar_t;
130 typedef ScannerT scanner_t;
131 typedef DerivedT derived_t;
132 typedef typename grammar_definition<DerivedT, ScannerT>::type definition_t;
134 typedef grammar_helper<grammar_t, derived_t, scanner_t> helper_t;
135 typedef boost::shared_ptr<helper_t> helper_ptr_t;
136 typedef boost::weak_ptr<helper_t> helper_weak_ptr_t;
139 this_() { return this; }
141 grammar_helper(helper_weak_ptr_t& p)
147 define(grammar_t const* target_grammar)
149 grammar_helper_list<GrammarT> &helpers =
150 grammartract_helper_list::do_(target_grammar);
151 typename grammar_t::object_id id = target_grammar->get_object_id();
153 if (definitions.size()<=id)
154 definitions.resize(id*3/2+1);
155 if (definitions[id]!=0)
156 return *definitions[id];
158 std::auto_ptr<definition_t>
159 result(new definition_t(target_grammar->derived()));
161 #ifdef BOOST_SPIRIT_THREADSAFE
162 boost::mutex::scoped_lock lock(helpers.mutex());
164 helpers.push_back(this);
167 definitions[id] = result.get();
168 return *(result.release());
172 undefine(grammar_t* target_grammar)
174 typename grammar_t::object_id id = target_grammar->get_object_id();
176 if (definitions.size()<=id)
178 delete definitions[id];
180 if (--definitions_cnt==0)
187 std::vector<definition_t*> definitions;
188 unsigned long definitions_cnt;
192 #endif /* defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) */
194 #ifdef BOOST_SPIRIT_THREADSAFE
195 class get_definition_static_data_tag
197 template<typename DerivedT, typename ContextT, typename ScannerT>
198 friend typename DerivedT::template definition<ScannerT> &
199 get_definition(grammar<DerivedT, ContextT> const* self);
201 get_definition_static_data_tag() {}
205 template<typename DerivedT, typename ContextT, typename ScannerT>
206 inline typename DerivedT::template definition<ScannerT> &
207 get_definition(grammar<DerivedT, ContextT> const* self)
209 #if defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE)
211 typedef typename DerivedT::template definition<ScannerT> definition_t;
212 static definition_t def(self->derived());
215 typedef grammar<DerivedT, ContextT> self_t;
216 typedef impl::grammar_helper<self_t, DerivedT, ScannerT> helper_t;
217 typedef typename helper_t::helper_weak_ptr_t ptr_t;
219 # ifdef BOOST_SPIRIT_THREADSAFE
220 boost::thread_specific_ptr<ptr_t> & tld_helper
221 = static_<boost::thread_specific_ptr<ptr_t>,
222 get_definition_static_data_tag>(get_definition_static_data_tag());
224 if (!tld_helper.get())
225 tld_helper.reset(new ptr_t);
226 ptr_t &helper = *tld_helper;
230 if (helper.expired())
231 new helper_t(helper);
232 return helper.lock()->define(self);
239 template <typename RT, typename DefinitionT, typename ScannerT>
241 do_ (RT &result, DefinitionT &def, ScannerT const &scan)
243 result = def.template get_start_parser<N>()->parse(scan);
248 struct call_helper<0> {
250 template <typename RT, typename DefinitionT, typename ScannerT>
252 do_ (RT &result, DefinitionT &def, ScannerT const &scan)
254 result = def.start().parse(scan);
258 //////////////////////////////////
259 template<int N, typename DerivedT, typename ContextT, typename ScannerT>
260 inline typename parser_result<grammar<DerivedT, ContextT>, ScannerT>::type
261 grammar_parser_parse(
262 grammar<DerivedT, ContextT> const* self,
263 ScannerT const &scan)
266 typename parser_result<grammar<DerivedT, ContextT>, ScannerT>::type
268 typedef typename DerivedT::template definition<ScannerT> definition_t;
271 definition_t &def = get_definition<DerivedT, ContextT, ScannerT>(self);
273 call_helper<N>::do_(result, def, scan);
277 //////////////////////////////////
278 template<typename GrammarT>
280 grammar_destruct(GrammarT* self)
282 #if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE)
283 typedef impl::grammar_helper_base<GrammarT> helper_base_t;
284 typedef grammar_helper_list<GrammarT> helper_list_t;
285 typedef typename helper_list_t::vector_t::reverse_iterator iterator_t;
287 helper_list_t& helpers =
288 grammartract_helper_list::do_(self);
290 # if defined(BOOST_INTEL_CXX_VERSION)
291 for (iterator_t i = helpers.rbegin(); i != helpers.rend(); ++i)
292 (*i)->undefine(self);
294 std::for_each(helpers.rbegin(), helpers.rend(),
295 std::bind2nd(std::mem_fun(&helper_base_t::undefine), self));
303 ///////////////////////////////////////////////////////////////////////////
305 // entry_grammar class
307 ///////////////////////////////////////////////////////////////////////////
308 template <typename DerivedT, int N, typename ContextT>
310 : public parser<entry_grammar<DerivedT, N, ContextT> >
314 typedef entry_grammar<DerivedT, N, ContextT> self_t;
315 typedef self_t embed_t;
316 typedef typename ContextT::context_linker_t context_t;
317 typedef typename context_t::attr_t attr_t;
319 template <typename ScannerT>
322 typedef typename match_result<ScannerT, attr_t>::type type;
325 entry_grammar(DerivedT const &p) : target_grammar(p) {}
327 template <typename ScannerT>
328 typename parser_result<self_t, ScannerT>::type
329 parse_main(ScannerT const& scan) const
330 { return impl::grammar_parser_parse<N>(&target_grammar, scan); }
332 template <typename ScannerT>
333 typename parser_result<self_t, ScannerT>::type
334 parse(ScannerT const& scan) const
336 typedef typename parser_result<self_t, ScannerT>::type result_t;
337 typedef parser_scanner_linker<ScannerT> scanner_t;
338 BOOST_SPIRIT_CONTEXT_PARSE(scan, target_grammar, scanner_t,
343 DerivedT const &target_grammar;
348 ///////////////////////////////////////
349 #if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE)
350 #define BOOST_SPIRIT_GRAMMAR_ID , public impl::object_with_id<impl::grammar_tag>
352 #define BOOST_SPIRIT_GRAMMAR_ID
355 ///////////////////////////////////////
356 #if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE)
357 #define BOOST_SPIRIT_GRAMMAR_STATE \
359 friend struct impl::grammartract_helper_list; \
360 mutable impl::grammar_helper_list<self_t> helpers;
362 #define BOOST_SPIRIT_GRAMMAR_STATE
365 ///////////////////////////////////////////////////////////////////////////////
366 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
368 }} // namespace boost::spirit