symbols.hpp 9.7 KB

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