subrule_calc.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*=============================================================================
  2. Copyright (c) 2002-2003 Joel de Guzman
  3. http://spirit.sourceforge.net/
  4. Use, modification and distribution is subject to the Boost Software
  5. License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. http://www.boost.org/LICENSE_1_0.txt)
  7. =============================================================================*/
  8. ///////////////////////////////////////////////////////////////////////////////
  9. //
  10. // This calculator example demontrates the use of subrules.
  11. // This is discussed in the "Subrule" chapter in the Spirit User's Guide.
  12. //
  13. // [ JDG 4/11/2002 ]
  14. //
  15. ///////////////////////////////////////////////////////////////////////////////
  16. //#define BOOST_SPIRIT_DEBUG // define this for debug output
  17. #include <boost/spirit/include/classic_core.hpp>
  18. #include <iostream>
  19. #include <string>
  20. using namespace std;
  21. using namespace BOOST_SPIRIT_CLASSIC_NS;
  22. ///////////////////////////////////////////////////////////////////////////////
  23. //
  24. // Semantic actions
  25. //
  26. ///////////////////////////////////////////////////////////////////////////////
  27. namespace
  28. {
  29. void do_int(char const* str, char const* end)
  30. {
  31. string s(str, end);
  32. cout << "PUSH(" << s << ')' << endl;
  33. }
  34. void do_add(char const*, char const*) { cout << "ADD\n"; }
  35. void do_subt(char const*, char const*) { cout << "SUBTRACT\n"; }
  36. void do_mult(char const*, char const*) { cout << "MULTIPLY\n"; }
  37. void do_div(char const*, char const*) { cout << "DIVIDE\n"; }
  38. void do_neg(char const*, char const*) { cout << "NEGATE\n"; }
  39. }
  40. ///////////////////////////////////////////////////////////////////////////////
  41. //
  42. // Our calculator grammar (using subrules)
  43. //
  44. ///////////////////////////////////////////////////////////////////////////////
  45. struct calculator : public grammar<calculator>
  46. {
  47. template <typename ScannerT>
  48. struct definition {
  49. definition(calculator const& /*self*/)
  50. {
  51. first = (
  52. expression =
  53. term
  54. >> *( ('+' >> term)[&do_add]
  55. | ('-' >> term)[&do_subt]
  56. )
  57. ,
  58. term =
  59. factor
  60. >> *( ('*' >> factor)[&do_mult]
  61. | ('/' >> factor)[&do_div]
  62. )
  63. ,
  64. factor
  65. = lexeme_d[(+digit_p)[&do_int]]
  66. | '(' >> expression >> ')'
  67. | ('-' >> factor)[&do_neg]
  68. | ('+' >> factor)
  69. );
  70. BOOST_SPIRIT_DEBUG_NODE(first);
  71. BOOST_SPIRIT_DEBUG_NODE(expression);
  72. BOOST_SPIRIT_DEBUG_NODE(term);
  73. BOOST_SPIRIT_DEBUG_NODE(factor);
  74. }
  75. subrule<0> expression;
  76. subrule<1> term;
  77. subrule<2> factor;
  78. rule<ScannerT> first;
  79. rule<ScannerT> const&
  80. start() const { return first; }
  81. };
  82. };
  83. ///////////////////////////////////////////////////////////////////////////////
  84. //
  85. // Main program
  86. //
  87. ///////////////////////////////////////////////////////////////////////////////
  88. int
  89. main()
  90. {
  91. cout << "/////////////////////////////////////////////////////////\n\n";
  92. cout << "\t\tA calculator using subrules...\n\n";
  93. cout << "/////////////////////////////////////////////////////////\n\n";
  94. cout << "Type an expression...or [q or Q] to quit\n\n";
  95. calculator calc; // Our parser
  96. string str;
  97. while (getline(cin, str))
  98. {
  99. if (str.empty() || str[0] == 'q' || str[0] == 'Q')
  100. break;
  101. parse_info<> info = parse(str.c_str(), calc, space_p);
  102. if (info.full)
  103. {
  104. cout << "-------------------------\n";
  105. cout << "Parsing succeeded\n";
  106. cout << "-------------------------\n";
  107. }
  108. else
  109. {
  110. cout << "-------------------------\n";
  111. cout << "Parsing failed\n";
  112. cout << "stopped at: \": " << info.stop << "\"\n";
  113. cout << "-------------------------\n";
  114. }
  115. }
  116. cout << "Bye... :-) \n\n";
  117. return 0;
  118. }