full_calc.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*=============================================================================
  2. Copyright (c) 2001-2003 Dan Nuffer
  3. Copyright (c) 2002-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 using STL functors
  12. // This is discussed in the "Functional" chapter in the Spirit User's Guide.
  13. //
  14. // Ported to Spirit v1.5 from v1.2/1.3 example by Dan Nuffer
  15. // [ JDG 9/18/2002 ]
  16. //
  17. ////////////////////////////////////////////////////////////////////////////
  18. #include <boost/spirit/include/classic_core.hpp>
  19. #include <iostream>
  20. #include <stack>
  21. #include <functional>
  22. #include <string>
  23. ////////////////////////////////////////////////////////////////////////////
  24. using namespace std;
  25. using namespace BOOST_SPIRIT_CLASSIC_NS;
  26. ////////////////////////////////////////////////////////////////////////////
  27. //
  28. // Semantic actions
  29. //
  30. ////////////////////////////////////////////////////////////////////////////
  31. struct push_int
  32. {
  33. push_int(stack<long>& eval_)
  34. : eval(eval_) {}
  35. void operator()(char const* str, char const* /*end*/) const
  36. {
  37. long n = strtol(str, 0, 10);
  38. eval.push(n);
  39. cout << "push\t" << long(n) << endl;
  40. }
  41. stack<long>& eval;
  42. };
  43. template <typename op>
  44. struct do_op
  45. {
  46. do_op(op const& the_op, stack<long>& eval_)
  47. : m_op(the_op), eval(eval_) {}
  48. void operator()(char const*, char const*) const
  49. {
  50. long rhs = eval.top();
  51. eval.pop();
  52. long lhs = eval.top();
  53. eval.pop();
  54. cout << "popped " << lhs << " and " << rhs << " from the stack. ";
  55. cout << "pushing " << m_op(lhs, rhs) << " onto the stack.\n";
  56. eval.push(m_op(lhs, rhs));
  57. }
  58. op m_op;
  59. stack<long>& eval;
  60. };
  61. template <class op>
  62. do_op<op>
  63. make_op(op const& the_op, stack<long>& eval)
  64. {
  65. return do_op<op>(the_op, eval);
  66. }
  67. struct do_negate
  68. {
  69. do_negate(stack<long>& eval_)
  70. : eval(eval_) {}
  71. void operator()(char const*, char const*) const
  72. {
  73. long lhs = eval.top();
  74. eval.pop();
  75. cout << "popped " << lhs << " from the stack. ";
  76. cout << "pushing " << -lhs << " onto the stack.\n";
  77. eval.push(-lhs);
  78. }
  79. stack<long>& eval;
  80. };
  81. ////////////////////////////////////////////////////////////////////////////
  82. //
  83. // Our calculator grammar
  84. //
  85. ////////////////////////////////////////////////////////////////////////////
  86. struct calculator : public grammar<calculator>
  87. {
  88. calculator(stack<long>& eval_)
  89. : eval(eval_) {}
  90. template <typename ScannerT>
  91. struct definition
  92. {
  93. definition(calculator const& self)
  94. {
  95. integer =
  96. lexeme_d[ (+digit_p)[push_int(self.eval)] ]
  97. ;
  98. factor =
  99. integer
  100. | '(' >> expression >> ')'
  101. | ('-' >> factor)[do_negate(self.eval)]
  102. | ('+' >> factor)
  103. ;
  104. term =
  105. factor
  106. >> *( ('*' >> factor)[make_op(multiplies<long>(), self.eval)]
  107. | ('/' >> factor)[make_op(divides<long>(), self.eval)]
  108. )
  109. ;
  110. expression =
  111. term
  112. >> *( ('+' >> term)[make_op(plus<long>(), self.eval)]
  113. | ('-' >> term)[make_op(minus<long>(), self.eval)]
  114. )
  115. ;
  116. }
  117. rule<ScannerT> expression, term, factor, integer;
  118. rule<ScannerT> const&
  119. start() const { return expression; }
  120. };
  121. stack<long>& eval;
  122. };
  123. ////////////////////////////////////////////////////////////////////////////
  124. //
  125. // Main program
  126. //
  127. ////////////////////////////////////////////////////////////////////////////
  128. int
  129. main()
  130. {
  131. cout << "/////////////////////////////////////////////////////////\n\n";
  132. cout << "\t\tThe simplest working calculator...\n\n";
  133. cout << "/////////////////////////////////////////////////////////\n\n";
  134. cout << "Type an expression...or [q or Q] to quit\n\n";
  135. stack<long> eval;
  136. calculator calc(eval); // Our parser
  137. string str;
  138. while (getline(cin, str))
  139. {
  140. if (str.empty() || str[0] == 'q' || str[0] == 'Q')
  141. break;
  142. parse_info<> info = parse(str.c_str(), calc, space_p);
  143. if (info.full)
  144. {
  145. cout << "-------------------------\n";
  146. cout << "Parsing succeeded\n";
  147. cout << "-------------------------\n";
  148. }
  149. else
  150. {
  151. cout << "-------------------------\n";
  152. cout << "Parsing failed\n";
  153. cout << "stopped at: \": " << info.stop << "\"\n";
  154. cout << "-------------------------\n";
  155. }
  156. }
  157. cout << "Bye... :-) \n\n";
  158. return 0;
  159. }