calc_debug.cpp 5.4 KB

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