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