1 /*============================================================================= 2 Copyright (c) 2001-2003 Joel de Guzman 3 http://spirit.sourceforge.net/ 4 5 Distributed under the Boost Software License, Version 1.0. (See accompanying 6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 =============================================================================*/ 8 #ifndef BOOST_SPIRIT_SYMBOLS_HPP 9 #define BOOST_SPIRIT_SYMBOLS_HPP 10 11 /////////////////////////////////////////////////////////////////////////////// 12 #include <string> 13 14 #include <boost/ref.hpp> 15 16 #include <boost/spirit/home/classic/namespace.hpp> 17 #include <boost/spirit/home/classic/core/parser.hpp> 18 #include <boost/spirit/home/classic/core/composite/directives.hpp> 19 20 #include <boost/spirit/home/classic/symbols/symbols_fwd.hpp> 21 22 23 /////////////////////////////////////////////////////////////////////////////// 24 namespace boost { namespace spirit { 25 26 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN 27 28 /////////////////////////////////////////////////////////////////////////////// 29 // 30 // symbols class 31 // 32 // This class implements a symbol table. The symbol table holds a 33 // dictionary of symbols where each symbol is a sequence of CharTs. 34 // The template class can work efficiently with 8, 16 and 32 bit 35 // characters. Mutable data of type T is associated with each 36 // symbol. 37 // 38 // The class is a parser. The parse member function returns 39 // additional information in the symbol_match class (see below). 40 // The additional data is a pointer to some data associated with 41 // the matching symbol. 42 // 43 // The actual set implementation is supplied by the SetT template 44 // parameter. By default, this uses the tst class (see tst.ipp). 45 // 46 // Symbols are added into the symbol table statically using the 47 // construct: 48 // 49 // sym = a, b, c, d ...; 50 // 51 // where sym is a symbol table and a..d are strings. Example: 52 // 53 // sym = "pineapple", "orange", "banana", "apple"; 54 // 55 // Alternatively, symbols may be added dynamically through the 56 // member functor 'add' (see symbol_inserter below). The member 57 // functor 'add' may be attached to a parser as a semantic action 58 // taking in a begin/end pair: 59 // 60 // p[sym.add] 61 // 62 // where p is a parser (and sym is a symbol table). On success, 63 // the matching portion of the input is added to the symbol table. 64 // 65 // 'add' may also be used to directly initialize data. Examples: 66 // 67 // sym.add("hello", 1)("crazy", 2)("world", 3); 68 // 69 /////////////////////////////////////////////////////////////////////////////// 70 template <typename T, typename CharT, typename SetT> 71 class symbols 72 : private SetT 73 , public parser<symbols<T, CharT, SetT> > 74 { 75 public: 76 77 typedef parser<symbols<T, CharT, SetT> > parser_base_t; 78 typedef symbols<T, CharT, SetT> self_t; 79 typedef self_t const& embed_t; 80 typedef T symbol_data_t; 81 typedef boost::reference_wrapper<T> symbol_ref_t; 82 83 symbols(); 84 symbols(symbols const& other); 85 ~symbols(); 86 87 symbols& 88 operator=(symbols const& other); 89 90 symbol_inserter<T, SetT> const& 91 operator=(CharT const* str); 92 93 template <typename ScannerT> 94 struct result 95 { 96 typedef typename match_result<ScannerT, symbol_ref_t>::type type; 97 }; 98 99 template <typename ScannerT> 100 typename parser_result<self_t, ScannerT>::type parse_main(ScannerT const & scan) const101 parse_main(ScannerT const& scan) const 102 { 103 typedef typename ScannerT::iterator_t iterator_t; 104 iterator_t first = scan.first; 105 typename SetT::search_info result = SetT::find(scan); 106 107 if (result.data) 108 return scan. 109 create_match( 110 result.length, 111 symbol_ref_t(*result.data), 112 first, 113 scan.first); 114 else 115 return scan.no_match(); 116 } 117 118 template <typename ScannerT> 119 typename parser_result<self_t, ScannerT>::type parse(ScannerT const & scan) const120 parse(ScannerT const& scan) const 121 { 122 typedef typename parser_result<self_t, ScannerT>::type result_t; 123 return impl::implicit_lexeme_parse<result_t> 124 (*this, scan, scan); 125 } 126 127 template < typename ScannerT > find(ScannerT const & scan) const128 T* find(ScannerT const& scan) const 129 { return SetT::find(scan).data; } 130 131 symbol_inserter<T, SetT> const add; 132 }; 133 134 /////////////////////////////////////////////////////////////////////////////// 135 // 136 // Symbol table utilities 137 // 138 // add 139 // 140 // adds a symbol 'sym' (string) to a symbol table 'table' plus an 141 // optional data 'data' associated with the symbol. Returns a pointer to 142 // the data associated with the symbol or NULL if add failed (e.g. when 143 // the symbol is already added before). 144 // 145 // find 146 // 147 // finds a symbol 'sym' (string) from a symbol table 'table'. Returns a 148 // pointer to the data associated with the symbol or NULL if not found 149 // 150 /////////////////////////////////////////////////////////////////////////////// 151 template <typename T, typename CharT, typename SetT> 152 T* add(symbols<T, CharT, SetT>& table, CharT const* sym, T const& data = T()); 153 154 template <typename T, typename CharT, typename SetT> 155 T* find(symbols<T, CharT, SetT> const& table, CharT const* sym); 156 157 /////////////////////////////////////////////////////////////////////////////// 158 // 159 // symbol_inserter class 160 // 161 // The symbols class holds an instance of this class named 'add'. 162 // This can be called directly just like a member function, 163 // passing in a first/last iterator and optional data: 164 // 165 // sym.add(first, last, data); 166 // 167 // Or, passing in a C string and optional data: 168 // 169 // sym.add(c_string, data); 170 // 171 // where sym is a symbol table. The 'data' argument is optional. 172 // This may also be used as a semantic action since it conforms 173 // to the action interface (see action.hpp): 174 // 175 // p[sym.add] 176 // 177 /////////////////////////////////////////////////////////////////////////////// 178 template <typename T, typename SetT> 179 class symbol_inserter 180 { 181 public: 182 symbol_inserter(SetT & set_)183 symbol_inserter(SetT& set_) 184 : set(set_) {} 185 186 typedef symbol_inserter const & result_type; 187 188 template <typename IteratorT> 189 symbol_inserter const& operator ()(IteratorT first,IteratorT const & last,T const & data=T ()) const190 operator()(IteratorT first, IteratorT const& last, T const& data = T()) const 191 { 192 set.add(first, last, data); 193 return *this; 194 } 195 196 template <typename CharT> 197 symbol_inserter const& operator ()(CharT const * str,T const & data=T ()) const198 operator()(CharT const* str, T const& data = T()) const 199 { 200 CharT const* last = str; 201 while (*last) 202 last++; 203 set.add(str, last, data); 204 return *this; 205 } 206 207 template <typename CharT> 208 symbol_inserter const& operator ,(CharT const * str) const209 operator,(CharT const* str) const 210 { 211 CharT const* last = str; 212 while (*last) 213 last++; 214 set.add(str, last, T()); 215 return *this; 216 } 217 218 private: 219 220 SetT& set; 221 }; 222 223 /////////////////////////////////////////////////////////////////////////////// 224 BOOST_SPIRIT_CLASSIC_NAMESPACE_END 225 226 }} // namespace BOOST_SPIRIT_CLASSIC_NS 227 228 #include <boost/spirit/home/classic/symbols/impl/symbols.ipp> 229 #endif 230