fusion_map.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*=============================================================================
  2. Copyright (c) 2001-2015 Joel de Guzman
  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. #include <boost/detail/lightweight_test.hpp>
  7. #include <boost/spirit/home/x3.hpp>
  8. #include <boost/fusion/include/at_key.hpp>
  9. #include <boost/fusion/include/make_map.hpp>
  10. #include <boost/fusion/adapted/struct.hpp>
  11. #include <string>
  12. #include <iostream>
  13. #include "test.hpp"
  14. struct AdaptedStruct {
  15. std::string key1;
  16. std::string key2;
  17. };
  18. class key1_attr {};
  19. class key2_attr {};
  20. BOOST_FUSION_ADAPT_ASSOC_STRUCT(
  21. AdaptedStruct,
  22. (std::string, key1, class key1_attr)
  23. (std::string, key2, class key2_attr)
  24. )
  25. template <class Parser, class Attribute>
  26. bool test_attr(const std::string in,Parser const& p, Attribute& attr) {
  27. auto it = in.begin();
  28. return boost::spirit::x3::parse(it,in.end(), p, attr);
  29. }
  30. int
  31. main()
  32. {
  33. using spirit_test::test;
  34. using boost::spirit::x3::lit;
  35. using boost::spirit::x3::attr;
  36. using boost::spirit::x3::char_;
  37. using boost::spirit::x3::eps;
  38. namespace fusion = boost::fusion;
  39. { // parsing sequence directly into fusion map
  40. auto const key1 = lit("key1") >> attr(key1_attr());
  41. auto const kv1 = key1 >> lit("=") >> +char_;
  42. {
  43. auto attr_ = fusion::make_map<key1_attr>(std::string());
  44. BOOST_TEST(test_attr("key1=ABC", kv1, attr_));
  45. BOOST_TEST(fusion::at_key<key1_attr>(attr_) == "ABC");
  46. }
  47. {
  48. AdaptedStruct attr_;
  49. BOOST_TEST(test_attr("key1=ABC", kv1, attr_));
  50. BOOST_TEST(attr_.key1 == "ABC");
  51. BOOST_TEST(attr_.key2 == "");
  52. }
  53. }
  54. { // case when parser handling fusion assoc sequence
  55. // is on one side of another sequence
  56. auto const key1 = lit("key1") >> attr(key1_attr());
  57. auto const kv1 = key1 >> lit("=") >> +~char_(';');
  58. AdaptedStruct attr_;
  59. BOOST_TEST(test_attr("key1=ABC", eps >> (kv1 % ';') , attr_));
  60. BOOST_TEST(attr_.key1 == "ABC");
  61. BOOST_TEST(attr_.key2 == "");
  62. }
  63. { // parsing repeated sequence directly into fusion map (overwrite)
  64. auto const key1 = lit("key1") >> attr(key1_attr());
  65. auto const kv1 = key1 >> lit("=") >> +~char_(';');
  66. {
  67. auto attr_ = fusion::make_map<key1_attr>(std::string());
  68. BOOST_TEST(test_attr("key1=ABC;key1=XYZ", kv1 % ';', attr_));
  69. BOOST_TEST(fusion::at_key<key1_attr>(attr_) == "XYZ");
  70. }
  71. {
  72. AdaptedStruct attr_;
  73. BOOST_TEST(test_attr("key1=ABC;key1=XYZ", kv1 % ';', attr_));
  74. BOOST_TEST(attr_.key1 == "XYZ");
  75. }
  76. }
  77. { // parsing repeated sequence directly into fusion map (append)
  78. /* NOT IMPLEMENTED
  79. auto const key1 = lit("key1") >> attr(key1_attr());
  80. auto const kv1 = key1 >> lit("=") >> +char_;
  81. auto attr_ = fusion::make_map<key1_attr>(std::vector<std::string>());
  82. BOOST_TEST(test_attr("key1=ABC;key1=XYZ", kv1 % ";", attr_));
  83. BOOST_TEST(fusion::at_key<key1_attr>(attr_) == {"ABC","XYZ"});
  84. */
  85. }
  86. { // alternative over key-value pairs
  87. auto const key1 = lit("key1") >> attr(key1_attr());
  88. auto const key2 = lit("key2") >> attr(key2_attr());
  89. auto const kv1 = key1 >> lit("=") >> +~char_(';');
  90. auto const kv2 = key2 >> lit("=") >> +~char_(';');
  91. auto attr_ = fusion::make_map<key1_attr, key2_attr>(std::string(),std::string());
  92. BOOST_TEST(test_attr("key2=XYZ;key1=ABC", (kv1|kv2) % ';', attr_));
  93. BOOST_TEST(fusion::at_key<key1_attr>(attr_) == "ABC");
  94. BOOST_TEST(fusion::at_key<key2_attr>(attr_) == "XYZ");
  95. }
  96. { // parsing sequence where key is a variant
  97. namespace x3 = boost::spirit::x3;
  98. auto key1 = lit("key1") >> attr(key1_attr());
  99. auto key2 = lit("key2") >> attr(key2_attr());
  100. auto keys = key1 | key2;
  101. auto pair = keys >> lit("=") >> +~char_(';');
  102. {
  103. auto attr_ = fusion::make_map<key1_attr,key2_attr>(std::string(),std::string());
  104. BOOST_TEST(test_attr("key1=ABC;key2=XYZ", pair % ';', attr_));
  105. BOOST_TEST(fusion::at_key<key1_attr>(attr_) == "ABC");
  106. BOOST_TEST(fusion::at_key<key2_attr>(attr_) == "XYZ");
  107. }
  108. {
  109. AdaptedStruct attr_;
  110. BOOST_TEST(test_attr("key1=ABC;key2=XYZ", pair % ';', attr_));
  111. BOOST_TEST(fusion::at_key<key1_attr>(attr_) == "ABC");
  112. BOOST_TEST(fusion::at_key<key2_attr>(attr_) == "XYZ");
  113. }
  114. }
  115. return boost::report_errors();
  116. }