• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2002-2003 Hartmut Kaiser
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 //  Full calculator example
12 //  [ demonstrating phoenix and subrules ]
13 //
14 //  [ Hartmut Kaiser 10/8/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 <boost/spirit/include/classic_attribute.hpp>
22 #include <iostream>
23 #include <string>
24 
25 ///////////////////////////////////////////////////////////////////////////////
26 using namespace std;
27 using namespace BOOST_SPIRIT_CLASSIC_NS;
28 using namespace phoenix;
29 
30 ///////////////////////////////////////////////////////////////////////////////
31 //
32 //  Our calculator grammar using phoenix to do the semantics and subrule's
33 //  as it's working horses
34 //
35 //  Note:   The top rule propagates the expression result (value) upwards
36 //          to the calculator grammar self.val closure member which is
37 //          then visible outside the grammar (i.e. since self.val is the
38 //          member1 of the closure, it becomes the attribute passed by
39 //          the calculator to an attached semantic action. See the
40 //          driver code that uses the calculator below).
41 //
42 ///////////////////////////////////////////////////////////////////////////////
43 struct calc_closure : BOOST_SPIRIT_CLASSIC_NS::closure<calc_closure, double>
44 {
45     member1 val;
46 };
47 
48 struct calculator : public grammar<calculator, calc_closure::context_t>
49 {
50     template <typename ScannerT>
51     struct definition
52     {
definitioncalculator::definition53         definition(calculator const& self)
54         {
55             top = (
56                 expression =
57                     term[self.val = arg1]
58                     >> *(   ('+' >> term[self.val += arg1])
59                         |   ('-' >> term[self.val -= arg1])
60                         )
61                 ,
62 
63                 term =
64                     factor[term.val = arg1]
65                     >> *(   ('*' >> factor[term.val *= arg1])
66                         |   ('/' >> factor[term.val /= arg1])
67                         )
68                 ,
69 
70                 factor
71                     =    ureal_p[factor.val = arg1]
72                     |   '(' >> expression[factor.val = arg1] >> ')'
73                     |   ('-' >> factor[factor.val = -arg1])
74                     |   ('+' >> factor[factor.val = arg1])
75             );
76 
77             BOOST_SPIRIT_DEBUG_NODE(top);
78             BOOST_SPIRIT_DEBUG_NODE(expression);
79             BOOST_SPIRIT_DEBUG_NODE(term);
80             BOOST_SPIRIT_DEBUG_NODE(factor);
81         }
82 
83         subrule<0, calc_closure::context_t>  expression;
84         subrule<1, calc_closure::context_t>  term;
85         subrule<2, calc_closure::context_t>  factor;
86 
87         rule<ScannerT> top;
88 
89         rule<ScannerT> const&
startcalculator::definition90         start() const { return top; }
91     };
92 };
93 
94 ///////////////////////////////////////////////////////////////////////////////
95 //
96 //  Main program
97 //
98 ///////////////////////////////////////////////////////////////////////////////
99 int
main()100 main()
101 {
102     cout << "/////////////////////////////////////////////////////////\n\n";
103     cout << "\t\tExpression parser using Phoenix...\n\n";
104     cout << "/////////////////////////////////////////////////////////\n\n";
105     cout << "Type an expression...or [q or Q] to quit\n\n";
106 
107     calculator calc;    //  Our parser
108 
109     string str;
110     while (getline(cin, str))
111     {
112         if (str.empty() || str[0] == 'q' || str[0] == 'Q')
113             break;
114 
115         double n = 0;
116         parse_info<> info = parse(str.c_str(), calc[var(n) = arg1], space_p);
117 
118         //  calc[var(n) = arg1] invokes the calculator and extracts
119         //  the result of the computation. See calculator grammar
120         //  note above.
121 
122         if (info.full)
123         {
124             cout << "-------------------------\n";
125             cout << "Parsing succeeded\n";
126             cout << "result = " << n << endl;
127             cout << "-------------------------\n";
128         }
129         else
130         {
131             cout << "-------------------------\n";
132             cout << "Parsing failed\n";
133             cout << "stopped at: \": " << info.stop << "\"\n";
134             cout << "-------------------------\n";
135         }
136     }
137 
138     cout << "Bye... :-) \n\n";
139     return 0;
140 }
141 
142 
143