230 lines
7.0 KiB
C++
230 lines
7.0 KiB
C++
/*=============================================================================
|
|
Copyright (c) 2001-2003 Joel de Guzman
|
|
http://spirit.sourceforge.net/
|
|
|
|
Distributed under 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)
|
|
=============================================================================*/
|
|
#ifndef BOOST_SPIRIT_SYMBOLS_HPP
|
|
#define BOOST_SPIRIT_SYMBOLS_HPP
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#include <string>
|
|
|
|
#include <boost/ref.hpp>
|
|
|
|
#include <boost/spirit/home/classic/namespace.hpp>
|
|
#include <boost/spirit/home/classic/core/parser.hpp>
|
|
#include <boost/spirit/home/classic/core/composite/directives.hpp>
|
|
|
|
#include <boost/spirit/home/classic/symbols/symbols_fwd.hpp>
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
namespace boost { namespace spirit {
|
|
|
|
BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// symbols class
|
|
//
|
|
// This class implements a symbol table. The symbol table holds a
|
|
// dictionary of symbols where each symbol is a sequence of CharTs.
|
|
// The template class can work efficiently with 8, 16 and 32 bit
|
|
// characters. Mutable data of type T is associated with each
|
|
// symbol.
|
|
//
|
|
// The class is a parser. The parse member function returns
|
|
// additional information in the symbol_match class (see below).
|
|
// The additional data is a pointer to some data associated with
|
|
// the matching symbol.
|
|
//
|
|
// The actual set implementation is supplied by the SetT template
|
|
// parameter. By default, this uses the tst class (see tst.ipp).
|
|
//
|
|
// Symbols are added into the symbol table statically using the
|
|
// construct:
|
|
//
|
|
// sym = a, b, c, d ...;
|
|
//
|
|
// where sym is a symbol table and a..d are strings. Example:
|
|
//
|
|
// sym = "pineapple", "orange", "banana", "apple";
|
|
//
|
|
// Alternatively, symbols may be added dynamically through the
|
|
// member functor 'add' (see symbol_inserter below). The member
|
|
// functor 'add' may be attached to a parser as a semantic action
|
|
// taking in a begin/end pair:
|
|
//
|
|
// p[sym.add]
|
|
//
|
|
// where p is a parser (and sym is a symbol table). On success,
|
|
// the matching portion of the input is added to the symbol table.
|
|
//
|
|
// 'add' may also be used to directly initialize data. Examples:
|
|
//
|
|
// sym.add("hello", 1)("crazy", 2)("world", 3);
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
template <typename T, typename CharT, typename SetT>
|
|
class symbols
|
|
: private SetT
|
|
, public parser<symbols<T, CharT, SetT> >
|
|
{
|
|
public:
|
|
|
|
typedef parser<symbols<T, CharT, SetT> > parser_base_t;
|
|
typedef symbols<T, CharT, SetT> self_t;
|
|
typedef self_t const& embed_t;
|
|
typedef T symbol_data_t;
|
|
typedef boost::reference_wrapper<T> symbol_ref_t;
|
|
|
|
symbols();
|
|
symbols(symbols const& other);
|
|
~symbols();
|
|
|
|
symbols&
|
|
operator=(symbols const& other);
|
|
|
|
symbol_inserter<T, SetT> const&
|
|
operator=(CharT const* str);
|
|
|
|
template <typename ScannerT>
|
|
struct result
|
|
{
|
|
typedef typename match_result<ScannerT, symbol_ref_t>::type type;
|
|
};
|
|
|
|
template <typename ScannerT>
|
|
typename parser_result<self_t, ScannerT>::type
|
|
parse_main(ScannerT const& scan) const
|
|
{
|
|
typedef typename ScannerT::iterator_t iterator_t;
|
|
iterator_t first = scan.first;
|
|
typename SetT::search_info result = SetT::find(scan);
|
|
|
|
if (result.data)
|
|
return scan.
|
|
create_match(
|
|
result.length,
|
|
symbol_ref_t(*result.data),
|
|
first,
|
|
scan.first);
|
|
else
|
|
return scan.no_match();
|
|
}
|
|
|
|
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;
|
|
return impl::implicit_lexeme_parse<result_t>
|
|
(*this, scan, scan);
|
|
}
|
|
|
|
template < typename ScannerT >
|
|
T* find(ScannerT const& scan) const
|
|
{ return SetT::find(scan).data; }
|
|
|
|
symbol_inserter<T, SetT> const add;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Symbol table utilities
|
|
//
|
|
// add
|
|
//
|
|
// adds a symbol 'sym' (string) to a symbol table 'table' plus an
|
|
// optional data 'data' associated with the symbol. Returns a pointer to
|
|
// the data associated with the symbol or NULL if add failed (e.g. when
|
|
// the symbol is already added before).
|
|
//
|
|
// find
|
|
//
|
|
// finds a symbol 'sym' (string) from a symbol table 'table'. Returns a
|
|
// pointer to the data associated with the symbol or NULL if not found
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
template <typename T, typename CharT, typename SetT>
|
|
T* add(symbols<T, CharT, SetT>& table, CharT const* sym, T const& data = T());
|
|
|
|
template <typename T, typename CharT, typename SetT>
|
|
T* find(symbols<T, CharT, SetT> const& table, CharT const* sym);
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// symbol_inserter class
|
|
//
|
|
// The symbols class holds an instance of this class named 'add'.
|
|
// This can be called directly just like a member function,
|
|
// passing in a first/last iterator and optional data:
|
|
//
|
|
// sym.add(first, last, data);
|
|
//
|
|
// Or, passing in a C string and optional data:
|
|
//
|
|
// sym.add(c_string, data);
|
|
//
|
|
// where sym is a symbol table. The 'data' argument is optional.
|
|
// This may also be used as a semantic action since it conforms
|
|
// to the action interface (see action.hpp):
|
|
//
|
|
// p[sym.add]
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
template <typename T, typename SetT>
|
|
class symbol_inserter
|
|
{
|
|
public:
|
|
|
|
symbol_inserter(SetT& set_)
|
|
: set(set_) {}
|
|
|
|
typedef symbol_inserter const & result_type;
|
|
|
|
template <typename IteratorT>
|
|
symbol_inserter const&
|
|
operator()(IteratorT first, IteratorT const& last, T const& data = T()) const
|
|
{
|
|
set.add(first, last, data);
|
|
return *this;
|
|
}
|
|
|
|
template <typename CharT>
|
|
symbol_inserter const&
|
|
operator()(CharT const* str, T const& data = T()) const
|
|
{
|
|
CharT const* last = str;
|
|
while (*last)
|
|
last++;
|
|
set.add(str, last, data);
|
|
return *this;
|
|
}
|
|
|
|
template <typename CharT>
|
|
symbol_inserter const&
|
|
operator,(CharT const* str) const
|
|
{
|
|
CharT const* last = str;
|
|
while (*last)
|
|
last++;
|
|
set.add(str, last, T());
|
|
return *this;
|
|
}
|
|
|
|
private:
|
|
|
|
SetT& set;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOST_SPIRIT_CLASSIC_NAMESPACE_END
|
|
|
|
}} // namespace BOOST_SPIRIT_CLASSIC_NS
|
|
|
|
#include <boost/spirit/home/classic/symbols/impl/symbols.ipp>
|
|
#endif
|