1 /*=============================================================================
2     Copyright (c) 2001-2003 Hartmut Kaiser
3     http://spirit.sourceforge.net/
4 
5     Use, modification and distribution is subject to the Boost Software
6     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7     http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9 ///////////////////////////////////////////////////////////////////////////////
10 // This sample shows the usage of the list_p utility parser
11 //  1. parsing a simple ',' delimited list w/o item formatting
12 //  2. parsing a CSV list (comma separated values - strings, integers or reals)
13 //  3. parsing a token list (token separated values - strings, integers or
14 //     reals)
15 // with an action parser directly attached to the item part of the list_p
16 // generated parser
17 
18 #include <string>
19 #include <iostream>
20 #include <cassert>
21 #include <vector>
22 
23 #include <boost/spirit/include/classic_core.hpp>
24 #include <boost/spirit/include/classic_confix.hpp>
25 #include <boost/spirit/include/classic_lists.hpp>
26 #include <boost/spirit/include/classic_escape_char.hpp>
27 
28 ///////////////////////////////////////////////////////////////////////////////
29 using namespace std;
30 using namespace BOOST_SPIRIT_CLASSIC_NS;
31 
32 ///////////////////////////////////////////////////////////////////////////////
33 // actor, attached to the list_p parser
34 class list_actor
35 {
36 public:
list_actor(std::vector<std::string> & vec_)37     list_actor (std::vector<std::string> &vec_) : vec(vec_) {}
38 
39     // The following operator() is called by the action parser generated by
40     // attaching this actor to a list_p generated list parser.
41 
42     template <typename ActionIterT>
operator ()(ActionIterT const & first,ActionIterT const & last) const43     void operator() (ActionIterT const &first, ActionIterT const &last) const
44     {
45         vec.push_back(std::string(first, last-first));
46     }
47 
48 private:
49     std::vector<std::string> &vec;
50 };
51 
52 ///////////////////////////////////////////////////////////////////////////////
53 // main entry point
main()54 int main ()
55 {
56     // 1. parsing a simple ',' delimited list w/o item formatting
57     char const*                 plist_wo_item = "element1,element2,element3";
58     rule<>                      list_wo_item;
59     std::vector<std::string>    vec_list;
60 
61     list_wo_item =
62             list_p[push_back_a(vec_list)]
63         ;
64 
65     parse_info<> result = parse (plist_wo_item, list_wo_item);
66 
67     cout << "-----------------------------------------------------------------"
68         << endl;
69 
70     if (result.hit)
71     {
72         cout
73             << "Parsing simple list" << endl
74             << "\t" << plist_wo_item << endl
75             << "Parsed successfully!" << endl << endl;
76 
77         cout
78             << "Actor was called " << (int)vec_list.size()
79             << " times: " << endl;
80 
81         cout
82             << "Results got from the list parser:" << endl;
83         for (std::vector<std::string>::iterator it = vec_list.begin();
84              it != vec_list.end(); ++it)
85         {
86             cout << *it << endl;
87         }
88     }
89     else
90     {
91         cout << "Failed to parse simple list!" << endl;
92     }
93 
94     cout << endl;
95 
96     // 2. parsing a CSV list (comma separated values - strings, integers or
97     // reals)
98     char const *plist_csv = "\"string\",\"string with an embedded \\\"\","
99         "12345,0.12345e4,,2";
100     rule<> list_csv, list_csv_item;
101     std::vector<std::string> vec_item;
102 
103     vec_list.clear();
104 
105     list_csv_item =
106         !(
107                 confix_p('\"', *c_escape_ch_p, '\"')
108             |   longest_d[real_p | int_p]
109         );
110 
111     list_csv =
112             list_p(
113                 list_csv_item[push_back_a(vec_item)],
114                 ','
115             )[push_back_a(vec_list)]
116         ;
117 
118     result = parse (plist_csv, list_csv);
119 
120     cout << "-----------------------------------------------------------------"
121         << endl;
122     if (result.hit)
123     {
124         cout
125             << "Parsing CSV list (comma separated values) " << endl
126             << "\t" << plist_csv << endl
127             << "Parsed successfully!" << endl << endl;
128 
129         if (result.full)
130         {
131             cout << "Matched " << (int)vec_list.size() <<
132                 " list elements (full list): " << endl;
133         }
134         else
135         {
136             cout << "Matched " << (int)vec_list.size() <<
137                 " list elements: " << endl;
138         }
139 
140         cout << "The list parser matched:" << endl;
141         for (std::vector<std::string>::iterator itl = vec_list.begin();
142                 itl != vec_list.end(); ++itl)
143         {
144             cout << *itl << endl;
145         }
146 
147         cout << endl << "Item(s) got directly from the item parser:" << endl;
148         for (std::vector<std::string>::iterator it = vec_item.begin();
149                 it != vec_item.end(); ++it)
150         {
151             cout << *it << endl;
152         }
153 
154     }
155     else
156     {
157         cout << "Failed to parse CSV list!" << endl;
158     }
159 
160     cout << endl;
161 
162     // 3. parsing a token list (token separated values - strings, integers or
163     // reals) with an action parser directly attached to the item part of the
164     // list_p generated parser
165     char const *plist_csv_direct = "\"string\"<par>\"string with an embedded "
166         "\\\"\"<par>12345<par>0.12345e4";
167     rule<> list_csv_direct, list_csv_direct_item;
168 
169     vec_list.clear();
170     vec_item.clear();
171 
172     // Note: the list parser is here generated through the list_p.direct()
173     // generator function. This inhibits re-attachment of the item_actor_direct
174     // during parser construction (see: comment in utility/lists.hpp)
175     list_csv_direct_item =
176             confix_p('\"', *c_escape_ch_p, '\"')
177         |   longest_d[real_p | int_p]
178         ;
179 
180     list_csv_direct =
181             list_p.direct(
182                 (*list_csv_direct_item)[list_actor(vec_item)],
183                 "<par>"
184             )[list_actor(vec_list)]
185         ;
186 
187     result = parse (plist_csv_direct, list_csv_direct);
188 
189     cout << "-----------------------------------------------------------------"
190         << endl;
191     if (result.hit)
192     {
193         cout
194             << "Parsing CSV list (comma separated values)" << endl
195             << "The list parser was generated with 'list_p.direct()'" << endl
196             << "\t" << plist_csv_direct << endl
197             << "Parsed successfully!" << endl << endl;
198 
199         if (result.full)
200         {
201             cout << "Matched " << vec_list.size() <<
202                 " list elements (full list): " << endl;
203         }
204         else
205         {
206             cout << "Matched " << vec_list.size() <<
207                 " list elements: " << endl;
208         }
209 
210         cout << "The list parser matched:" << endl;
211         for (std::vector<std::string>::iterator itl = vec_list.begin();
212                 itl != vec_list.end(); ++itl)
213         {
214             cout << *itl << endl;
215         }
216 
217         cout << endl << "Items got directly from the item parser:" << endl;
218         for (std::vector<std::string>::iterator it = vec_item.begin();
219                 it != vec_item.end(); ++it)
220         {
221             cout << *it << endl;
222         }
223 
224     }
225     else
226     {
227         cout << "Failed to parse CSV list!" << endl;
228     }
229 
230     cout << endl;
231 
232     return 0;
233 }
234