• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //  Copyright (c) 2001-2010 Hartmut Kaiser
2 //
3 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
4 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 // The purpose of this example is to show how to parse arbitrary key/value
7 // pairs delimited by some separator into a std::vector. The difference to
8 // the example 'key_value_sequence.cpp' is that we preserve the order of the
9 // elements in the parsed sequence as well as possibly existing duplicates.
10 // In addition to the example 'key_value_sequence_ordered.cpp' we allow for
11 // empty values, i.e. the grammar allows to distinguish between 'key=;' and
12 // 'key;", where the first stores an empty string as the value, while the
13 // second does not initialize the optional holding the value.
14 //
15 // For a more elaborate explanation see here: http://spirit.sourceforge.net/home/?p=371
16 
17 #include <boost/spirit/include/qi.hpp>
18 #include <boost/fusion/include/std_pair.hpp>
19 
20 #include <iostream>
21 #include <map>
22 
23 namespace client
24 {
25     namespace qi = boost::spirit::qi;
26 
27     typedef std::pair<std::string, boost::optional<std::string> > pair_type;
28     typedef std::vector<pair_type> pairs_type;
29 
30     template <typename Iterator>
31     struct key_value_sequence_empty_value
32       : qi::grammar<Iterator, pairs_type()>
33     {
key_value_sequence_empty_valueclient::key_value_sequence_empty_value34         key_value_sequence_empty_value()
35           : key_value_sequence_empty_value::base_type(query)
36         {
37             query =  pair >> *((qi::lit(';') | '&') >> pair);
38             pair  =  key >> -('=' >> -value);
39             key   =  qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9");
40             value = +qi::char_("a-zA-Z_0-9");
41         }
42 
43         qi::rule<Iterator, pairs_type()> query;
44         qi::rule<Iterator, pair_type()> pair;
45         qi::rule<Iterator, std::string()> key, value;
46     };
47 }
48 
49 ///////////////////////////////////////////////////////////////////////////////
main()50 int main()
51 {
52     namespace qi = boost::spirit::qi;
53 
54     std::string input("key1=value1;key2;key3=value3;key4=");
55     std::string::iterator begin = input.begin();
56     std::string::iterator end = input.end();
57 
58     client::key_value_sequence_empty_value<std::string::iterator> p;
59     client::pairs_type m;
60 
61     if (!qi::parse(begin, end, p, m))
62     {
63         std::cout << "-------------------------------- \n";
64         std::cout << "Parsing failed\n";
65         std::cout << "-------------------------------- \n";
66     }
67     else
68     {
69         std::cout << "-------------------------------- \n";
70         std::cout << "Parsing succeeded, found entries:\n";
71         client::pairs_type::iterator end = m.end();
72         for (client::pairs_type::iterator it = m.begin(); it != end; ++it)
73         {
74             std::cout << (*it).first;
75             if ((*it).second)
76                 std::cout << "=" << boost::get<std::string>((*it).second);
77             std::cout << std::endl;
78         }
79         std::cout << "---------------------------------\n";
80     }
81     return 0;
82 }
83 
84