1/*=============================================================================
2 Copyright (c) 2001-2010 Hartmut Kaiser
3 Copyright (c) 2001-2010 Joel de Guzman
4
5 Distributed under the Boost Software License, Version 1.0. (See accompanying
6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7=============================================================================*/
8
9// This example is not meant to be a sophisticated date parser. It's sole
10// purpose is to demonstrate the intrinsic attribute transformation
11// capabilities of a rule.
12//
13// Note how the rule exposes a fusion sequence, but gets passed an instance of
14// a boost::gregorian::date as the attribute. In order to make these types
15// compatible for the rule we define a specialization of the customization
16// point called 'transform_attribute'.
17
18#include <boost/spirit/include/qi.hpp>
19#include <boost/fusion/include/vector.hpp>
20#include <boost/date_time.hpp>
21
22// define custom transformation
23namespace boost { namespace spirit { namespace traits
24{
25 // This specialization of the customization point transform_attribute
26 // allows to pass a boost::gregorian::date to a rule which is expecting
27 // a fusion sequence consisting out of three integers as its attribute.
28 template<>
29 struct transform_attribute<
30 boost::gregorian::date, fusion::vector<int, int, int>, qi::domain>
31 {
32 typedef fusion::vector<int, int, int> date_parts;
33
34 // The embedded typedef 'type' exposes the attribute as it will be
35 // passed to the right hand side of the rule.
36 typedef date_parts type;
37
38 // The function pre() is called for down-stream conversion of the
39 // attribute supplied to the rule to the attribute expected by the
40 // right hand side.
41 // The supplied attribute might have been pre-initialized by parsers
42 // (i.e. semantic actions) higher up the parser hierarchy (in the
43 // grammar), in which case we would need to properly initialize the
44 // returned value from the argument. In this example this is not
45 // required, so we just create a new instance of a date_parts.
46 static date_parts pre(boost::gregorian::date)
47 {
48 return date_parts();
49 }
50
51 // The function post() is called for up-stream conversion of the
52 // results returned from parsing the right hand side of the rule.
53 // We need to initialize the attribute supplied to the rule (referenced
54 // by the first argument) with the values taken from the parsing
55 // results (referenced by the second argument).
56 static void post(boost::gregorian::date& d, date_parts const& v)
57 {
58 d = boost::gregorian::date(fusion::at_c<0>(seq: v), fusion::at_c<1>(seq: v)
59 , fusion::at_c<2>(seq: v));
60 }
61
62 // The function fail() is called whenever the parsing of the right hand
63 // side of the rule fails. We don't need to do anything here.
64 static void fail(boost::gregorian::date&) {}
65 };
66}}}
67
68///////////////////////////////////////////////////////////////////////////////
69namespace client
70{
71 namespace qi = boost::spirit::qi;
72
73 template <typename Iterator>
74 bool parse_date(Iterator& first, Iterator last, boost::gregorian::date& d)
75 {
76 typedef boost::fusion::vector<int, int, int> date_parts;
77 qi::rule<Iterator, date_parts(), qi::space_type> date =
78 qi::int_ >> '-' >> qi::int_ >> '-' >> qi::int_;
79
80 return phrase_parse(first, last, date, qi::space, d);
81 }
82}
83
84///////////////////////////////////////////////////////////////////////////////
85int main()
86{
87 std::cout << "/////////////////////////////////////////////////////////\n\n";
88 std::cout << "\t\tA date parser for Spirit...\n\n";
89 std::cout << "/////////////////////////////////////////////////////////\n\n";
90
91 std::cout << "Give me a date of the form : year-month-day\n";
92 std::cout << "Type [q or Q] to quit\n\n";
93
94 std::string str;
95 while (getline(is&: std::cin, str&: str))
96 {
97 if (str.empty() || str[0] == 'q' || str[0] == 'Q')
98 break;
99
100 boost::gregorian::date d;
101 std::string::const_iterator iter = str.begin();
102 std::string::const_iterator end = str.end();
103 bool r = client::parse_date(first&: iter, last: end, d);
104
105 if (r && iter == end)
106 {
107 std::cout << "-------------------------\n";
108 std::cout << "Parsing succeeded\n";
109 std::cout << "got: " << d << std::endl;
110 std::cout << "\n-------------------------\n";
111 }
112 else
113 {
114 std::cout << "-------------------------\n";
115 std::cout << "Parsing failed\n";
116 std::cout << "-------------------------\n";
117 }
118 }
119
120 std::cout << "Bye... :-) \n\n";
121 return 0;
122}
123
124
125

source code of boost/libs/spirit/example/qi/parse_date.cpp