• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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