phoenix_calc.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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. // Full calculator example demonstrating Phoenix
  11. // This is discussed in the "Closures" chapter in the Spirit User's Guide.
  12. //
  13. // [ JDG 6/29/2002 ]
  14. //
  15. ////////////////////////////////////////////////////////////////////////////
  16. #include <boost/spirit/include/classic_core.hpp>
  17. #include <boost/spirit/include/classic_attribute.hpp>
  18. #include <iostream>
  19. #include <string>
  20. ////////////////////////////////////////////////////////////////////////////
  21. using namespace std;
  22. using namespace BOOST_SPIRIT_CLASSIC_NS;
  23. using namespace phoenix;
  24. ////////////////////////////////////////////////////////////////////////////
  25. //
  26. // Our calculator grammar using phoenix to do the semantics
  27. //
  28. // Note: The top rule propagates the expression result (value) upwards
  29. // to the calculator grammar self.val closure member which is
  30. // then visible outside the grammar (i.e. since self.val is the
  31. // member1 of the closure, it becomes the attribute passed by
  32. // the calculator to an attached semantic action. See the
  33. // driver code that uses the calculator below).
  34. //
  35. ////////////////////////////////////////////////////////////////////////////
  36. struct calc_closure : BOOST_SPIRIT_CLASSIC_NS::closure<calc_closure, double>
  37. {
  38. member1 val;
  39. };
  40. struct calculator : public grammar<calculator, calc_closure::context_t>
  41. {
  42. template <typename ScannerT>
  43. struct definition
  44. {
  45. definition(calculator const& self)
  46. {
  47. top = expression[self.val = arg1];
  48. expression
  49. = term[expression.val = arg1]
  50. >> *( ('+' >> term[expression.val += arg1])
  51. | ('-' >> term[expression.val -= arg1])
  52. )
  53. ;
  54. term
  55. = factor[term.val = arg1]
  56. >> *( ('*' >> factor[term.val *= arg1])
  57. | ('/' >> factor[term.val /= arg1])
  58. )
  59. ;
  60. factor
  61. = ureal_p[factor.val = arg1]
  62. | '(' >> expression[factor.val = arg1] >> ')'
  63. | ('-' >> factor[factor.val = -arg1])
  64. | ('+' >> factor[factor.val = arg1])
  65. ;
  66. }
  67. typedef rule<ScannerT, calc_closure::context_t> rule_t;
  68. rule_t expression, term, factor;
  69. rule<ScannerT> top;
  70. rule<ScannerT> const&
  71. start() const { return top; }
  72. };
  73. };
  74. ////////////////////////////////////////////////////////////////////////////
  75. //
  76. // Main program
  77. //
  78. ////////////////////////////////////////////////////////////////////////////
  79. int
  80. main()
  81. {
  82. cout << "/////////////////////////////////////////////////////////\n\n";
  83. cout << "\t\tExpression parser using Phoenix...\n\n";
  84. cout << "/////////////////////////////////////////////////////////\n\n";
  85. cout << "Type an expression...or [q or Q] to quit\n\n";
  86. calculator calc; // Our parser
  87. string str;
  88. while (getline(cin, str))
  89. {
  90. if (str.empty() || str[0] == 'q' || str[0] == 'Q')
  91. break;
  92. double n = 0;
  93. parse_info<> info = parse(str.c_str(), calc[var(n) = arg1], space_p);
  94. // calc[var(n) = arg1] invokes the calculator and extracts
  95. // the result of the computation. See calculator grammar
  96. // note above.
  97. if (info.full)
  98. {
  99. cout << "-------------------------\n";
  100. cout << "Parsing succeeded\n";
  101. cout << "result = " << n << endl;
  102. cout << "-------------------------\n";
  103. }
  104. else
  105. {
  106. cout << "-------------------------\n";
  107. cout << "Parsing failed\n";
  108. cout << "stopped at: \": " << info.stop << "\"\n";
  109. cout << "-------------------------\n";
  110. }
  111. }
  112. cout << "Bye... :-) \n\n";
  113. return 0;
  114. }