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