phoenix_subrule_calc.cpp 4.6 KB

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