]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/classic/example/fundamental/phoenix_calc.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / spirit / classic / example / fundamental / phoenix_calc.cpp
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 // Full calculator example demonstrating Phoenix
12 // This is discussed in the "Closures" chapter in the Spirit User's Guide.
13 //
14 // [ JDG 6/29/2002 ]
15 //
16 ////////////////////////////////////////////////////////////////////////////
17 #include <boost/spirit/include/classic_core.hpp>
18 #include <boost/spirit/include/classic_attribute.hpp>
19 #include <iostream>
20 #include <string>
21
22 ////////////////////////////////////////////////////////////////////////////
23 using namespace std;
24 using namespace BOOST_SPIRIT_CLASSIC_NS;
25 using namespace phoenix;
26
27 ////////////////////////////////////////////////////////////////////////////
28 //
29 // Our calculator grammar using phoenix to do the semantics
30 //
31 // Note: The top rule propagates the expression result (value) upwards
32 // to the calculator grammar self.val closure member which is
33 // then visible outside the grammar (i.e. since self.val is the
34 // member1 of the closure, it becomes the attribute passed by
35 // the calculator to an attached semantic action. See the
36 // driver code that uses the calculator below).
37 //
38 ////////////////////////////////////////////////////////////////////////////
39 struct calc_closure : BOOST_SPIRIT_CLASSIC_NS::closure<calc_closure, double>
40 {
41 member1 val;
42 };
43
44 struct calculator : public grammar<calculator, calc_closure::context_t>
45 {
46 template <typename ScannerT>
47 struct definition
48 {
49 definition(calculator const& self)
50 {
51 top = expression[self.val = arg1];
52
53 expression
54 = term[expression.val = arg1]
55 >> *( ('+' >> term[expression.val += arg1])
56 | ('-' >> term[expression.val -= arg1])
57 )
58 ;
59
60 term
61 = factor[term.val = arg1]
62 >> *( ('*' >> factor[term.val *= arg1])
63 | ('/' >> factor[term.val /= arg1])
64 )
65 ;
66
67 factor
68 = ureal_p[factor.val = arg1]
69 | '(' >> expression[factor.val = arg1] >> ')'
70 | ('-' >> factor[factor.val = -arg1])
71 | ('+' >> factor[factor.val = arg1])
72 ;
73 }
74
75 typedef rule<ScannerT, calc_closure::context_t> rule_t;
76 rule_t expression, term, factor;
77 rule<ScannerT> top;
78
79 rule<ScannerT> const&
80 start() const { return top; }
81 };
82 };
83
84 ////////////////////////////////////////////////////////////////////////////
85 //
86 // Main program
87 //
88 ////////////////////////////////////////////////////////////////////////////
89 int
90 main()
91 {
92 cout << "/////////////////////////////////////////////////////////\n\n";
93 cout << "\t\tExpression parser using Phoenix...\n\n";
94 cout << "/////////////////////////////////////////////////////////\n\n";
95 cout << "Type an expression...or [q or Q] to quit\n\n";
96
97 calculator calc; // Our parser
98
99 string str;
100 while (getline(cin, str))
101 {
102 if (str.empty() || str[0] == 'q' || str[0] == 'Q')
103 break;
104
105 double n = 0;
106 parse_info<> info = parse(str.c_str(), calc[var(n) = arg1], space_p);
107
108 // calc[var(n) = arg1] invokes the calculator and extracts
109 // the result of the computation. See calculator grammar
110 // note above.
111
112 if (info.full)
113 {
114 cout << "-------------------------\n";
115 cout << "Parsing succeeded\n";
116 cout << "result = " << n << endl;
117 cout << "-------------------------\n";
118 }
119 else
120 {
121 cout << "-------------------------\n";
122 cout << "Parsing failed\n";
123 cout << "stopped at: \": " << info.stop << "\"\n";
124 cout << "-------------------------\n";
125 }
126 }
127
128 cout << "Bye... :-) \n\n";
129 return 0;
130 }
131
132