374 lines
12 KiB
Plaintext
374 lines
12 KiB
Plaintext
/*=============================================================================
|
|
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>
|
|
#include <boost/thread/lock_types.hpp>
|
|
#endif
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
namespace boost { namespace spirit {
|
|
|
|
BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
|
|
|
|
template <typename DerivedT, typename ContextT>
|
|
struct grammar;
|
|
|
|
|
|
//////////////////////////////////
|
|
template <typename GrammarT, typename ScannerT>
|
|
struct grammar_definition
|
|
{
|
|
typedef typename GrammarT::template definition<ScannerT> type;
|
|
};
|
|
|
|
|
|
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)
|
|
|
|
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 =
|
|
grammartract_helper_list::do_(target_grammar);
|
|
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::unique_lock<boost::mutex> 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
|
|
}
|
|
|
|
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);
|
|
}
|
|
};
|
|
|
|
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 grammar_helper_list<GrammarT> helper_list_t;
|
|
|
|
helper_list_t& helpers =
|
|
grammartract_helper_list::do_(self);
|
|
|
|
# if defined(BOOST_INTEL_CXX_VERSION)
|
|
typedef typename helper_list_t::vector_t::reverse_iterator iterator_t;
|
|
|
|
for (iterator_t i = helpers.rbegin(); i != helpers.rend(); ++i)
|
|
(*i)->undefine(self);
|
|
# else
|
|
typedef impl::grammar_helper_base<GrammarT> helper_base_t;
|
|
|
|
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(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE)
|
|
#define BOOST_SPIRIT_GRAMMAR_STATE \
|
|
private: \
|
|
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
|