symbols.hpp 7.0 KB

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