fork download
  1. #include <boost/config/warning_disable.hpp>
  2. #include <boost/spirit/include/qi.hpp>
  3. #include <boost/spirit/include/phoenix_core.hpp>
  4. #include <boost/spirit/include/phoenix_operator.hpp>
  5. #include <boost/spirit/include/phoenix_fusion.hpp>
  6. #include <boost/spirit/include/phoenix_stl.hpp>
  7. #include <boost/fusion/include/adapt_struct.hpp>
  8. #include <boost/variant/recursive_variant.hpp>
  9. #include <boost/foreach.hpp>
  10.  
  11. #include <iostream>
  12. #include <string>
  13. #include <vector>
  14.  
  15. namespace fun_lang {
  16. namespace qi = boost::spirit::qi;
  17. namespace ascii = boost::spirit::ascii;
  18. namespace phoenix = boost::phoenix;
  19. namespace fusion = boost::fusion;
  20.  
  21. struct number_node {
  22. long value;
  23. };
  24.  
  25. struct operation_node;
  26.  
  27. typedef boost::variant<
  28. boost::recursive_wrapper<operation_node>,
  29. number_node
  30. > node;
  31.  
  32. struct operation_node {
  33. node left, right;
  34. char op;
  35. };
  36.  
  37. struct program {
  38. std::vector<node> nodes;
  39. };
  40. }
  41.  
  42. BOOST_FUSION_ADAPT_STRUCT(fun_lang::program, (std::vector<fun_lang::node>, nodes));
  43. BOOST_FUSION_ADAPT_STRUCT(fun_lang::number_node, (long, value));
  44. BOOST_FUSION_ADAPT_STRUCT(fun_lang::operation_node, (fun_lang::node, left) (char, op) (fun_lang::node, right));
  45.  
  46. namespace fun_lang {
  47. template <typename Iterator, typename Skipper>
  48. struct fun_grammar : qi::grammar<Iterator, program(), Skipper> {
  49. fun_grammar() : fun_grammar::base_type(start) {
  50. using ascii::char_;
  51. using qi::ulong_;
  52. using qi::_val;
  53. using qi::_1;
  54.  
  55. using phoenix::push_back;
  56. using phoenix::at_c;
  57.  
  58. expression = (integer | operation)[_val = _1];
  59.  
  60. oper = (char_('+') | char_('-') | char_('*') | char_('/'))[_val = _1];
  61. integer = ulong_[at_c<0>(_val) = _1];
  62.  
  63. operation = expression[at_c<0>(_val) = _1] >> oper[at_c<1>(_val) = _1] >> expression[at_c<2>(_val) = _1];
  64.  
  65. start = *expression[push_back(at_c<0>(_val), _1)];
  66. }
  67.  
  68. qi::rule<Iterator, program(), Skipper> start;
  69. qi::rule<Iterator, number_node(), Skipper> integer;
  70. qi::rule<Iterator, char(), Skipper> oper;
  71. qi::rule<Iterator, node(), Skipper> expression;
  72. qi::rule<Iterator, operation_node(), Skipper> operation;
  73. };
  74.  
  75. struct node_printer : boost::static_visitor<> {
  76. void operator()(number_node const &node) const {
  77. std::cout << "number_node(" << node.value << ")\n";
  78. }
  79.  
  80. void operator()(operation_node const &node) const {
  81. std::cout << "operation_node(";
  82. std::cout << " "; boost::apply_visitor(*this, node.left);
  83. std::cout << " operator(" << node.op << ")\n";
  84. std::cout << " "; boost::apply_visitor(*this, node.right);
  85. std::cout << ")\n";
  86. }
  87. };
  88. }
  89.  
  90. int main(int argc, char *argv[]) {
  91. using std::cout;
  92.  
  93. std::string input;
  94. getline(std::cin, input);
  95. cout << "Received input \"" << input << "\"\n\n";
  96. typedef fun_lang::fun_grammar<std::string::const_iterator, boost::spirit::ascii::space_type> fun_grammar;
  97.  
  98. fun_grammar grammar;
  99. fun_lang::program program;
  100.  
  101. std::string::const_iterator begin = input.begin(), end = input.end();
  102. bool success = phrase_parse(begin, end, grammar, boost::spirit::ascii::space, program);
  103. if (success && begin == end) {
  104. cout << "Successful\n\n";
  105. fun_lang::node_printer printer;
  106. BOOST_FOREACH(fun_lang::node const &node, program.nodes) {
  107. boost::apply_visitor(printer, node);
  108. }
  109. } else {
  110. std::string::const_iterator some = begin + 30;
  111. std::string context(begin, (some > end) ? end : some);
  112. cout << "Failure: \"" << context << "\"\n\n";
  113. }
  114.  
  115. return 0;
  116. }
  117.  
  118.  
  119.  
Runtime error #stdin #stdout 0.01s 15488KB
stdin
1 + 1 - 1
stdout
Standard output is empty