1 /*=============================================================================
2 Copyright (c) 2001-2011 Hartmut Kaiser
3 Copyright (c) 2001-2011 Joel de Guzman
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 ///////////////////////////////////////////////////////////////////////////////
10 // Plain calculator example demonstrating the grammar. The parser is a
11 // syntax checker only and does not do any semantic evaluation.
13 // [ JDG May 10, 2002 ] spirit1
14 // [ JDG March 4, 2007 ] spirit2
15 // [ HK November 30, 2010 ] spirit2/utree
17 ///////////////////////////////////////////////////////////////////////////////
19 // #define BOOST_SPIRIT_DEBUG
21 #include <boost/config/warning_disable.hpp>
22 #include <boost/spirit/include/qi.hpp>
23 #include <boost/spirit/include/support_utree.hpp>
24 #include <boost/spirit/include/phoenix_operator.hpp>
25 #include <boost/spirit/include/phoenix_function.hpp>
30 #if BOOST_PHOENIX_VERSION == 0x2000
31 namespace boost
{ namespace phoenix
33 // There's a bug in the Phoenix V2 type deduction mechanism that prevents
34 // correct return type deduction for the math operations below. Newer
35 // versions of Phoenix will be switching to BOOST_TYPEOF. In the meantime,
36 // we will use the specializations helping with return type deduction
39 struct result_of_plus
<spirit::utree
&, spirit::utree
&>
41 typedef spirit::utree type
;
45 struct result_of_minus
<spirit::utree
&, spirit::utree
&>
47 typedef spirit::utree type
;
51 struct result_of_multiplies
<spirit::utree
&, spirit::utree
&>
53 typedef spirit::utree type
;
57 struct result_of_divides
<spirit::utree
&, spirit::utree
&>
59 typedef spirit::utree type
;
63 struct result_of_negate
<spirit::utree
&>
65 typedef spirit::utree type
;
72 namespace qi
= boost::spirit::qi
;
73 namespace ascii
= boost::spirit::ascii
;
74 namespace spirit
= boost::spirit
;
76 ///////////////////////////////////////////////////////////////////////////////
77 // Our calculator grammar
78 ///////////////////////////////////////////////////////////////////////////////
79 template <typename Iterator
>
80 struct calculator
: qi::grammar
<Iterator
, ascii::space_type
, spirit::utree()>
82 calculator() : calculator::base_type(expression
)
90 >> *( ('+' >> term
[_val
= _val
+ _1
])
91 | ('-' >> term
[_val
= _val
- _1
])
97 >> *( ('*' >> factor
[_val
= _val
* _1
])
98 | ('/' >> factor
[_val
= _val
/ _1
])
104 | '(' >> expression
[_val
= _1
] >> ')'
105 | ('-' >> factor
[_val
= -_1
])
106 | ('+' >> factor
[_val
= _1
])
109 BOOST_SPIRIT_DEBUG_NODE(expression
);
110 BOOST_SPIRIT_DEBUG_NODE(term
);
111 BOOST_SPIRIT_DEBUG_NODE(factor
);
114 qi::rule
<Iterator
, ascii::space_type
, spirit::utree()> expression
, term
, factor
;
118 ///////////////////////////////////////////////////////////////////////////////
120 ///////////////////////////////////////////////////////////////////////////////
123 std::cout
<< "/////////////////////////////////////////////////////////\n\n";
124 std::cout
<< "Expression parser...\n\n";
125 std::cout
<< "/////////////////////////////////////////////////////////\n\n";
126 std::cout
<< "Type an expression...or [q or Q] to quit\n\n";
128 using boost::spirit::ascii::space
;
129 using boost::spirit::utree
;
130 typedef std::string::const_iterator iterator_type
;
131 typedef client::calculator
<iterator_type
> calculator
;
133 calculator calc
; // Our grammar
136 while (std::getline(std::cin
, str
))
138 if (str
.empty() || str
[0] == 'q' || str
[0] == 'Q')
141 std::string::const_iterator iter
= str
.begin();
142 std::string::const_iterator end
= str
.end();
144 bool r
= phrase_parse(iter
, end
, calc
, space
, ut
);
146 if (r
&& iter
== end
)
148 std::cout
<< "-------------------------\n";
149 std::cout
<< "Parsing succeeded: " << ut
<< "\n";
150 std::cout
<< "-------------------------\n";
154 std::string
rest(iter
, end
);
155 std::cout
<< "-------------------------\n";
156 std::cout
<< "Parsing failed\n";
157 std::cout
<< "stopped at: \": " << rest
<< "\"\n";
158 std::cout
<< "-------------------------\n";
162 std::cout
<< "Bye... :-) \n\n";