parse_tree_calc1.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /*=============================================================================
  2. Copyright (c) 2001-2003 Daniel Nuffer
  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. // Demonstrates parse trees. This is discussed in the
  11. // "Trees" chapter in the Spirit User's Guide.
  12. //
  13. ///////////////////////////////////////////////////////////////////////////////
  14. #define BOOST_SPIRIT_DUMP_PARSETREE_AS_XML
  15. #include <boost/spirit/include/classic_core.hpp>
  16. #include <boost/spirit/include/classic_parse_tree.hpp>
  17. #include <boost/assert.hpp>
  18. #include <iostream>
  19. #include <stack>
  20. #include <functional>
  21. #include <string>
  22. #ifdef BOOST_SPIRIT_DUMP_PARSETREE_AS_XML
  23. #include <boost/spirit/include/classic_tree_to_xml.hpp>
  24. #include <map>
  25. #endif
  26. ////////////////////////////////////////////////////////////////////////////
  27. // This example shows how to use a parse tree
  28. using namespace std;
  29. using namespace BOOST_SPIRIT_CLASSIC_NS;
  30. // Here's some typedefs to simplify things
  31. typedef char const* iterator_t;
  32. typedef tree_match<iterator_t> parse_tree_match_t;
  33. typedef parse_tree_match_t::const_tree_iterator iter_t;
  34. typedef pt_match_policy<iterator_t> match_policy_t;
  35. typedef scanner_policies<iteration_policy, match_policy_t, action_policy> scanner_policy_t;
  36. typedef scanner<iterator_t, scanner_policy_t> scanner_t;
  37. typedef rule<scanner_t> rule_t;
  38. // grammar rules
  39. rule_t expression, term, factor, integer;
  40. ////////////////////////////////////////////////////////////////////////////
  41. // Here's the function prototypes that we'll use. One function for each
  42. // grammar rule.
  43. long evaluate(const tree_parse_info<>& info);
  44. long eval_expression(iter_t const& i);
  45. long eval_term(iter_t const& i);
  46. long eval_factor(iter_t const& i);
  47. long eval_integer(iter_t const& i);
  48. long evaluate(const tree_parse_info<>& info)
  49. {
  50. return eval_expression(info.trees.begin());
  51. }
  52. // i should be pointing to a node created by the expression rule
  53. long eval_expression(iter_t const& i)
  54. {
  55. parser_id id = i->value.id();
  56. BOOST_ASSERT(id == expression.id()); // check the id
  57. // first child points to a term, so call eval_term on it
  58. iter_t chi = i->children.begin();
  59. long lhs = eval_term(chi);
  60. for (++chi; chi != i->children.end(); ++chi)
  61. {
  62. // next node points to the operator. The text of the operator is
  63. // stored in value (a vector<char>)
  64. char op = *(chi->value.begin());
  65. ++chi;
  66. long rhs = eval_term(chi);
  67. if (op == '+')
  68. lhs += rhs;
  69. else if (op == '-')
  70. lhs -= rhs;
  71. else
  72. BOOST_ASSERT(0);
  73. }
  74. return lhs;
  75. }
  76. long eval_term(iter_t const& i)
  77. {
  78. parser_id id = i->value.id();
  79. BOOST_ASSERT(id == term.id());
  80. iter_t chi = i->children.begin();
  81. long lhs = eval_factor(chi);
  82. for (++chi; chi != i->children.end(); ++chi)
  83. {
  84. char op = *(chi->value.begin());
  85. ++chi;
  86. long rhs = eval_factor(chi);
  87. if (op == '*')
  88. lhs *= rhs;
  89. else if (op == '/')
  90. lhs /= rhs;
  91. else
  92. BOOST_ASSERT(0);
  93. }
  94. return lhs;
  95. }
  96. long eval_factor(iter_t const& i)
  97. {
  98. parser_id id = i->value.id();
  99. BOOST_ASSERT(id == factor.id());
  100. iter_t chi = i->children.begin();
  101. id = chi->value.id();
  102. if (id == integer.id())
  103. return eval_integer(chi->children.begin());
  104. else if (*(chi->value.begin()) == '(')
  105. {
  106. ++chi;
  107. return eval_expression(chi);
  108. }
  109. else if (*(chi->value.begin()) == '-')
  110. {
  111. ++chi;
  112. return -eval_factor(chi);
  113. }
  114. else
  115. {
  116. BOOST_ASSERT(0);
  117. return 0;
  118. }
  119. }
  120. long eval_integer(iter_t const& i)
  121. {
  122. // extract integer (not always delimited by '\0')
  123. string integer(i->value.begin(), i->value.end());
  124. return strtol(integer.c_str(), 0, 10);
  125. }
  126. ////////////////////////////////////////////////////////////////////////////
  127. int
  128. main()
  129. {
  130. // Start grammar definition
  131. integer = lexeme_d[ token_node_d[ (!ch_p('-') >> +digit_p) ] ];
  132. factor = integer
  133. | '(' >> expression >> ')'
  134. | ('-' >> factor);
  135. term = factor >>
  136. *( ('*' >> factor)
  137. | ('/' >> factor)
  138. );
  139. expression = term >>
  140. *( ('+' >> term)
  141. | ('-' >> term)
  142. );
  143. // End grammar definition
  144. cout << "/////////////////////////////////////////////////////////\n\n";
  145. cout << "\t\tThe simplest working calculator...\n\n";
  146. cout << "/////////////////////////////////////////////////////////\n\n";
  147. cout << "Type an expression...or [q or Q] to quit\n\n";
  148. string str;
  149. while (getline(cin, str))
  150. {
  151. if (str.empty() || str[0] == 'q' || str[0] == 'Q')
  152. break;
  153. const char* first = str.c_str();
  154. tree_parse_info<> info = pt_parse(first, expression);
  155. if (info.full)
  156. {
  157. #if defined(BOOST_SPIRIT_DUMP_PARSETREE_AS_XML)
  158. // dump parse tree as XML
  159. std::map<parser_id, std::string> rule_names;
  160. rule_names[integer.id()] = "integer";
  161. rule_names[factor.id()] = "factor";
  162. rule_names[term.id()] = "term";
  163. rule_names[expression.id()] = "expression";
  164. tree_to_xml(cout, info.trees, first, rule_names);
  165. #endif
  166. // print the result
  167. cout << "parsing succeeded\n";
  168. cout << "result = " << evaluate(info) << "\n\n";
  169. }
  170. else
  171. {
  172. cout << "parsing failed\n";
  173. }
  174. }
  175. cout << "Bye... :-) \n\n";
  176. return 0;
  177. }