attribute1.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Hartmut Kaiser
  3. Copyright (c) 2001-2011 Joel de Guzman
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. =============================================================================*/
  7. #include <boost/config/warning_disable.hpp>
  8. #include <boost/detail/lightweight_test.hpp>
  9. #include <boost/spirit/include/phoenix_limits.hpp>
  10. #include <boost/fusion/include/struct.hpp>
  11. #include <boost/fusion/include/nview.hpp>
  12. #include <boost/spirit/include/qi_char.hpp>
  13. #include <boost/spirit/include/qi_string.hpp>
  14. #include <boost/spirit/include/qi_numeric.hpp>
  15. #include <boost/spirit/include/qi_operator.hpp>
  16. #include <boost/spirit/include/qi_nonterminal.hpp>
  17. #include <boost/spirit/include/qi_auxiliary.hpp>
  18. #include <iostream>
  19. #include <vector>
  20. #include <string>
  21. #include "test.hpp"
  22. ///////////////////////////////////////////////////////////////////////////////
  23. struct test_data
  24. {
  25. std::string s1;
  26. std::string s2;
  27. int i1;
  28. double d1;
  29. std::string s3;
  30. };
  31. BOOST_FUSION_ADAPT_STRUCT(
  32. test_data,
  33. (int, i1)
  34. (std::string, s1)
  35. (std::string, s2)
  36. (std::string, s3)
  37. (double, d1)
  38. )
  39. ///////////////////////////////////////////////////////////////////////////////
  40. struct test_int_data1
  41. {
  42. int i;
  43. };
  44. // we provide a custom attribute transformation taking copy of the actual
  45. // attribute value, simulating more complex type transformations
  46. namespace boost { namespace spirit { namespace traits
  47. {
  48. template <>
  49. struct transform_attribute<test_int_data1, int, qi::domain>
  50. {
  51. typedef int type;
  52. static int pre(test_int_data1& d) { return d.i; }
  53. static void post(test_int_data1& d, int i) { d.i = i; }
  54. static void fail(test_int_data1&) {}
  55. };
  56. }}}
  57. ///////////////////////////////////////////////////////////////////////////////
  58. struct test_int_data2
  59. {
  60. int i;
  61. };
  62. // we provide a simple custom attribute transformation utilizing passing the
  63. // actual attribute by reference
  64. namespace boost { namespace spirit { namespace traits
  65. {
  66. template <>
  67. struct transform_attribute<test_int_data2, int, qi::domain>
  68. {
  69. typedef int& type;
  70. static int& pre(test_int_data2& d) { return d.i; }
  71. static void post(test_int_data2&, int const&) {}
  72. static void fail(test_int_data2&) {}
  73. };
  74. }}}
  75. ///////////////////////////////////////////////////////////////////////////////
  76. int
  77. main()
  78. {
  79. using spirit_test::test_attr;
  80. namespace qi = boost::spirit::qi;
  81. namespace fusion = boost::fusion;
  82. // testing attribute reordering in a fusion sequence as explicit attribute
  83. {
  84. typedef fusion::result_of::as_nview<test_data, 1, 0, 4>::type
  85. test_view;
  86. test_data d1 = { "", "", 0, 0.0, "" };
  87. test_view v1 = fusion::as_nview<1, 0, 4>(d1);
  88. BOOST_TEST(test_attr("s1,2,1.5",
  89. *(qi::char_ - ',') >> ',' >> qi::int_ >> ',' >> qi::double_, v1));
  90. BOOST_TEST(d1.i1 == 2 && d1.s1 == "s1" && d1.d1 == 1.5);
  91. test_data d2 = { "", "", 0, 0.0, "" };
  92. test_view v2 = fusion::as_nview<1, 0, 4>(d2);
  93. BOOST_TEST(test_attr("s1, 2, 1.5 ",
  94. *(qi::char_ - ',') >> ',' >> qi::int_ >> ',' >> qi::double_,
  95. v2, qi::space));
  96. BOOST_TEST(d2.i1 == 2 && d2.s1 == "s1" && d2.d1 == 1.5);
  97. }
  98. {
  99. // this won't work without the second template argument as *digit
  100. // exposes a vector<char> as its attribute
  101. std::string str;
  102. BOOST_TEST(test_attr("123"
  103. , qi::attr_cast<std::string, std::string>(*qi::digit), str));
  104. BOOST_TEST(str == "123");
  105. }
  106. // testing attribute reordering in a fusion sequence involving a rule
  107. {
  108. typedef fusion::result_of::as_nview<test_data, 1, 0, 4>::type
  109. test_view;
  110. std::vector<test_data> v;
  111. qi::rule<char const*, test_view()> r1 =
  112. *(qi::char_ - ',') >> ',' >> qi::int_ >> ',' >> qi::double_;
  113. BOOST_TEST(test_attr("s1,2,1.5\ns2,4,3.5", r1 % qi::eol, v));
  114. BOOST_TEST(v.size() == 2 &&
  115. v[0].i1 == 2 && v[0].s1 == "s1" && v[0].d1 == 1.5 &&
  116. v[1].i1 == 4 && v[1].s1 == "s2" && v[1].d1 == 3.5);
  117. qi::rule<char const*, test_view(), qi::blank_type> r2 =
  118. *(qi::char_ - ',') >> ',' >> qi::int_ >> ',' >> qi::double_;
  119. v.clear();
  120. BOOST_TEST(test_attr("s1, 2, 1.5 \n s2, 4, 3.5", r2 % qi::eol, v, qi::blank));
  121. BOOST_TEST(v.size() == 2 &&
  122. v[0].i1 == 2 && v[0].s1 == "s1" && v[0].d1 == 1.5 &&
  123. v[1].i1 == 4 && v[1].s1 == "s2" && v[1].d1 == 3.5);
  124. }
  125. // testing explicit transformation if attribute needs to be copied
  126. {
  127. test_int_data1 d = { 0 };
  128. BOOST_TEST(test_attr("1", qi::attr_cast(qi::int_), d));
  129. BOOST_TEST(d.i == 1);
  130. BOOST_TEST(test_attr("2", qi::attr_cast<test_int_data1>(qi::int_), d));
  131. BOOST_TEST(d.i == 2);
  132. BOOST_TEST(test_attr("3", qi::attr_cast<test_int_data1, int>(qi::int_), d));
  133. BOOST_TEST(d.i == 3);
  134. }
  135. {
  136. std::vector<test_int_data1> v;
  137. BOOST_TEST(test_attr("1,2", qi::attr_cast(qi::int_) % ',', v));
  138. BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
  139. v.clear();
  140. BOOST_TEST(test_attr("1,2"
  141. , qi::attr_cast<test_int_data1>(qi::int_) % ',', v));
  142. BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
  143. v.clear();
  144. BOOST_TEST(test_attr("1,2"
  145. , qi::attr_cast<test_int_data1, int>(qi::int_) % ',', v));
  146. BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
  147. }
  148. return boost::report_errors();
  149. }