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/support_utree.hpp>
23 #include <boost/spirit/include/qi.hpp>
24 #include <boost/spirit/include/phoenix_operator.hpp>
25 #include <boost/spirit/include/phoenix_function.hpp>
32 namespace qi
= boost::spirit::qi
;
33 namespace ascii
= boost::spirit::ascii
;
34 namespace spirit
= boost::spirit
;
38 template <typename T1
, typename T2
= void>
39 struct result
{ typedef void type
; };
41 expr(char op
) : op(op
) {}
43 void operator()(spirit::utree
& expr
, spirit::utree
const& rhs
) const
47 expr
.push_back(spirit::utf8_symbol_range_type(&op
, &op
+1));
54 boost::phoenix::function
<expr
> const plus
= expr('+');
55 boost::phoenix::function
<expr
> const minus
= expr('-');
56 boost::phoenix::function
<expr
> const times
= expr('*');
57 boost::phoenix::function
<expr
> const divide
= expr('/');
61 template <typename T1
, typename T2
= void>
62 struct result
{ typedef void type
; };
64 void operator()(spirit::utree
& expr
, spirit::utree
const& rhs
) const
68 expr
.push_back(spirit::utf8_symbol_range_type(&op
, &op
+1));
72 boost::phoenix::function
<negate_expr
> neg
;
74 ///////////////////////////////////////////////////////////////////////////////
75 // Our calculator grammar
76 ///////////////////////////////////////////////////////////////////////////////
77 template <typename Iterator
>
78 struct calculator
: qi::grammar
<Iterator
, ascii::space_type
, spirit::utree()>
80 calculator() : calculator::base_type(expression
)
88 >> *( ('+' >> term
[plus(_val
, _1
)])
89 | ('-' >> term
[minus(_val
, _1
)])
95 >> *( ('*' >> factor
[times(_val
, _1
)])
96 | ('/' >> factor
[divide(_val
, _1
)])
102 | '(' >> expression
[_val
= _1
] >> ')'
103 | ('-' >> factor
[neg(_val
, _1
)])
104 | ('+' >> factor
[_val
= _1
])
107 BOOST_SPIRIT_DEBUG_NODE(expression
);
108 BOOST_SPIRIT_DEBUG_NODE(term
);
109 BOOST_SPIRIT_DEBUG_NODE(factor
);
112 qi::rule
<Iterator
, ascii::space_type
, spirit::utree()> expression
, term
, factor
;
116 ///////////////////////////////////////////////////////////////////////////////
118 ///////////////////////////////////////////////////////////////////////////////
121 std::cout
<< "/////////////////////////////////////////////////////////\n\n";
122 std::cout
<< "Expression parser...\n\n";
123 std::cout
<< "/////////////////////////////////////////////////////////\n\n";
124 std::cout
<< "Type an expression...or [q or Q] to quit\n\n";
126 using boost::spirit::ascii::space
;
127 using boost::spirit::utree
;
128 typedef std::string::const_iterator iterator_type
;
129 typedef client::calculator
<iterator_type
> calculator
;
131 calculator calc
; // Our grammar
134 while (std::getline(std::cin
, str
))
136 if (str
.empty() || str
[0] == 'q' || str
[0] == 'Q')
139 std::string::const_iterator iter
= str
.begin();
140 std::string::const_iterator end
= str
.end();
142 bool r
= phrase_parse(iter
, end
, calc
, space
, ut
);
144 if (r
&& iter
== end
)
146 std::cout
<< "-------------------------\n";
147 std::cout
<< "Parsing succeeded: " << ut
<< "\n";
148 std::cout
<< "-------------------------\n";
152 std::string
rest(iter
, end
);
153 std::cout
<< "-------------------------\n";
154 std::cout
<< "Parsing failed\n";
155 std::cout
<< "stopped at: \": " << rest
<< "\"\n";
156 std::cout
<< "-------------------------\n";
160 std::cout
<< "Bye... :-) \n\n";