• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2001-2011 Hartmut Kaiser
3     Copyright (c) 2001-2011 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 //
10 //  Plain calculator example demonstrating the grammar. The parser is a
11 //  syntax checker only and does not do any semantic evaluation.
12 //
13 //  [ JDG May 10, 2002 ]        spirit1
14 //  [ JDG March 4, 2007 ]       spirit2
15 //  [ HK November 30, 2010 ]    spirit2/utree
16 //
17 ///////////////////////////////////////////////////////////////////////////////
18 
19 // #define BOOST_SPIRIT_DEBUG
20 
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>
26 
27 #include <iostream>
28 #include <string>
29 
30 #if BOOST_PHOENIX_VERSION == 0x2000
31 namespace boost { namespace phoenix
32 {
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
37     // below:
38     template <>
39     struct result_of_plus<spirit::utree&, spirit::utree&>
40     {
41         typedef spirit::utree type;
42     };
43 
44     template <>
45     struct result_of_minus<spirit::utree&, spirit::utree&>
46     {
47         typedef spirit::utree type;
48     };
49 
50     template <>
51     struct result_of_multiplies<spirit::utree&, spirit::utree&>
52     {
53         typedef spirit::utree type;
54     };
55 
56     template <>
57     struct result_of_divides<spirit::utree&, spirit::utree&>
58     {
59         typedef spirit::utree type;
60     };
61 
62     template <>
63     struct result_of_negate<spirit::utree&>
64     {
65         typedef spirit::utree type;
66     };
67 }}
68 #endif
69 
70 namespace client
71 {
72     namespace qi = boost::spirit::qi;
73     namespace ascii = boost::spirit::ascii;
74     namespace spirit = boost::spirit;
75 
76     ///////////////////////////////////////////////////////////////////////////////
77     //  Our calculator grammar
78     ///////////////////////////////////////////////////////////////////////////////
79     template <typename Iterator>
80     struct calculator : qi::grammar<Iterator, ascii::space_type, spirit::utree()>
81     {
calculatorclient::calculator82         calculator() : calculator::base_type(expression)
83         {
84             using qi::uint_;
85             using qi::_val;
86             using qi::_1;
87 
88             expression =
89                 term                            [_val = _1]
90                 >> *(   ('+' >> term            [_val = _val + _1])
91                     |   ('-' >> term            [_val = _val - _1])
92                     )
93                 ;
94 
95             term =
96                 factor                          [_val = _1]
97                 >> *(   ('*' >> factor          [_val = _val * _1])
98                     |   ('/' >> factor          [_val = _val / _1])
99                     )
100                 ;
101 
102             factor =
103                 uint_                           [_val = _1]
104                 |   '(' >> expression           [_val = _1] >> ')'
105                 |   ('-' >> factor              [_val = -_1])
106                 |   ('+' >> factor              [_val = _1])
107                 ;
108 
109             BOOST_SPIRIT_DEBUG_NODE(expression);
110             BOOST_SPIRIT_DEBUG_NODE(term);
111             BOOST_SPIRIT_DEBUG_NODE(factor);
112         }
113 
114         qi::rule<Iterator, ascii::space_type, spirit::utree()> expression, term, factor;
115     };
116 }
117 
118 ///////////////////////////////////////////////////////////////////////////////
119 //  Main program
120 ///////////////////////////////////////////////////////////////////////////////
main()121 int main()
122 {
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";
127 
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;
132 
133     calculator calc; // Our grammar
134 
135     std::string str;
136     while (std::getline(std::cin, str))
137     {
138         if (str.empty() || str[0] == 'q' || str[0] == 'Q')
139             break;
140 
141         std::string::const_iterator iter = str.begin();
142         std::string::const_iterator end = str.end();
143         utree ut;
144         bool r = phrase_parse(iter, end, calc, space, ut);
145 
146         if (r && iter == end)
147         {
148             std::cout << "-------------------------\n";
149             std::cout << "Parsing succeeded: " << ut << "\n";
150             std::cout << "-------------------------\n";
151         }
152         else
153         {
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";
159         }
160     }
161 
162     std::cout << "Bye... :-) \n\n";
163     return 0;
164 }
165 
166 
167