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