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
23namespace 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 {
34 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///////////////////////////////////////////////////////////////////////////////
50int 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(first&: begin, last: end, expr: p, attr&: 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>(opt&: (*it).second);
77 std::cout << std::endl;
78 }
79 std::cout << "---------------------------------\n";
80 }
81 return 0;
82}
83
84

source code of boost/libs/spirit/example/qi/key_value_sequence_empty_value.cpp