]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/classic/example/fundamental/more_calculators/rpn_calc.cpp
1 /*=============================================================================
2 Copyright (c) 2001-2003 Hartmut Kaiser
3 Copyright (c) 2002-2003 Joel de Guzman
4 http://spirit.sourceforge.net/
6 Use, modification and distribution is subject to the Boost Software
7 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8 http://www.boost.org/LICENSE_1_0.txt)
9 =============================================================================*/
10 ///////////////////////////////////////////////////////////////////////////////
12 // This sample shows, how to use Phoenix for implementing a
13 // simple (RPN style) calculator [ demonstrating phoenix ]
18 ///////////////////////////////////////////////////////////////////////////////
19 #include <boost/spirit/include/classic_core.hpp>
20 #include <boost/spirit/include/classic_attribute.hpp>
21 #include <boost/spirit/include/phoenix1_functions.hpp>
25 ///////////////////////////////////////////////////////////////////////////////
27 using namespace BOOST_SPIRIT_CLASSIC_NS
;
28 using namespace phoenix
;
30 ///////////////////////////////////////////////////////////////////////////////
32 // Our RPN calculator grammar using phoenix to do the semantics
33 // The class 'RPNCalculator' implements a polish reverse notation
34 // calculator which is equivalent to the following YACC description.
38 // | exp exp '+' { $$ = $1 + $2; }
39 // | exp exp '-' { $$ = $1 - $2; }
40 // | exp exp '*' { $$ = $1 * $2; }
41 // | exp exp '/' { $$ = $1 / $2; }
42 // | exp exp '^' { $$ = pow ($1, $2); } /* Exponentiation */
43 // | exp 'n' { $$ = -$1; } /* Unary minus */
46 // The different notation results from the requirement of LL parsers not to
47 // allow left recursion in their grammar (would lead to endless recursion).
48 // Therefore the left recursion in the YACC script before is transformated
49 // into iteration. To some, this is less intuitive, but once you get used
50 // to it, it's very easy to follow.
52 // Note: The top rule propagates the expression result (value) upwards
53 // to the calculator grammar self.val closure member which is
54 // then visible outside the grammar (i.e. since self.val is the
55 // member1 of the closure, it becomes the attribute passed by
56 // the calculator to an attached semantic action. See the
57 // driver code that uses the calculator below).
59 ///////////////////////////////////////////////////////////////////////////////
62 template <typename X
, typename Y
>
63 struct result
{ typedef X type
; };
65 template <typename X
, typename Y
>
66 X
operator()(X x
, Y y
) const
73 // Notice how power(x, y) is lazily implemented using Phoenix function.
76 struct calc_closure
: BOOST_SPIRIT_CLASSIC_NS::closure
<calc_closure
, double, double>
82 struct calculator
: public grammar
<calculator
, calc_closure::context_t
>
84 template <typename ScannerT
>
87 definition(calculator
const& self
)
89 top
= expr
[self
.x
= arg1
];
91 real_p
[expr
.x
= arg1
]
95 ch_p('+') [expr
.x
+= expr
.y
]
96 | ch_p('-') [expr
.x
-= expr
.y
]
97 | ch_p('*') [expr
.x
*= expr
.y
]
98 | ch_p('/') [expr
.x
/= expr
.y
]
99 | ch_p('^') [expr
.x
= power(expr
.x
, expr
.y
)]
101 | ch_p('n') [expr
.x
= -expr
.x
]
106 typedef rule
<ScannerT
, calc_closure::context_t
> rule_t
;
110 rule
<ScannerT
> const&
111 start() const { return top
; }
115 ///////////////////////////////////////////////////////////////////////////////
119 ///////////////////////////////////////////////////////////////////////////////
123 cout
<< "/////////////////////////////////////////////////////////\n\n";
124 cout
<< "\t\tExpression parser using Phoenix...\n\n";
125 cout
<< "/////////////////////////////////////////////////////////\n\n";
126 cout
<< "Type an expression...or [q or Q] to quit\n\n";
128 calculator calc
; // Our parser
131 while (getline(cin
, str
))
133 if (str
.empty() || str
[0] == 'q' || str
[0] == 'Q')
137 parse_info
<> info
= parse(str
.c_str(), calc
[var(n
) = arg1
], space_p
);
139 // calc[var(n) = arg1] invokes the calculator and extracts
140 // the result of the computation. See calculator grammar
145 cout
<< "-------------------------\n";
146 cout
<< "Parsing succeeded\n";
147 cout
<< "result = " << n
<< endl
;
148 cout
<< "-------------------------\n";
152 cout
<< "-------------------------\n";
153 cout
<< "Parsing failed\n";
154 cout
<< "stopped at: \": " << info
.stop
<< "\"\n";
155 cout
<< "-------------------------\n";
159 cout
<< "Bye... :-) \n\n";