| /*============================================================================= |
| Copyright (c) 2001-2003 Joel de Guzman |
| Copyright (c) 2002-2003 Martin Wille |
| Copyright (c) 2003 Hartmut Kaiser |
| http://spirit.sourceforge.net/ |
| |
| Use, modification and distribution is subject to 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_GRAMMAR_IPP |
| #define BOOST_SPIRIT_GRAMMAR_IPP |
| |
| #if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) |
| #include <boost/spirit/home/classic/core/non_terminal/impl/object_with_id.ipp> |
| #include <algorithm> |
| #include <functional> |
| #include <memory> // for std::auto_ptr |
| #include <boost/weak_ptr.hpp> |
| #endif |
| |
| #ifdef BOOST_SPIRIT_THREADSAFE |
| #include <boost/spirit/home/classic/core/non_terminal/impl/static.hpp> |
| #include <boost/thread/tss.hpp> |
| #include <boost/thread/mutex.hpp> |
| #endif |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| namespace boost { namespace spirit { |
| |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN |
| |
| template <typename DerivedT, typename ContextT> |
| struct grammar; |
| |
| #if defined(BOOST_MSVC) && (BOOST_MSVC < 1300) |
| |
| BOOST_SPIRIT_DEPENDENT_TEMPLATE_WRAPPER(grammar_definition_wrapper, definition); |
| |
| ////////////////////////////////// |
| template <typename GrammarT, typename ScannerT> |
| struct grammar_definition |
| { |
| typedef typename impl::grammar_definition_wrapper<GrammarT> |
| ::template result_<ScannerT>::param_t type; |
| }; |
| |
| #else |
| |
| ////////////////////////////////// |
| template <typename GrammarT, typename ScannerT> |
| struct grammar_definition |
| { |
| typedef typename GrammarT::template definition<ScannerT> type; |
| }; |
| |
| #endif |
| |
| namespace impl |
| { |
| |
| #if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) |
| struct grammar_tag {}; |
| |
| ////////////////////////////////// |
| template <typename GrammarT> |
| struct grammar_helper_base |
| { |
| virtual int undefine(GrammarT *) = 0; |
| virtual ~grammar_helper_base() {} |
| }; |
| |
| ////////////////////////////////// |
| template <typename GrammarT> |
| struct grammar_helper_list |
| { |
| typedef GrammarT grammar_t; |
| typedef grammar_helper_base<GrammarT> helper_t; |
| typedef std::vector<helper_t*> vector_t; |
| |
| grammar_helper_list() {} |
| grammar_helper_list(grammar_helper_list const& /*x*/) |
| { // Does _not_ copy the helpers member ! |
| } |
| |
| grammar_helper_list& operator=(grammar_helper_list const& x) |
| { // Does _not_ copy the helpers member ! |
| return *this; |
| } |
| |
| void push_back(helper_t *helper) |
| { helpers.push_back(helper); } |
| |
| void pop_back() |
| { helpers.pop_back(); } |
| |
| typename vector_t::size_type |
| size() const |
| { return helpers.size(); } |
| |
| typename vector_t::reverse_iterator |
| rbegin() |
| { return helpers.rbegin(); } |
| |
| typename vector_t::reverse_iterator |
| rend() |
| { return helpers.rend(); } |
| |
| #ifdef BOOST_SPIRIT_THREADSAFE |
| boost::mutex & mutex() |
| { return m; } |
| #endif |
| |
| private: |
| |
| vector_t helpers; |
| #ifdef BOOST_SPIRIT_THREADSAFE |
| boost::mutex m; |
| #endif |
| }; |
| |
| ////////////////////////////////// |
| struct grammartract_helper_list; |
| |
| #if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) \ |
| && (!defined(__GNUC__) || (__GNUC__ > 2)) |
| |
| struct grammartract_helper_list |
| { |
| template<typename GrammarT> |
| static grammar_helper_list<GrammarT>& |
| do_(GrammarT const* g) |
| { |
| return g->helpers; |
| } |
| }; |
| |
| #endif |
| |
| ////////////////////////////////// |
| template <typename GrammarT, typename DerivedT, typename ScannerT> |
| struct grammar_helper : private grammar_helper_base<GrammarT> |
| { |
| typedef GrammarT grammar_t; |
| typedef ScannerT scanner_t; |
| typedef DerivedT derived_t; |
| typedef typename grammar_definition<DerivedT, ScannerT>::type definition_t; |
| |
| typedef grammar_helper<grammar_t, derived_t, scanner_t> helper_t; |
| typedef boost::shared_ptr<helper_t> helper_ptr_t; |
| typedef boost::weak_ptr<helper_t> helper_weak_ptr_t; |
| |
| grammar_helper* |
| this_() { return this; } |
| |
| grammar_helper(helper_weak_ptr_t& p) |
| : definitions_cnt(0) |
| , self(this_()) |
| { p = self; } |
| |
| definition_t& |
| define(grammar_t const* target_grammar) |
| { |
| grammar_helper_list<GrammarT> &helpers = |
| #if !defined(__GNUC__) || (__GNUC__ > 2) |
| grammartract_helper_list::do_(target_grammar); |
| #else |
| target_grammar->helpers; |
| #endif |
| typename grammar_t::object_id id = target_grammar->get_object_id(); |
| |
| if (definitions.size()<=id) |
| definitions.resize(id*3/2+1); |
| if (definitions[id]!=0) |
| return *definitions[id]; |
| |
| std::auto_ptr<definition_t> |
| result(new definition_t(target_grammar->derived())); |
| |
| #ifdef BOOST_SPIRIT_THREADSAFE |
| boost::mutex::scoped_lock lock(helpers.mutex()); |
| #endif |
| helpers.push_back(this); |
| |
| ++definitions_cnt; |
| definitions[id] = result.get(); |
| return *(result.release()); |
| } |
| |
| int |
| undefine(grammar_t* target_grammar) |
| { |
| typename grammar_t::object_id id = target_grammar->get_object_id(); |
| |
| if (definitions.size()<=id) |
| return 0; |
| delete definitions[id]; |
| definitions[id] = 0; |
| if (--definitions_cnt==0) |
| self.reset(); |
| return 0; |
| } |
| |
| private: |
| |
| std::vector<definition_t*> definitions; |
| unsigned long definitions_cnt; |
| helper_ptr_t self; |
| }; |
| |
| #endif /* defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) */ |
| |
| #ifdef BOOST_SPIRIT_THREADSAFE |
| class get_definition_static_data_tag |
| { |
| template<typename DerivedT, typename ContextT, typename ScannerT> |
| friend typename DerivedT::template definition<ScannerT> & |
| get_definition(grammar<DerivedT, ContextT> const* self); |
| |
| get_definition_static_data_tag() {} |
| }; |
| #endif |
| |
| template<typename DerivedT, typename ContextT, typename ScannerT> |
| inline typename DerivedT::template definition<ScannerT> & |
| get_definition(grammar<DerivedT, ContextT> const* self) |
| { |
| #if defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) |
| |
| typedef typename DerivedT::template definition<ScannerT> definition_t; |
| static definition_t def(self->derived()); |
| return def; |
| #else |
| typedef grammar<DerivedT, ContextT> self_t; |
| typedef impl::grammar_helper<self_t, DerivedT, ScannerT> helper_t; |
| typedef typename helper_t::helper_weak_ptr_t ptr_t; |
| |
| # ifdef BOOST_SPIRIT_THREADSAFE |
| boost::thread_specific_ptr<ptr_t> & tld_helper |
| = static_<boost::thread_specific_ptr<ptr_t>, |
| get_definition_static_data_tag>(get_definition_static_data_tag()); |
| |
| if (!tld_helper.get()) |
| tld_helper.reset(new ptr_t); |
| ptr_t &helper = *tld_helper; |
| # else |
| static ptr_t helper; |
| # endif |
| if (helper.expired()) |
| new helper_t(helper); |
| return helper.lock()->define(self); |
| #endif |
| } |
| |
| #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) |
| template <int N> |
| struct call_helper { |
| |
| template <typename RT, typename DefinitionT, typename ScannerT> |
| static void |
| do_ (RT &result, DefinitionT &def, ScannerT const &scan) |
| { |
| result = def.template get_start_parser<N>()->parse(scan); |
| } |
| }; |
| #else |
| // The grammar_def stuff isn't supported for compilers, which do not |
| // support partial template specialization |
| template <int N> struct call_helper; |
| #endif |
| |
| template <> |
| struct call_helper<0> { |
| |
| template <typename RT, typename DefinitionT, typename ScannerT> |
| static void |
| do_ (RT &result, DefinitionT &def, ScannerT const &scan) |
| { |
| result = def.start().parse(scan); |
| } |
| }; |
| |
| ////////////////////////////////// |
| template<int N, typename DerivedT, typename ContextT, typename ScannerT> |
| inline typename parser_result<grammar<DerivedT, ContextT>, ScannerT>::type |
| grammar_parser_parse( |
| grammar<DerivedT, ContextT> const* self, |
| ScannerT const &scan) |
| { |
| typedef |
| typename parser_result<grammar<DerivedT, ContextT>, ScannerT>::type |
| result_t; |
| typedef typename DerivedT::template definition<ScannerT> definition_t; |
| |
| result_t result; |
| definition_t &def = get_definition<DerivedT, ContextT, ScannerT>(self); |
| |
| call_helper<N>::do_(result, def, scan); |
| return result; |
| } |
| |
| ////////////////////////////////// |
| template<typename GrammarT> |
| inline void |
| grammar_destruct(GrammarT* self) |
| { |
| #if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) |
| typedef impl::grammar_helper_base<GrammarT> helper_base_t; |
| typedef grammar_helper_list<GrammarT> helper_list_t; |
| typedef typename helper_list_t::vector_t::reverse_iterator iterator_t; |
| |
| helper_list_t& helpers = |
| # if !defined(__GNUC__) || (__GNUC__ > 2) |
| grammartract_helper_list::do_(self); |
| # else |
| self->helpers; |
| # endif |
| |
| # if (defined(BOOST_MSVC) && (BOOST_MSVC < 1300)) \ |
| || defined(BOOST_INTEL_CXX_VERSION) |
| for (iterator_t i = helpers.rbegin(); i != helpers.rend(); ++i) |
| (*i)->undefine(self); |
| # else |
| std::for_each(helpers.rbegin(), helpers.rend(), |
| std::bind2nd(std::mem_fun(&helper_base_t::undefine), self)); |
| # endif |
| |
| #else |
| (void)self; |
| #endif |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // entry_grammar class |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename DerivedT, int N, typename ContextT> |
| class entry_grammar |
| : public parser<entry_grammar<DerivedT, N, ContextT> > |
| { |
| |
| public: |
| typedef entry_grammar<DerivedT, N, ContextT> self_t; |
| typedef self_t embed_t; |
| typedef typename ContextT::context_linker_t context_t; |
| typedef typename context_t::attr_t attr_t; |
| |
| template <typename ScannerT> |
| struct result |
| { |
| typedef typename match_result<ScannerT, attr_t>::type type; |
| }; |
| |
| entry_grammar(DerivedT const &p) : target_grammar(p) {} |
| |
| template <typename ScannerT> |
| typename parser_result<self_t, ScannerT>::type |
| parse_main(ScannerT const& scan) const |
| { return impl::grammar_parser_parse<N>(&target_grammar, scan); } |
| |
| template <typename ScannerT> |
| typename parser_result<self_t, ScannerT>::type |
| parse(ScannerT const& scan) const |
| { |
| typedef typename parser_result<self_t, ScannerT>::type result_t; |
| typedef parser_scanner_linker<ScannerT> scanner_t; |
| BOOST_SPIRIT_CONTEXT_PARSE(scan, target_grammar, scanner_t, |
| context_t, result_t) |
| } |
| |
| private: |
| DerivedT const &target_grammar; |
| }; |
| |
| } // namespace impl |
| |
| /////////////////////////////////////// |
| #if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) |
| #define BOOST_SPIRIT_GRAMMAR_ID , public impl::object_with_id<impl::grammar_tag> |
| #else |
| #define BOOST_SPIRIT_GRAMMAR_ID |
| #endif |
| |
| /////////////////////////////////////// |
| #if !defined(__GNUC__) || (__GNUC__ > 2) |
| #define BOOST_SPIRIT_GRAMMAR_ACCESS private: |
| #else |
| #define BOOST_SPIRIT_GRAMMAR_ACCESS |
| #endif |
| |
| /////////////////////////////////////// |
| #if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) |
| #define BOOST_SPIRIT_GRAMMAR_STATE \ |
| BOOST_SPIRIT_GRAMMAR_ACCESS \ |
| friend struct impl::grammartract_helper_list; \ |
| mutable impl::grammar_helper_list<self_t> helpers; |
| #else |
| #define BOOST_SPIRIT_GRAMMAR_STATE |
| #endif |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_END |
| |
| }} // namespace boost::spirit |
| |
| #endif |