reorder_struct.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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 main purpose of this example is to show how a single fusion sequence
  6. // can be filled from a parsed input of the elements in different sequences
  7. #include <boost/config/warning_disable.hpp>
  8. #include <boost/mpl/print.hpp>
  9. #include <boost/spirit/include/qi.hpp>
  10. #include <boost/fusion/include/struct.hpp>
  11. #include <boost/fusion/include/nview.hpp>
  12. #include <boost/foreach.hpp>
  13. namespace fusion = boost::fusion;
  14. namespace qi = boost::spirit::qi;
  15. ///////////////////////////////////////////////////////////////////////////////
  16. namespace client
  17. {
  18. // Our employee struct
  19. struct employee
  20. {
  21. std::string surname;
  22. std::string forename;
  23. int age;
  24. double salary;
  25. std::string department;
  26. };
  27. // define iterator type
  28. typedef std::string::const_iterator iterator_type;
  29. // This is the output routine taking a format description and the data to
  30. // print
  31. template <typename Parser, typename Sequence>
  32. bool parse(std::string const& input, Parser const& p, Sequence& s)
  33. {
  34. iterator_type begin = input.begin();
  35. return qi::parse(begin, input.end(), p, s);
  36. }
  37. }
  38. // We need to tell fusion about our employee struct to make it a first-class
  39. // fusion citizen. This has to be in global scope. Note that we don't need to
  40. // list the members of our struct in the same sequence a they are defined
  41. BOOST_FUSION_ADAPT_STRUCT(
  42. client::employee,
  43. (int, age)
  44. (std::string, surname)
  45. (std::string, forename)
  46. (std::string, department)
  47. (double, salary)
  48. )
  49. ///////////////////////////////////////////////////////////////////////////////
  50. // that's the different types we need to reorder the attributes
  51. typedef fusion::result_of::as_nview<client::employee, 2, 0>::type name_and_age;
  52. typedef fusion::result_of::as_nview<client::employee, 1, 2, 4>::type names_and_salary;
  53. typedef fusion::result_of::as_nview<client::employee, 2, 0, 3>::type name_age_and_department;
  54. ///////////////////////////////////////////////////////////////////////////////
  55. int main()
  56. {
  57. std::string str;
  58. // some employees
  59. client::employee john;
  60. client::employee mary;
  61. client::employee tom;
  62. // print data about employees in different formats
  63. {
  64. // parse forename and age only
  65. name_and_age johnview(fusion::as_nview<2, 0>(john));
  66. bool r = client::parse(
  67. "John, 25",
  68. *(qi::char_ - ',') >> ", " >> qi::int_,
  69. johnview);
  70. if (r) {
  71. std::cout << "Parsed: " << john.forename << ", " << john.age
  72. << std::endl;
  73. }
  74. // parse surname, forename, and salary
  75. names_and_salary maryview(fusion::as_nview<1, 2, 4>(mary));
  76. r = client::parse(
  77. "Higgins, Mary: 2200.36",
  78. *(qi::char_ - ',') >> ", " >> *(qi::char_ - ':') >> ": " >> qi::double_,
  79. maryview);
  80. if (r) {
  81. std::cout << "Parsed: " << mary.forename << ", " << mary.surname
  82. << ", " << mary.salary << std::endl;
  83. }
  84. // parse forename, age, and department
  85. name_age_and_department tomview(fusion::as_nview<2, 0, 3>(tom));
  86. client::parse(
  87. "Tom: 48 (Boss)",
  88. *(qi::char_ - ':') >> ": " >> qi::int_ >> " (" >> *(qi::char_ - ')') >> ')',
  89. tomview);
  90. if (r) {
  91. std::cout << "Parsed: " << tom.forename << ", " << tom.age
  92. << ", " << tom.department << std::endl;
  93. }
  94. }
  95. // now parse a list of several employees and print them all
  96. std::vector<client::employee> employees;
  97. // parse surname, forename, and salary for all employees
  98. {
  99. qi::rule<client::iterator_type, names_and_salary()> r =
  100. *(qi::char_ - ',') >> ", " >> *(qi::char_ - ',') >> ", " >> qi::double_;
  101. bool result = client::parse(
  102. "John, Smith, 2000.50\n" "Mary, Higgins, 2200.36\n" "Tom, Taylor, 3200.00\n",
  103. r % qi::eol, employees);
  104. std::cout << "Parsed: " << std::endl;
  105. BOOST_FOREACH(client::employee const& e, employees)
  106. {
  107. std::cout << e.forename << ", " << e.surname << ", " << e.salary
  108. << std::endl;
  109. }
  110. }
  111. return 0;
  112. }