| // Copyright (c) 2001-2010 Hartmut Kaiser |
| // |
| // Distributed under the Boost Software License, Version 1.0. (See accompanying |
| // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| |
| // The purpose of this example is to show how to parse arbitrary key/value |
| // pairs delimited by some separator into a std::vector. The difference to |
| // the example 'key_value_sequence.cpp' is that we preserve the order of the |
| // elements in the parsed sequence as well as possibly existing duplicates. |
| // In addition to the example 'key_value_sequence_ordered.cpp' we allow for |
| // empty values, i.e. the grammar allows to distinguish between 'key=;' and |
| // 'key;", where the first stores an empty string as the value, while the |
| // second does not initialize the optional holding the value. |
| // |
| // For a more elaborate explanation see here: http://spirit.sourceforge.net/home/?p=371 |
| |
| #include <boost/spirit/include/qi.hpp> |
| #include <boost/fusion/include/std_pair.hpp> |
| |
| #include <iostream> |
| #include <map> |
| |
| namespace client |
| { |
| namespace qi = boost::spirit::qi; |
| |
| typedef std::pair<std::string, boost::optional<std::string> > pair_type; |
| typedef std::vector<pair_type> pairs_type; |
| |
| template <typename Iterator> |
| struct key_value_sequence_empty_value |
| : qi::grammar<Iterator, pairs_type()> |
| { |
| key_value_sequence_empty_value() |
| : key_value_sequence_empty_value::base_type(query) |
| { |
| query = pair >> *((qi::lit(';') | '&') >> pair); |
| pair = key >> -('=' >> -value); |
| key = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9"); |
| value = +qi::char_("a-zA-Z_0-9"); |
| } |
| |
| qi::rule<Iterator, pairs_type()> query; |
| qi::rule<Iterator, pair_type()> pair; |
| qi::rule<Iterator, std::string()> key, value; |
| }; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| int main() |
| { |
| namespace qi = boost::spirit::qi; |
| |
| std::string input("key1=value1;key2;key3=value3;key4="); |
| std::string::iterator begin = input.begin(); |
| std::string::iterator end = input.end(); |
| |
| client::key_value_sequence_empty_value<std::string::iterator> p; |
| client::pairs_type m; |
| |
| if (!qi::parse(begin, end, p, m)) |
| { |
| std::cout << "-------------------------------- \n"; |
| std::cout << "Parsing failed\n"; |
| std::cout << "-------------------------------- \n"; |
| } |
| else |
| { |
| std::cout << "-------------------------------- \n"; |
| std::cout << "Parsing succeeded, found entries:\n"; |
| client::pairs_type::iterator end = m.end(); |
| for (client::pairs_type::iterator it = m.begin(); it != end; ++it) |
| { |
| std::cout << (*it).first; |
| if ((*it).second) |
| std::cout << "=" << boost::get<std::string>((*it).second); |
| std::cout << std::endl; |
| } |
| std::cout << "---------------------------------\n"; |
| } |
| return 0; |
| } |
| |