boost_array.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // Copyright (c) 2009 Erik Bryan
  2. // Copyright (c) 2007-2010 Hartmut Kaiser
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #include <string>
  7. #include <vector>
  8. #include <boost/array.hpp>
  9. #include <boost/spirit/include/qi.hpp>
  10. namespace qi = boost::spirit::qi;
  11. namespace ascii = boost::spirit::ascii;
  12. ///////////////////////////////////////////////////////////////////////////////
  13. // create a wrapper holding the boost::array and a current insertion point
  14. namespace client
  15. {
  16. namespace detail
  17. {
  18. template <typename T>
  19. struct adapt_array;
  20. template <typename T, std::size_t N>
  21. struct adapt_array<boost::array<T, N> >
  22. {
  23. typedef boost::array<T, N> array_type;
  24. adapt_array(array_type& arr)
  25. : arr_(arr), current_(0) {}
  26. // expose a push_back function compatible with std containers
  27. bool push_back(typename array_type::value_type const& val)
  28. {
  29. // if the array is full, we need to bail out
  30. // returning false will fail the parse
  31. if (current_ >= N)
  32. return false;
  33. arr_[current_++] = val;
  34. return true;
  35. }
  36. array_type& arr_;
  37. std::size_t current_;
  38. };
  39. }
  40. namespace result_of
  41. {
  42. template <typename T>
  43. struct adapt_array;
  44. template <typename T, std::size_t N>
  45. struct adapt_array<boost::array<T, N> >
  46. {
  47. typedef detail::adapt_array<boost::array<T, N> > type;
  48. };
  49. }
  50. template <typename T, std::size_t N>
  51. inline detail::adapt_array<boost::array<T, N> >
  52. adapt_array(boost::array<T, N>& arr)
  53. {
  54. return detail::adapt_array<boost::array<T, N> >(arr);
  55. }
  56. }
  57. ///////////////////////////////////////////////////////////////////////////////
  58. // specialize Spirit's container specific customization points for our adaptor
  59. namespace boost { namespace spirit { namespace traits
  60. {
  61. template <typename T, std::size_t N>
  62. struct is_container<client::detail::adapt_array<boost::array<T, N> > >
  63. : boost::mpl::true_
  64. {};
  65. template <typename T, std::size_t N>
  66. struct container_value<client::detail::adapt_array<boost::array<T, N> > >
  67. {
  68. typedef T type; // value type of container
  69. };
  70. template <typename T, std::size_t N>
  71. struct push_back_container<
  72. client::detail::adapt_array<boost::array<T, N> >, T>
  73. {
  74. static bool call(client::detail::adapt_array<boost::array<T, N> >& c
  75. , T const& val)
  76. {
  77. return c.push_back(val);
  78. }
  79. };
  80. }}}
  81. int main()
  82. {
  83. typedef std::string::const_iterator iterator_type;
  84. typedef boost::array<int, 2> array_type;
  85. typedef client::result_of::adapt_array<array_type>::type adapted_type;
  86. array_type arr;
  87. std::string str = "1 2";
  88. iterator_type iter = str.begin();
  89. iterator_type end = str.end();
  90. qi::rule<iterator_type, adapted_type(), ascii::space_type> r = *qi::int_;
  91. adapted_type attr = client::adapt_array(arr);
  92. bool result = qi::phrase_parse(iter, end, r, ascii::space, attr);
  93. if (result)
  94. std::cout << "Parsed: " << arr[0] << ", " << arr[1] << std::endl;
  95. return 0;
  96. }