symbols.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. /*=============================================================================
  2. Copyright (c) 2001-2014 Joel de Guzman
  3. Copyright (c) 2013 Carl Barron
  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. #if !defined(BOOST_SPIRIT_X3_SYMBOLS_MARCH_11_2007_1055AM)
  8. #define BOOST_SPIRIT_X3_SYMBOLS_MARCH_11_2007_1055AM
  9. #include <boost/spirit/home/x3/core/skip_over.hpp>
  10. #include <boost/spirit/home/x3/core/parser.hpp>
  11. #include <boost/spirit/home/x3/string/tst.hpp>
  12. #include <boost/spirit/home/x3/support/unused.hpp>
  13. #include <boost/spirit/home/x3/support/traits/string_traits.hpp>
  14. #include <boost/spirit/home/x3/support/traits/move_to.hpp>
  15. #include <boost/spirit/home/x3/support/no_case.hpp>
  16. #include <boost/spirit/home/support/char_encoding/ascii.hpp>
  17. #include <boost/spirit/home/support/char_encoding/iso8859_1.hpp>
  18. #include <boost/spirit/home/support/char_encoding/standard.hpp>
  19. #include <boost/spirit/home/support/char_encoding/standard_wide.hpp>
  20. #include <boost/fusion/include/at.hpp>
  21. #include <boost/range.hpp>
  22. #include <boost/type_traits/add_reference.hpp>
  23. #include <boost/type_traits/is_same.hpp>
  24. #include <boost/shared_ptr.hpp>
  25. #include <initializer_list>
  26. #if defined(BOOST_MSVC)
  27. # pragma warning(push)
  28. # pragma warning(disable: 4355) // 'this' : used in base member initializer list warning
  29. #endif
  30. namespace boost { namespace spirit { namespace x3
  31. {
  32. template <
  33. typename Encoding
  34. , typename T = unused_type
  35. , typename Lookup = tst<typename Encoding::char_type, T> >
  36. struct symbols_parser : parser<symbols_parser<Encoding, T, Lookup>>
  37. {
  38. typedef typename Encoding::char_type char_type; // the character type
  39. typedef Encoding encoding;
  40. typedef T value_type; // the value associated with each entry
  41. typedef value_type attribute_type;
  42. static bool const has_attribute =
  43. !is_same<unused_type, attribute_type>::value;
  44. static bool const handles_container =
  45. traits::is_container<attribute_type>::value;
  46. symbols_parser(std::string const& name = "symbols")
  47. : add(*this)
  48. , remove(*this)
  49. , lookup(new Lookup())
  50. , name_(name)
  51. {
  52. }
  53. symbols_parser(symbols_parser const& syms)
  54. : add(*this)
  55. , remove(*this)
  56. , lookup(syms.lookup)
  57. , name_(syms.name_)
  58. {
  59. }
  60. template <typename Symbols>
  61. symbols_parser(Symbols const& syms, std::string const& name = "symbols")
  62. : add(*this)
  63. , remove(*this)
  64. , lookup(new Lookup())
  65. , name_(name)
  66. {
  67. typename range_const_iterator<Symbols>::type si = boost::begin(syms);
  68. while (si != boost::end(syms))
  69. add(*si++);
  70. }
  71. template <typename Symbols, typename Data>
  72. symbols_parser(Symbols const& syms, Data const& data
  73. , std::string const& name = "symbols")
  74. : add(*this)
  75. , remove(*this)
  76. , lookup(new Lookup())
  77. , name_(name)
  78. {
  79. typename range_const_iterator<Symbols>::type si = boost::begin(syms);
  80. typename range_const_iterator<Data>::type di = boost::begin(data);
  81. while (si != boost::end(syms))
  82. add(*si++, *di++);
  83. }
  84. symbols_parser(std::initializer_list<std::pair<char_type const*, T>> syms
  85. , std::string const & name="symbols")
  86. : add(*this)
  87. , remove(*this)
  88. , lookup(new Lookup())
  89. , name_(name)
  90. {
  91. typedef std::initializer_list<std::pair<char_type const*, T>> symbols_t;
  92. typename range_const_iterator<symbols_t>::type si = boost::begin(syms);
  93. for (;si != boost::end(syms); ++si)
  94. add(si->first, si->second);
  95. }
  96. symbols_parser(std::initializer_list<char_type const*> syms
  97. , std::string const &name="symbols")
  98. : add(*this)
  99. , remove(*this)
  100. , lookup(new Lookup())
  101. , name_(name)
  102. {
  103. typedef std::initializer_list<char_type const*> symbols_t;
  104. typename range_const_iterator<symbols_t>::type si = boost::begin(syms);
  105. while (si != boost::end(syms))
  106. add(*si++);
  107. }
  108. symbols_parser&
  109. operator=(symbols_parser const& rhs)
  110. {
  111. name_ = rhs.name_;
  112. lookup = rhs.lookup;
  113. return *this;
  114. }
  115. void clear()
  116. {
  117. lookup->clear();
  118. }
  119. struct adder;
  120. struct remover;
  121. template <typename Str>
  122. adder const&
  123. operator=(Str const& str)
  124. {
  125. lookup->clear();
  126. return add(str);
  127. }
  128. template <typename Str>
  129. friend adder const&
  130. operator+=(symbols_parser& sym, Str const& str)
  131. {
  132. return sym.add(str);
  133. }
  134. template <typename Str>
  135. friend remover const&
  136. operator-=(symbols_parser& sym, Str const& str)
  137. {
  138. return sym.remove(str);
  139. }
  140. template <typename F>
  141. void for_each(F f) const
  142. {
  143. lookup->for_each(f);
  144. }
  145. template <typename Str>
  146. value_type& at(Str const& str)
  147. {
  148. return *lookup->add(traits::get_string_begin<char_type>(str)
  149. , traits::get_string_end<char_type>(str), T());
  150. }
  151. template <typename Iterator>
  152. value_type* prefix_find(Iterator& first, Iterator const& last)
  153. {
  154. return lookup->find(first, last, case_compare<Encoding>());
  155. }
  156. template <typename Iterator>
  157. value_type const* prefix_find(Iterator& first, Iterator const& last) const
  158. {
  159. return lookup->find(first, last, case_compare<Encoding>());
  160. }
  161. template <typename Str>
  162. value_type* find(Str const& str)
  163. {
  164. return find_impl(traits::get_string_begin<char_type>(str)
  165. , traits::get_string_end<char_type>(str));
  166. }
  167. template <typename Str>
  168. value_type const* find(Str const& str) const
  169. {
  170. return find_impl(traits::get_string_begin<char_type>(str)
  171. , traits::get_string_end<char_type>(str));
  172. }
  173. private:
  174. template <typename Iterator>
  175. value_type* find_impl(Iterator begin, Iterator end)
  176. {
  177. value_type* r = lookup->find(begin, end, case_compare<Encoding>());
  178. return begin == end ? r : 0;
  179. }
  180. template <typename Iterator>
  181. value_type const* find_impl(Iterator begin, Iterator end) const
  182. {
  183. value_type const* r = lookup->find(begin, end, case_compare<Encoding>());
  184. return begin == end ? r : 0;
  185. }
  186. public:
  187. template <typename Iterator, typename Context, typename Attribute>
  188. bool parse(Iterator& first, Iterator const& last
  189. , Context const& context, unused_type, Attribute& attr) const
  190. {
  191. x3::skip_over(first, last, context);
  192. if (value_type const* val_ptr
  193. = lookup->find(first, last, get_case_compare<Encoding>(context)))
  194. {
  195. x3::traits::move_to(*val_ptr, attr);
  196. return true;
  197. }
  198. return false;
  199. }
  200. void name(std::string const &str)
  201. {
  202. name_ = str;
  203. }
  204. std::string const &name() const
  205. {
  206. return name_;
  207. }
  208. struct adder
  209. {
  210. template <typename, typename = unused_type, typename = unused_type>
  211. struct result { typedef adder const& type; };
  212. adder(symbols_parser& sym)
  213. : sym(sym)
  214. {
  215. }
  216. template <typename Iterator>
  217. adder const&
  218. operator()(Iterator first, Iterator last, T const& val) const
  219. {
  220. sym.lookup->add(first, last, val);
  221. return *this;
  222. }
  223. template <typename Str>
  224. adder const&
  225. operator()(Str const& s, T const& val = T()) const
  226. {
  227. sym.lookup->add(traits::get_string_begin<char_type>(s)
  228. , traits::get_string_end<char_type>(s), val);
  229. return *this;
  230. }
  231. template <typename Str>
  232. adder const&
  233. operator,(Str const& s) const
  234. {
  235. sym.lookup->add(traits::get_string_begin<char_type>(s)
  236. , traits::get_string_end<char_type>(s), T());
  237. return *this;
  238. }
  239. symbols_parser& sym;
  240. };
  241. struct remover
  242. {
  243. template <typename, typename = unused_type, typename = unused_type>
  244. struct result { typedef remover const& type; };
  245. remover(symbols_parser& sym)
  246. : sym(sym)
  247. {
  248. }
  249. template <typename Iterator>
  250. remover const&
  251. operator()(Iterator const& first, Iterator const& last) const
  252. {
  253. sym.lookup->remove(first, last);
  254. return *this;
  255. }
  256. template <typename Str>
  257. remover const&
  258. operator()(Str const& s) const
  259. {
  260. sym.lookup->remove(traits::get_string_begin<char_type>(s)
  261. , traits::get_string_end<char_type>(s));
  262. return *this;
  263. }
  264. template <typename Str>
  265. remover const&
  266. operator,(Str const& s) const
  267. {
  268. sym.lookup->remove(traits::get_string_begin<char_type>(s)
  269. , traits::get_string_end<char_type>(s));
  270. return *this;
  271. }
  272. symbols_parser& sym;
  273. };
  274. adder add;
  275. remover remove;
  276. shared_ptr<Lookup> lookup;
  277. std::string name_;
  278. };
  279. template <typename Encoding, typename T, typename Lookup>
  280. struct get_info<symbols_parser<Encoding, T, Lookup>>
  281. {
  282. typedef std::string result_type;
  283. result_type operator()(symbols_parser< Encoding, T
  284. , Lookup
  285. > const& symbols) const
  286. {
  287. return symbols.name();
  288. }
  289. };
  290. namespace standard
  291. {
  292. template <typename T = unused_type>
  293. using symbols = symbols_parser<char_encoding::standard, T>;
  294. }
  295. using standard::symbols;
  296. #ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
  297. namespace standard_wide
  298. {
  299. template <typename T = unused_type>
  300. using symbols = symbols_parser<char_encoding::standard_wide, T>;
  301. }
  302. #endif
  303. namespace ascii
  304. {
  305. template <typename T = unused_type>
  306. using symbols = symbols_parser<char_encoding::ascii, T>;
  307. }
  308. namespace iso8859_1
  309. {
  310. template <typename T = unused_type>
  311. using symbols = symbols_parser<char_encoding::iso8859_1, T>;
  312. }
  313. }}}
  314. #if defined(BOOST_MSVC)
  315. # pragma warning(pop)
  316. #endif
  317. #endif