• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2002-2015 Joel de Guzman
3 
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 ///////////////////////////////////////////////////////////////////////////////
8 //
9 //  A parser for arbitrary tuples. This example presents a parser
10 //  for an employee structure.
11 //
12 //  [ JDG May 9, 2007 ]
13 //  [ JDG May 13, 2015 ]    spirit X3
14 //
15 ///////////////////////////////////////////////////////////////////////////////
16 
17 #include <boost/config/warning_disable.hpp>
18 #include <boost/spirit/home/x3.hpp>
19 #include <boost/fusion/include/adapt_struct.hpp>
20 #include <boost/fusion/include/io.hpp>
21 
22 #include <iostream>
23 #include <string>
24 
25 namespace client { namespace ast
26 {
27     ///////////////////////////////////////////////////////////////////////////
28     //  Our employee struct
29     ///////////////////////////////////////////////////////////////////////////
30     struct employee
31     {
32         int age;
33         std::string forename;
34         std::string surname;
35         double salary;
36     };
37 
38     using boost::fusion::operator<<;
39 }}
40 
41 // We need to tell fusion about our employee struct
42 // to make it a first-class fusion citizen. This has to
43 // be in global scope.
44 
45 BOOST_FUSION_ADAPT_STRUCT(client::ast::employee,
46     age, forename, surname, salary
47 )
48 
49 namespace client
50 {
51     ///////////////////////////////////////////////////////////////////////////////
52     //  Our employee parser
53     ///////////////////////////////////////////////////////////////////////////////
54     namespace parser
55     {
56         namespace x3 = boost::spirit::x3;
57         namespace ascii = boost::spirit::x3::ascii;
58 
59         using x3::int_;
60         using x3::lit;
61         using x3::double_;
62         using x3::lexeme;
63         using ascii::char_;
64 
65         x3::rule<class employee, ast::employee> const employee = "employee";
66 
67         auto const quoted_string = lexeme['"' >> +(char_ - '"') >> '"'];
68 
69         auto const employee_def =
70             lit("employee")
71             >> '{'
72             >>  int_ >> ','
73             >>  quoted_string >> ','
74             >>  quoted_string >> ','
75             >>  double_
76             >>  '}'
77             ;
78 
79         BOOST_SPIRIT_DEFINE(employee);
80     }
81 }
82 
83 ////////////////////////////////////////////////////////////////////////////
84 //  Main program
85 ////////////////////////////////////////////////////////////////////////////
86 int
main()87 main()
88 {
89     std::cout << "/////////////////////////////////////////////////////////\n\n";
90     std::cout << "\t\tAn employee parser for Spirit...\n\n";
91     std::cout << "/////////////////////////////////////////////////////////\n\n";
92 
93     std::cout
94         << "Give me an employee of the form :"
95         << "employee{age, \"forename\", \"surname\", salary } \n";
96     std::cout << "Type [q or Q] to quit\n\n";
97 
98     using boost::spirit::x3::ascii::space;
99     typedef std::string::const_iterator iterator_type;
100     using client::parser::employee;
101 
102     std::string str;
103     while (getline(std::cin, str))
104     {
105         if (str.empty() || str[0] == 'q' || str[0] == 'Q')
106             break;
107 
108         client::ast::employee emp;
109         iterator_type iter = str.begin();
110         iterator_type const end = str.end();
111         bool r = phrase_parse(iter, end, employee, space, emp);
112 
113         if (r && iter == end)
114         {
115             std::cout << boost::fusion::tuple_open('[');
116             std::cout << boost::fusion::tuple_close(']');
117             std::cout << boost::fusion::tuple_delimiter(", ");
118 
119             std::cout << "-------------------------\n";
120             std::cout << "Parsing succeeded\n";
121             std::cout << "got: " << emp << std::endl;
122             std::cout << "\n-------------------------\n";
123         }
124         else
125         {
126             std::cout << "-------------------------\n";
127             std::cout << "Parsing failed\n";
128             std::cout << "-------------------------\n";
129         }
130     }
131 
132     std::cout << "Bye... :-) \n\n";
133     return 0;
134 }
135