fork(1) download
  1. #include <boost/spirit/include/qi.hpp>
  2. #include <boost/spirit/include/phoenix_operator.hpp>
  3. #include <boost/variant/variant.hpp>
  4.  
  5. #include <iostream>
  6. #include <string>
  7. #include <vector>
  8. #include <cmath>
  9.  
  10. namespace qi = boost::spirit::qi;
  11. namespace ascii = boost::spirit::ascii;
  12.  
  13. struct STNode
  14. {
  15. enum {ROOT, DOUBLE, STRING, ADD, SUB, MUL, DIV, POW, MINUS, PRINT};
  16.  
  17. STNode() : type(ROOT) {}
  18.  
  19. int type;
  20. boost::variant<double, std::vector<char>, boost::spirit::unused_type> value;
  21. std::vector<STNode> children;
  22.  
  23. double Eval(std::ostream & os = std::cout)
  24. {
  25. switch(type)
  26. {
  27. case ROOT : return children[0].Eval();
  28. case DOUBLE : return boost::get<double>(value);
  29. case ADD : return children[1].Eval() + children[0].Eval();
  30. case SUB : return children[1].Eval() - children[0].Eval();
  31. case MUL : return children[1].Eval() * children[0].Eval();
  32. case DIV : return children[1].Eval() / children[0].Eval();
  33. case POW : return std::pow(children[1].Eval(), children[0].Eval());
  34. case MINUS : return - children[0].Eval();
  35. case PRINT : return children[0].Eval();
  36. case STRING :
  37. {
  38. std::vector<char> str = boost::get<std::vector<char> >(value);
  39. os << std::string(str.begin(), str.end()) << std::endl; return 0.0;
  40. }
  41. }
  42. }
  43. } st;
  44.  
  45. struct AddNode
  46. {
  47. int nodeType;
  48. STNode & root;
  49.  
  50. AddNode(STNode & r, int type) : nodeType(type), root(r) {}
  51.  
  52. void operator()(boost::variant<double, std::vector<char>, boost::spirit::unused_type> value,
  53. boost::spirit::unused_type, boost::spirit::unused_type) const
  54. {
  55. STNode newNode;
  56.  
  57. newNode.type = nodeType;
  58. newNode.value = value;
  59.  
  60. if (nodeType == STNode::DOUBLE || nodeType == STNode::STRING)
  61. root.children.push_back(newNode);
  62. else
  63. {
  64. newNode.children.push_back(root.children.back());
  65. root.children.pop_back();
  66.  
  67. if (!root.children.empty())
  68. {
  69. newNode.children.push_back(root.children.back());
  70. root.children.pop_back();
  71. }
  72.  
  73. root.children.push_back(newNode);
  74. }
  75. }
  76. };
  77.  
  78. template <typename Iterator>
  79. struct interpreter_grammar : qi::grammar<Iterator, int(), ascii::space_type>
  80. {
  81. interpreter_grammar() : interpreter_grammar::base_type(entry)
  82. {
  83. entry = math_expression [qi::_val = 1] | print_expression [qi::_val = qi::_1] ;
  84.  
  85. math_expression = term >>
  86. *( ('+' >> term) [AddNode(st, STNode::ADD)]
  87. | ('-' >> term) [AddNode(st, STNode::SUB)]);
  88.  
  89. term = factor >>
  90. *( ('*' >> factor) [AddNode(st, STNode::MUL)]
  91. | ('/' >> factor) [AddNode(st, STNode::DIV)]);
  92.  
  93. factor = primary >> *('^' >> primary [AddNode(st, STNode::POW)]);
  94.  
  95. primary = qi::double_ [AddNode(st, STNode::DOUBLE)]
  96. | '(' >> math_expression >> ')'
  97. | '-' >> !(qi::lit('-')|'+') >> primary [AddNode(st, STNode::MINUS)]
  98. | '+' >> !(qi::lit('-')|'+') >> primary;
  99.  
  100. print_expression = qi::lexeme["print" >> qi::space] >> (
  101. math_expression [qi::_val = 1]
  102. | qi::lexeme[('"' >> (*(qi::char_ - '"')) [AddNode(st, STNode::STRING)]
  103. >> qi::lit('"') [AddNode(st, STNode::PRINT)] ) [qi::_val = 2]]);
  104. }
  105.  
  106. qi::rule<Iterator, int(), ascii::space_type> entry, print_expression, math_expression;
  107. qi::rule<Iterator, ascii::space_type> term, factor, primary;
  108. };
  109.  
  110. int main()
  111. {
  112. using namespace std;
  113.  
  114. cout << "type an expression... or empty line to quit\n\n";
  115.  
  116. interpreter_grammar<string::const_iterator> my_grammar;
  117.  
  118. string str;
  119.  
  120. while (getline(cin, str))
  121. {
  122. if (str.empty()) break;
  123.  
  124. string::const_iterator iter = str.begin();
  125. string::const_iterator end = str.end();
  126.  
  127. int exp_type; st = STNode();
  128.  
  129. bool r = phrase_parse(iter, end, my_grammar, ascii::space, exp_type);
  130.  
  131. if (r && iter == end)
  132. {
  133. double result = st.Eval();
  134. if (exp_type == 1) cout << result << endl;
  135. }
  136. else cout << "invalid expression..." << endl;
  137. }
  138.  
  139. return 0;
  140. }
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty