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