1 /*=============================================================================
2     Copyright (c) 2002-2010 Hartmut Kaiser
3     Copyright (c) 2002-2010 Joel de Guzman
4 
5     Distributed under the Boost Software License, Version 1.0. (See accompanying
6     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 =============================================================================*/
8 ///////////////////////////////////////////////////////////////////////////////
9 //
10 //  This sample demonstrates a generator for a comma separated list of numbers.
11 //  No actions. It is based on the example qi/num_lists.cpp for reading in
12 //  some numbers to generate.
13 //
14 ///////////////////////////////////////////////////////////////////////////////
15 
16 #include <boost/config/warning_disable.hpp>
17 #include <boost/spirit/include/qi.hpp>
18 #include <boost/spirit/include/karma.hpp>
19 
20 #include <iostream>
21 #include <string>
22 #include <vector>
23 
24 namespace client
25 {
26     ///////////////////////////////////////////////////////////////////////////
27     //  Our number list parser, please see the example qi/numlist1.cpp for
28     //  more information
29     ///////////////////////////////////////////////////////////////////////////
30     template <typename Iterator>
parse_numbers(Iterator first,Iterator last,std::vector<double> & v)31     bool parse_numbers(Iterator first, Iterator last, std::vector<double>& v)
32     {
33         using boost::spirit::qi::double_;
34         using boost::spirit::qi::phrase_parse;
35         using boost::spirit::ascii::space;
36 
37         bool r = phrase_parse(first, last, double_ % ',', space, v);
38         if (first != last)
39             return false;
40         return r;
41     }
42 
43     //[tutorial_karma_numlist3_complex
44     // a simple complex number representation z = a + bi
45     struct complex
46     {
complexclient::complex47         complex (double a, double b = 0.0) : a(a), b(b) {}
48 
49         double a;
50         double b;
51     };
52 
53     // the streaming operator for the type complex
54     std::ostream&
operator <<(std::ostream & os,complex const & z)55     operator<< (std::ostream& os, complex const& z)
56     {
57         os << "{" << z.a << "," << z.b << "}";
58         return os;
59     }
60     //]
61 
62     ///////////////////////////////////////////////////////////////////////////
63     //  Our number list generator
64     ///////////////////////////////////////////////////////////////////////////
65     //[tutorial_karma_numlist3
66     template <typename OutputIterator, typename Container>
generate_numbers(OutputIterator & sink,Container const & v)67     bool generate_numbers(OutputIterator& sink, Container const& v)
68     {
69         using boost::spirit::karma::stream;
70         using boost::spirit::karma::generate;
71         using boost::spirit::karma::eol;
72 
73         bool r = generate(
74             sink,                           // destination: output iterator
75             stream % eol,                   // the generator
76             v                               // the data to output
77         );
78         return r;
79     }
80     //]
81 }
82 
83 ////////////////////////////////////////////////////////////////////////////
84 //  Main program
85 ////////////////////////////////////////////////////////////////////////////
86 int
main()87 main()
88 {
89     std::cout << "/////////////////////////////////////////////////////////\n\n";
90     std::cout << "\tA comma separated list generator for Spirit...\n\n";
91     std::cout << "/////////////////////////////////////////////////////////\n\n";
92 
93     std::cout << "Give me a comma separated list of numbers.\n";
94     std::cout << "Type [q or Q] to quit\n\n";
95 
96     std::string str;
97     while (getline(std::cin, str))
98     {
99         if (str.empty() || str[0] == 'q' || str[0] == 'Q')
100             break;
101 
102         std::vector<double> v;      // here we put the data gotten from input
103         if (client::parse_numbers(str.begin(), str.end(), v))
104         {
105             // ok, we got some numbers, fill a vector of client::complex
106             // instances and print them back out
107             std::vector<client::complex> vc;
108             std::vector<double>::const_iterator end = v.end();
109             for (std::vector<double>::const_iterator it = v.begin();
110                  it != end; ++it)
111             {
112                 double real(*it);
113                 if (++it != end)
114                     vc.push_back(client::complex(real, *it));
115                 else {
116                     vc.push_back(client::complex(real));
117                     break;
118                 }
119             }
120 
121             std::cout << "-------------------------\n";
122 
123             std::string generated;
124             std::back_insert_iterator<std::string> sink(generated);
125             if (!client::generate_numbers(sink, vc))
126             {
127                 std::cout << "-------------------------\n";
128                 std::cout << "Generating failed\n";
129                 std::cout << "-------------------------\n";
130             }
131             else
132             {
133                 std::cout << "-------------------------\n";
134                 std::cout << "Generated:\n" << generated << "\n";
135                 std::cout << "-------------------------\n";
136             }
137         }
138         else
139         {
140             std::cout << "-------------------------\n";
141             std::cout << "Parsing failed\n";
142             std::cout << "-------------------------\n";
143         }
144     }
145 
146     std::cout << "Bye... :-) \n\n";
147     return 0;
148 }
149 
150 
151