9
3

rule_parser_2_2.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /*==============================================================================
  2. Copyright (c) 2002-2003 Joel de Guzman
  3. Copyright (c) 2006 Tobias Schwinger
  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. // This example demonstrates how to make recursive grammars scale with typeof.
  11. // It uses a rule parser with member variables and the parser_reference utility.
  12. // See boost/spirit/include/rule_parser.hpp for details.
  13. // This example is based on subrule_calc.cpp.
  14. //------------------------------------------------------------------------------
  15. #include <string>
  16. #include <iostream>
  17. #include <boost/config.hpp>
  18. #if defined(BOOST_MSVC)
  19. // Disable MSVC's "'this' used in base/member initializer" warning.
  20. // It's perfectly safe to use 'this' in a base/member initializer [ 12.6.2-7 ].
  21. // The warning tries to prevent undefined behaviour when the 'this'-pointer is
  22. // used to do illegal things during construction [ 12.6.2-8 ] -- we don't.
  23. # pragma warning(disable:4355)
  24. #endif
  25. #include <boost/typeof/typeof.hpp>
  26. #include <boost/spirit/include/classic_core.hpp>
  27. #include <boost/spirit/include/classic_typeof.hpp>
  28. #include <boost/spirit/include/classic_rule_parser.hpp>
  29. // Don't forget to
  30. #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
  31. using namespace BOOST_SPIRIT_CLASSIC_NS;
  32. // Semantic actions
  33. namespace
  34. {
  35. void do_int(int v) { std::cout << "PUSH(" << v << ')' << std::endl; }
  36. void do_add(char const*, char const*) { std::cout << "ADD" << std::endl; }
  37. void do_sub(char const*, char const*) { std::cout << "SUB" << std::endl; }
  38. void do_mul(char const*, char const*) { std::cout << "MUL" << std::endl; }
  39. void do_div(char const*, char const*) { std::cout << "DIV" << std::endl; }
  40. void do_neg(char const*, char const*) { std::cout << "NEG" << std::endl; }
  41. }
  42. // Operating at root namespace...
  43. #define BOOST_SPIRIT__NAMESPACE -
  44. // Our calculator grammar using paramterized rule parsers.
  45. // Subrules are passed to the rule parsers as arguments to allow recursion.
  46. BOOST_SPIRIT_RULE_PARSER(expression,
  47. (1,(term)),
  48. -,
  49. -,
  50. term
  51. >> *( ('+' >> term)[ &do_add ]
  52. | ('-' >> term)[ &do_sub ]
  53. )
  54. )
  55. BOOST_SPIRIT_RULE_PARSER(term,
  56. (1,(factor)),
  57. -,
  58. -,
  59. factor
  60. >> *( ('*' >> factor)[ &do_mul ]
  61. | ('/' >> factor)[ &do_div ]
  62. )
  63. )
  64. // This rule parser uses the 'parser_reference' utility to refer to itself.
  65. // Note that here is another recursive loop, however, the self-reference, unlike
  66. // a subrule, cannot be passed to contained parsers because we would end up with
  67. // an endless loop at compile time finding the type.
  68. BOOST_SPIRIT_RULE_PARSER(factor,
  69. (1,(expression)),
  70. -,
  71. (1,( ((parser_reference<factor_t>),factor,(*this)) )),
  72. ( int_p[& do_int]
  73. | ('(' >> expression >> ')')
  74. | ('-' >> factor)[&do_neg]
  75. | ('+' >> factor)
  76. )
  77. )
  78. // This rule parser implements recursion between the other ones.
  79. BOOST_SPIRIT_RULE_PARSER( calc,
  80. -,
  81. -,
  82. (3,( ((subrule<0>),sr_expression,()),
  83. ((subrule<1>),sr_term,()),
  84. ((subrule<2>),sr_factor,() )) ),
  85. (
  86. sr_expression = expression(sr_term),
  87. sr_term = term(sr_factor),
  88. sr_factor = factor(sr_expression)
  89. )
  90. )
  91. // Main program
  92. int main()
  93. {
  94. std::cout
  95. << "/////////////////////////////////////////////////////////////\n"
  96. << "\t\tA ruleless calculator using rule parsers and subrules...\n"
  97. << "/////////////////////////////////////////////////////////////\n"
  98. << "Type an expression...or an empty line to quit\n"
  99. << std::endl;
  100. std::string str;
  101. while (std::getline(std::cin, str))
  102. {
  103. if (str.empty()) break;
  104. parse_info<> info = parse(str.c_str(), calc, space_p);
  105. if (info.full)
  106. std::cout
  107. << "OK."
  108. << std::endl;
  109. else
  110. std::cout
  111. << "ERROR.\n"
  112. << "Stopped at: \": " << info.stop << "\".\n"
  113. << std::endl;
  114. }
  115. return 0;
  116. }