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 // This calculator example demontrates the use of subrules.
12 // This is discussed in the "Subrule" chapter in the Spirit User's Guide.
13 //
14 // [ JDG 4/11/2002 ]
15 //
16 ///////////////////////////////////////////////////////////////////////////////
17
18 //#define BOOST_SPIRIT_DEBUG // define this for debug output
19
20 #include <boost/spirit/include/classic_core.hpp>
21 #include <iostream>
22 #include <string>
23
24 using namespace std;
25 using namespace BOOST_SPIRIT_CLASSIC_NS;
26
27 ///////////////////////////////////////////////////////////////////////////////
28 //
29 // Semantic actions
30 //
31 ///////////////////////////////////////////////////////////////////////////////
32 namespace
33 {
do_int(char const * str,char const * end)34 void do_int(char const* str, char const* end)
35 {
36 string s(str, end);
37 cout << "PUSH(" << s << ')' << endl;
38 }
39
do_add(char const *,char const *)40 void do_add(char const*, char const*) { cout << "ADD\n"; }
do_subt(char const *,char const *)41 void do_subt(char const*, char const*) { cout << "SUBTRACT\n"; }
do_mult(char const *,char const *)42 void do_mult(char const*, char const*) { cout << "MULTIPLY\n"; }
do_div(char const *,char const *)43 void do_div(char const*, char const*) { cout << "DIVIDE\n"; }
do_neg(char const *,char const *)44 void do_neg(char const*, char const*) { cout << "NEGATE\n"; }
45 }
46
47 ///////////////////////////////////////////////////////////////////////////////
48 //
49 // Our calculator grammar (using subrules)
50 //
51 ///////////////////////////////////////////////////////////////////////////////
52 struct calculator : public grammar<calculator>
53 {
54 template <typename ScannerT>
55 struct definition {
56
definitioncalculator::definition57 definition(calculator const& /*self*/)
58 {
59 first = (
60
61 expression =
62 term
63 >> *( ('+' >> term)[&do_add]
64 | ('-' >> term)[&do_subt]
65 )
66 ,
67
68 term =
69 factor
70 >> *( ('*' >> factor)[&do_mult]
71 | ('/' >> factor)[&do_div]
72 )
73 ,
74
75 factor
76 = lexeme_d[(+digit_p)[&do_int]]
77 | '(' >> expression >> ')'
78 | ('-' >> factor)[&do_neg]
79 | ('+' >> factor)
80 );
81
82 BOOST_SPIRIT_DEBUG_NODE(first);
83 BOOST_SPIRIT_DEBUG_NODE(expression);
84 BOOST_SPIRIT_DEBUG_NODE(term);
85 BOOST_SPIRIT_DEBUG_NODE(factor);
86 }
87
88 subrule<0> expression;
89 subrule<1> term;
90 subrule<2> factor;
91
92 rule<ScannerT> first;
93 rule<ScannerT> const&
startcalculator::definition94 start() const { return first; }
95 };
96 };
97
98 ///////////////////////////////////////////////////////////////////////////////
99 //
100 // Main program
101 //
102 ///////////////////////////////////////////////////////////////////////////////
103 int
main()104 main()
105 {
106 cout << "/////////////////////////////////////////////////////////\n\n";
107 cout << "\t\tA calculator using subrules...\n\n";
108 cout << "/////////////////////////////////////////////////////////\n\n";
109 cout << "Type an expression...or [q or Q] to quit\n\n";
110
111 calculator calc; // Our parser
112
113 string str;
114 while (getline(cin, str))
115 {
116 if (str.empty() || str[0] == 'q' || str[0] == 'Q')
117 break;
118
119 parse_info<> info = parse(str.c_str(), calc, space_p);
120
121 if (info.full)
122 {
123 cout << "-------------------------\n";
124 cout << "Parsing succeeded\n";
125 cout << "-------------------------\n";
126 }
127 else
128 {
129 cout << "-------------------------\n";
130 cout << "Parsing failed\n";
131 cout << "stopped at: \": " << info.stop << "\"\n";
132 cout << "-------------------------\n";
133 }
134 }
135
136 cout << "Bye... :-) \n\n";
137 return 0;
138 }
139
140
141