/*============================================================================= | |
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 |