ast_calc2.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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. #include <boost/spirit/include/classic_core.hpp>
  9. #include <boost/spirit/include/classic_ast.hpp>
  10. #include <boost/assert.hpp>
  11. #include <iostream>
  12. #include <stack>
  13. #include <functional>
  14. #include <string>
  15. // This example shows how to use an AST and tree_iter_node instead of
  16. // tree_val_node
  17. ////////////////////////////////////////////////////////////////////////////
  18. using namespace std;
  19. using namespace BOOST_SPIRIT_CLASSIC_NS;
  20. typedef char const* iterator_t;
  21. typedef tree_match<iterator_t, node_iter_data_factory<> >
  22. parse_tree_match_t;
  23. typedef parse_tree_match_t::tree_iterator iter_t;
  24. typedef ast_match_policy<iterator_t, node_iter_data_factory<> > match_policy_t;
  25. typedef scanner<iterator_t, scanner_policies<iter_policy_t, match_policy_t> > scanner_t;
  26. typedef rule<scanner_t> rule_t;
  27. // grammar rules
  28. rule_t expression, term, factor, integer;
  29. ////////////////////////////////////////////////////////////////////////////
  30. long evaluate(parse_tree_match_t hit);
  31. long eval_expression(iter_t const& i);
  32. long eval_term(iter_t const& i);
  33. long eval_factor(iter_t const& i);
  34. long eval_integer(iter_t const& i);
  35. long evaluate(parse_tree_match_t hit)
  36. {
  37. return eval_expression(hit.trees.begin());
  38. }
  39. long eval_expression(iter_t const& i)
  40. {
  41. cout << "In eval_expression. i->value = " <<
  42. string(i->value.begin(), i->value.end()) <<
  43. " i->children.size() = " << i->children.size() << endl;
  44. cout << "ID: " << i->value.id().to_long() << endl;
  45. if (i->value.id() == integer.id())
  46. {
  47. BOOST_ASSERT(i->children.size() == 0);
  48. return strtol(i->value.begin(), 0, 10);
  49. }
  50. else if (i->value.id() == factor.id())
  51. {
  52. // factor can only be unary minus
  53. BOOST_ASSERT(*i->value.begin() == '-');
  54. return - eval_expression(i->children.begin());
  55. }
  56. else if (i->value.id() == term.id())
  57. {
  58. if (*i->value.begin() == '*')
  59. {
  60. BOOST_ASSERT(i->children.size() == 2);
  61. return eval_expression(i->children.begin()) *
  62. eval_expression(i->children.begin()+1);
  63. }
  64. else if (*i->value.begin() == '/')
  65. {
  66. BOOST_ASSERT(i->children.size() == 2);
  67. return eval_expression(i->children.begin()) /
  68. eval_expression(i->children.begin()+1);
  69. }
  70. else
  71. BOOST_ASSERT(0);
  72. }
  73. else if (i->value.id() == expression.id())
  74. {
  75. if (*i->value.begin() == '+')
  76. {
  77. BOOST_ASSERT(i->children.size() == 2);
  78. return eval_expression(i->children.begin()) +
  79. eval_expression(i->children.begin()+1);
  80. }
  81. else if (*i->value.begin() == '-')
  82. {
  83. BOOST_ASSERT(i->children.size() == 2);
  84. return eval_expression(i->children.begin()) -
  85. eval_expression(i->children.begin()+1);
  86. }
  87. else
  88. BOOST_ASSERT(0);
  89. }
  90. else
  91. BOOST_ASSERT(0); // error
  92. return 0;
  93. }
  94. ////////////////////////////////////////////////////////////////////////////
  95. int
  96. main()
  97. {
  98. BOOST_SPIRIT_DEBUG_RULE(integer);
  99. BOOST_SPIRIT_DEBUG_RULE(factor);
  100. BOOST_SPIRIT_DEBUG_RULE(term);
  101. BOOST_SPIRIT_DEBUG_RULE(expression);
  102. // Start grammar definition
  103. integer = leaf_node_d[ lexeme_d[ (!ch_p('-') >> +digit_p) ] ];
  104. factor = integer
  105. | inner_node_d[ch_p('(') >> expression >> ch_p(')')]
  106. | (root_node_d[ch_p('-')] >> factor);
  107. term = factor >>
  108. *( (root_node_d[ch_p('*')] >> factor)
  109. | (root_node_d[ch_p('/')] >> factor)
  110. );
  111. expression = term >>
  112. *( (root_node_d[ch_p('+')] >> term)
  113. | (root_node_d[ch_p('-')] >> term)
  114. );
  115. // End grammar definition
  116. cout << "/////////////////////////////////////////////////////////\n\n";
  117. cout << "\t\tThe simplest working calculator...\n\n";
  118. cout << "/////////////////////////////////////////////////////////\n\n";
  119. cout << "Type an expression...or [q or Q] to quit\n\n";
  120. string str;
  121. while (getline(cin, str))
  122. {
  123. if (str.empty() || str[0] == 'q' || str[0] == 'Q')
  124. break;
  125. const char* str_begin = str.c_str();
  126. const char* str_end = str.c_str();
  127. while (*str_end)
  128. ++str_end;
  129. scanner_t scan(str_begin, str_end);
  130. parse_tree_match_t hit = expression.parse(scan);
  131. if (hit && str_begin == str_end)
  132. {
  133. #if defined(BOOST_SPIRIT_DUMP_PARSETREE_AS_XML)
  134. // dump parse tree as XML
  135. std::map<rule_id, std::string> rule_names;
  136. rule_names[&integer] = "integer";
  137. rule_names[&factor] = "factor";
  138. rule_names[&term] = "term";
  139. rule_names[&expression] = "expression";
  140. tree_to_xml(cout, hit.trees, str.c_str(), rule_names);
  141. #endif
  142. // print the result
  143. cout << "parsing succeeded\n";
  144. cout << "result = " << evaluate(hit) << "\n\n";
  145. }
  146. else
  147. {
  148. cout << "parsing failed\n";
  149. }
  150. }
  151. cout << "Bye... :-) \n\n";
  152. return 0;
  153. }