calc_with_variables.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /*=============================================================================
  2. Copyright (c) 2001-2003 Dan Nuffer
  3. Copyright (c) 2001-2003 Joel de Guzman
  4. http://spirit.sourceforge.net/
  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 with variables
  12. // [ JDG 9/18/2002 ]
  13. //
  14. ///////////////////////////////////////////////////////////////////////////////
  15. #include <boost/spirit/include/classic_core.hpp>
  16. #include <boost/spirit/include/classic_symbols.hpp>
  17. #include <iostream>
  18. #include <stack>
  19. #include <functional>
  20. #include <string>
  21. using namespace std;
  22. using namespace BOOST_SPIRIT_CLASSIC_NS;
  23. ///////////////////////////////////////////////////////////////////////////////
  24. //
  25. // Semantic actions
  26. //
  27. ///////////////////////////////////////////////////////////////////////////////
  28. struct push_num
  29. {
  30. push_num(stack<double>& eval_)
  31. : eval(eval_) {}
  32. void operator()(double n) const
  33. {
  34. eval.push(n);
  35. cout << "push\t" << n << endl;
  36. }
  37. stack<double>& eval;
  38. };
  39. template <typename op>
  40. struct do_op
  41. {
  42. do_op(op const& the_op, stack<double>& eval_)
  43. : m_op(the_op), eval(eval_) {}
  44. void operator()(char const*, char const*) const
  45. {
  46. double rhs = eval.top();
  47. eval.pop();
  48. double lhs = eval.top();
  49. eval.pop();
  50. cout << "popped " << lhs << " and " << rhs << " from the stack. ";
  51. cout << "pushing " << m_op(lhs, rhs) << " onto the stack.\n";
  52. eval.push(m_op(lhs, rhs));
  53. }
  54. op m_op;
  55. stack<double>& eval;
  56. };
  57. template <class op>
  58. do_op<op>
  59. make_op(op const& the_op, stack<double>& eval)
  60. {
  61. return do_op<op>(the_op, eval);
  62. }
  63. struct do_negate
  64. {
  65. do_negate(stack<double>& eval_)
  66. : eval(eval_) {}
  67. void operator()(char const*, char const*) const
  68. {
  69. double lhs = eval.top();
  70. eval.pop();
  71. cout << "popped " << lhs << " from the stack. ";
  72. cout << "pushing " << -lhs << " onto the stack.\n";
  73. eval.push(-lhs);
  74. }
  75. stack<double>& eval;
  76. };
  77. struct get_var
  78. {
  79. get_var(stack<double>& eval_)
  80. : eval(eval_) {}
  81. void operator()(double n) const
  82. {
  83. eval.push(n);
  84. cout << "push\t" << n << endl;
  85. }
  86. stack<double>& eval;
  87. };
  88. struct set_var
  89. {
  90. set_var(double*& var_)
  91. : var(var_) {}
  92. void operator()(double& n) const
  93. {
  94. var = &n;
  95. }
  96. double*& var;
  97. };
  98. struct redecl_var
  99. {
  100. void operator()(double& /*n*/) const
  101. {
  102. cout << "Warning. You are attempting to re-declare a var.\n";
  103. }
  104. };
  105. struct do_assign
  106. {
  107. do_assign(double*& var_, stack<double>& eval_)
  108. : var(var_), eval(eval_) {}
  109. void operator()(char const*, char const*) const
  110. {
  111. if (var != 0)
  112. {
  113. *var = eval.top();
  114. cout << "assigning\n";
  115. }
  116. }
  117. double*& var;
  118. stack<double>& eval;
  119. };
  120. ///////////////////////////////////////////////////////////////////////////////
  121. //
  122. // Our calculator grammar
  123. //
  124. ///////////////////////////////////////////////////////////////////////////////
  125. struct calculator : public grammar<calculator>
  126. {
  127. calculator(stack<double>& eval_)
  128. : eval(eval_) {}
  129. template <typename ScannerT>
  130. struct definition
  131. {
  132. definition(calculator const& self)
  133. {
  134. factor =
  135. real_p[push_num(self.eval)]
  136. | vars[get_var(self.eval)]
  137. | '(' >> expression >> ')'
  138. | ('-' >> factor)[do_negate(self.eval)]
  139. ;
  140. term =
  141. factor
  142. >> *( ('*' >> factor)[make_op(multiplies<double>(), self.eval)]
  143. | ('/' >> factor)[make_op(divides<double>(), self.eval)]
  144. )
  145. ;
  146. expression =
  147. term
  148. >> *( ('+' >> term)[make_op(plus<double>(), self.eval)]
  149. | ('-' >> term)[make_op(minus<double>(), self.eval)]
  150. )
  151. ;
  152. assignment =
  153. vars[set_var(self.var)]
  154. >> '=' >> expression[do_assign(self.var, self.eval)]
  155. ;
  156. var_decl =
  157. lexeme_d
  158. [
  159. ((alpha_p >> *(alnum_p | '_'))
  160. - vars[redecl_var()])[vars.add]
  161. ]
  162. ;
  163. declaration =
  164. lexeme_d["var" >> space_p] >> var_decl >> *(',' >> var_decl)
  165. ;
  166. statement =
  167. declaration | assignment | '?' >> expression
  168. ;
  169. }
  170. symbols<double> vars;
  171. rule<ScannerT> statement, declaration, var_decl,
  172. assignment, expression, term, factor;
  173. rule<ScannerT> const&
  174. start() const { return statement; }
  175. };
  176. mutable double* var;
  177. stack<double>& eval;
  178. };
  179. ///////////////////////////////////////////////////////////////////////////////
  180. //
  181. // Main program
  182. //
  183. ///////////////////////////////////////////////////////////////////////////////
  184. int
  185. main()
  186. {
  187. cout << "/////////////////////////////////////////////////////////\n\n";
  188. cout << "\t\tThe calculator with variables...\n\n";
  189. cout << "/////////////////////////////////////////////////////////\n\n";
  190. cout << "Type a statement...or [q or Q] to quit\n\n";
  191. cout << "Variables may be declared:\t\tExample: var i, j, k\n";
  192. cout << "Assigning to a variable:\t\tExample: i = 10 * j\n";
  193. cout << "To evaluate an expression:\t\tExample: ? i * 3.33E-3\n\n";
  194. stack<double> eval;
  195. calculator calc(eval); // Our parser
  196. string str;
  197. while (getline(cin, str))
  198. {
  199. if (str.empty() || str[0] == 'q' || str[0] == 'Q')
  200. break;
  201. parse_info<> info = parse(str.c_str(), calc, space_p);
  202. if (info.full)
  203. {
  204. cout << "-------------------------\n";
  205. cout << "Parsing succeeded\n";
  206. cout << "-------------------------\n";
  207. }
  208. else
  209. {
  210. cout << "-------------------------\n";
  211. cout << "Parsing failed\n";
  212. cout << "stopped at: \": " << info.stop << "\"\n";
  213. cout << "-------------------------\n";
  214. }
  215. }
  216. cout << "Bye... :-) \n\n";
  217. return 0;
  218. }