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