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
7 #include <string>
8 #include <vector>
9
10 #include <boost/array.hpp>
11
12 #include <boost/spirit/include/qi.hpp>
13
14 namespace qi = boost::spirit::qi;
15 namespace ascii = boost::spirit::ascii;
16
17 ///////////////////////////////////////////////////////////////////////////////
18 // create a wrapper holding the boost::array and a current insertion point
19 namespace client
20 {
21 namespace detail
22 {
23 template <typename T>
24 struct adapt_array;
25
26 template <typename T, std::size_t N>
27 struct adapt_array<boost::array<T, N> >
28 {
29 typedef boost::array<T, N> array_type;
30
adapt_arrayclient::detail::adapt_array31 adapt_array(array_type& arr)
32 : arr_(arr), current_(0) {}
33
34 // expose a push_back function compatible with std containers
push_backclient::detail::adapt_array35 bool push_back(typename array_type::value_type const& val)
36 {
37 // if the array is full, we need to bail out
38 // returning false will fail the parse
39 if (current_ >= N)
40 return false;
41
42 arr_[current_++] = val;
43 return true;
44 }
45
46 array_type& arr_;
47 std::size_t current_;
48 };
49 }
50
51 namespace result_of
52 {
53 template <typename T>
54 struct adapt_array;
55
56 template <typename T, std::size_t N>
57 struct adapt_array<boost::array<T, N> >
58 {
59 typedef detail::adapt_array<boost::array<T, N> > type;
60 };
61 }
62
63 template <typename T, std::size_t N>
64 inline detail::adapt_array<boost::array<T, N> >
adapt_array(boost::array<T,N> & arr)65 adapt_array(boost::array<T, N>& arr)
66 {
67 return detail::adapt_array<boost::array<T, N> >(arr);
68 }
69 }
70
71 ///////////////////////////////////////////////////////////////////////////////
72 // specialize Spirit's container specific customization points for our adaptor
73 namespace boost { namespace spirit { namespace traits
74 {
75 template <typename T, std::size_t N>
76 struct is_container<client::detail::adapt_array<boost::array<T, N> > >
77 : boost::mpl::true_
78 {};
79
80 template <typename T, std::size_t N>
81 struct container_value<client::detail::adapt_array<boost::array<T, N> > >
82 {
83 typedef T type; // value type of container
84 };
85
86 template <typename T, std::size_t N>
87 struct push_back_container<
88 client::detail::adapt_array<boost::array<T, N> >, T>
89 {
callboost::spirit::traits::push_back_container90 static bool call(client::detail::adapt_array<boost::array<T, N> >& c
91 , T const& val)
92 {
93 return c.push_back(val);
94 }
95 };
96 }}}
97
main()98 int main()
99 {
100 typedef std::string::const_iterator iterator_type;
101 typedef boost::array<int, 2> array_type;
102 typedef client::result_of::adapt_array<array_type>::type adapted_type;
103
104 array_type arr;
105
106 std::string str = "1 2";
107 iterator_type iter = str.begin();
108 iterator_type end = str.end();
109
110 qi::rule<iterator_type, adapted_type(), ascii::space_type> r = *qi::int_;
111
112 adapted_type attr = client::adapt_array(arr);
113 bool result = qi::phrase_parse(iter, end, r, ascii::space, attr);
114
115 if (result)
116 std::cout << "Parsed: " << arr[0] << ", " << arr[1] << std::endl;
117
118 return 0;
119 }
120