key_value_sequence_empty_value.cpp 2.9 KB

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