• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2002-2003 Joel de Guzman
3     http://spirit.sourceforge.net/
4 
5     Use, modification and distribution is subject to the Boost Software
6     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7     http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9 ////////////////////////////////////////////////////////////////////////////
10 //
11 //  Plain calculator example demostrating the grammar and semantic actions.
12 //  This is discussed in the "Grammar" and "Semantic Actions" chapters in
13 //  the Spirit User's Guide.
14 //
15 //  [ JDG 5/10/2002 ]
16 //
17 ////////////////////////////////////////////////////////////////////////////
18 #include <boost/spirit/include/classic_core.hpp>
19 #include <iostream>
20 #include <string>
21 
22 ////////////////////////////////////////////////////////////////////////////
23 using namespace std;
24 using namespace BOOST_SPIRIT_CLASSIC_NS;
25 
26 ////////////////////////////////////////////////////////////////////////////
27 //
28 //  Semantic actions
29 //
30 ////////////////////////////////////////////////////////////////////////////
31 namespace
32 {
do_int(char const * str,char const * end)33     void    do_int(char const* str, char const* end)
34     {
35         string  s(str, end);
36         cout << "PUSH(" << s << ')' << endl;
37     }
38 
do_add(char const *,char const *)39     void    do_add(char const*, char const*)    { cout << "ADD\n"; }
do_subt(char const *,char const *)40     void    do_subt(char const*, char const*)   { cout << "SUBTRACT\n"; }
do_mult(char const *,char const *)41     void    do_mult(char const*, char const*)   { cout << "MULTIPLY\n"; }
do_div(char const *,char const *)42     void    do_div(char const*, char const*)    { cout << "DIVIDE\n"; }
do_neg(char const *,char const *)43     void    do_neg(char const*, char const*)    { cout << "NEGATE\n"; }
44 }
45 
46 ////////////////////////////////////////////////////////////////////////////
47 //
48 //  Our calculator grammar
49 //
50 ////////////////////////////////////////////////////////////////////////////
51 struct calculator : public grammar<calculator>
52 {
53     template <typename ScannerT>
54     struct definition
55     {
definitioncalculator::definition56         definition(calculator const& /*self*/)
57         {
58             expression
59                 =   term
60                     >> *(   ('+' >> term)[&do_add]
61                         |   ('-' >> term)[&do_subt]
62                         )
63                 ;
64 
65             term
66                 =   factor
67                     >> *(   ('*' >> factor)[&do_mult]
68                         |   ('/' >> factor)[&do_div]
69                         )
70                 ;
71 
72             factor
73                 =   lexeme_d[(+digit_p)[&do_int]]
74                 |   '(' >> expression >> ')'
75                 |   ('-' >> factor)[&do_neg]
76                 |   ('+' >> factor)
77                 ;
78         }
79 
80         rule<ScannerT> expression, term, factor;
81 
82         rule<ScannerT> const&
startcalculator::definition83         start() const { return expression; }
84     };
85 };
86 
87 ////////////////////////////////////////////////////////////////////////////
88 //
89 //  Main program
90 //
91 ////////////////////////////////////////////////////////////////////////////
92 int
main()93 main()
94 {
95     cout << "/////////////////////////////////////////////////////////\n\n";
96     cout << "\t\tExpression parser...\n\n";
97     cout << "/////////////////////////////////////////////////////////\n\n";
98     cout << "Type an expression...or [q or Q] to quit\n\n";
99 
100     calculator calc;    //  Our parser
101 
102     string str;
103     while (getline(cin, str))
104     {
105         if (str.empty() || str[0] == 'q' || str[0] == 'Q')
106             break;
107 
108         parse_info<> info = parse(str.c_str(), calc, space_p);
109 
110         if (info.full)
111         {
112             cout << "-------------------------\n";
113             cout << "Parsing succeeded\n";
114             cout << "-------------------------\n";
115         }
116         else
117         {
118             cout << "-------------------------\n";
119             cout << "Parsing failed\n";
120             cout << "stopped at: \": " << info.stop << "\"\n";
121             cout << "-------------------------\n";
122         }
123     }
124 
125     cout << "Bye... :-) \n\n";
126     return 0;
127 }
128 
129 
130