fork download
  1. #include <boost/variant.hpp>
  2. #include <functional>
  3. #include <iostream>
  4. #include <vector>
  5.  
  6. typedef boost::make_recursive_variant<std::string,
  7. // put anything else you want here (e.g. double, int, some custom type)
  8. std::vector<boost::recursive_variant_>>::type semantic_value_t;
  9.  
  10. struct success_t {
  11. semantic_value_t val;
  12. std::string rest;
  13. };
  14.  
  15. struct failure_t {
  16. std::string msg;
  17. std::string rest;
  18. };
  19.  
  20. typedef std::string parser_arg_t;
  21. typedef boost::variant<success_t, failure_t> parser_result_t;
  22. typedef std::function<parser_result_t(parser_arg_t)> parser_t;
  23.  
  24. typedef semantic_value_t generator_arg_t;
  25. typedef parser_t generator_result_t;
  26. typedef std::function<generator_result_t(generator_arg_t)> generator_t;
  27.  
  28. typedef std::vector<parser_t> combinator_arg_t;
  29. typedef parser_t combinator_result_t;
  30. typedef std::function<combinator_result_t(combinator_arg_t)> combinator_t;
  31.  
  32. auto lit = [](generator_arg_t match_v) -> parser_t {
  33.  
  34. return [=](std::string input) -> parser_result_t {
  35.  
  36. auto match = boost::get<std::string>(match_v);
  37.  
  38. auto inLen = input.length();
  39. auto mLen = match.length();
  40.  
  41. auto len = mLen < inLen ? mLen : inLen;
  42.  
  43. auto head = input.substr(0, len);
  44. auto tail = input.substr(len, inLen - 1);
  45.  
  46. if (head == match) return success_t{match, tail };
  47. else return failure_t{"error", input};
  48. };
  49. };
  50.  
  51. auto succeed = [](generator_arg_t val) -> parser_t {
  52.  
  53. return [=](std::string input) -> parser_result_t {
  54.  
  55. return success_t{val, input};
  56. };
  57. };
  58.  
  59. auto alt = [](combinator_arg_t parsers) -> parser_t {
  60.  
  61. return [=](std::string input) -> parser_result_t {
  62.  
  63. for (auto parser : parsers) {
  64. parser_result_t result = parser(input);
  65.  
  66. if (success_t * pret = boost::get<success_t>(&result))
  67. return *pret;
  68. }
  69.  
  70. return failure_t{"error", input};
  71. };
  72. };
  73.  
  74. auto seq = [](combinator_arg_t parsers) -> parser_t {
  75.  
  76. return [=](std::string input) -> parser_result_t {
  77.  
  78. semantic_value_t val{std::vector<semantic_value_t>{}};
  79. std::string rest = input;
  80.  
  81. for (auto parser : parsers) {
  82.  
  83. auto r = parser(rest);
  84.  
  85. if (failure_t * pr = boost::get<failure_t>(&r))
  86. return failure_t{"error", input};
  87.  
  88. success_t * pr = boost::get<success_t>(&r);
  89.  
  90. boost::get<std::vector<semantic_value_t>>(&val)->push_back(pr->val);
  91.  
  92. rest = pr->rest;
  93. }
  94.  
  95. return success_t{val, rest};
  96. };
  97. };
  98.  
  99. struct semantic_value_printer : boost::static_visitor<> {
  100.  
  101. template <class T>
  102. void operator()(const T & val) const { std::cout << val; }
  103.  
  104. void operator()(const std::string & val) const { std::cout << '"' << val << '"'; }
  105.  
  106. void operator()(const std::vector<semantic_value_t> & vec) const {
  107. std::cout << "[ ";
  108.  
  109. for (auto val : vec) {
  110. boost::apply_visitor(semantic_value_printer(), val);
  111. std::cout << ' ';
  112. }
  113.  
  114. std::cout << ']';
  115. }
  116. };
  117.  
  118. struct result_printer : boost::static_visitor<> {
  119.  
  120. void operator()(const success_t & s) const {
  121. std::cout << "success("; boost::apply_visitor(semantic_value_printer(), s.val);
  122. std::cout << ", \"" << s.rest << "\")" << std::endl;
  123. }
  124.  
  125. void operator()(const failure_t & f) const {
  126. std::cout << "failure(" << '"' << f.msg << "\", \"" << f.rest << "\")" << std::endl;
  127. }
  128. };
  129.  
  130. int main()
  131. {
  132. parser_t number = alt({lit("0"), lit("1"), lit("2"), lit("3"), lit("4"),
  133. lit("5"), lit("6"), lit("7"), lit("8"), lit("9")});
  134.  
  135. parser_t term;
  136. term = [&](std::string input) { return
  137. alt({
  138. seq({number, lit("*"), term}),
  139. number,
  140. })(input);
  141. };
  142.  
  143. parser_t expr;
  144. expr = [&](std::string input) { return
  145. alt({
  146. seq({term, lit("+"), expr}),
  147. term,
  148. })(input);
  149. };
  150.  
  151. auto results = {
  152. lit("Hello")("HelloWorld!"),
  153. seq({lit("asdf"), lit("qwerty")})("asdfqwerty"),
  154. alt({lit("qwerty"), lit("asdf")})("asdfqwerty"),
  155. expr("1+2*3+4*5+6")
  156. };
  157.  
  158. for (auto result : results)
  159. boost::apply_visitor(result_printer(), result);
  160. }
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
prog.cpp:1:29: fatal error: boost/variant.hpp: No such file or directory
 #include <boost/variant.hpp>
                             ^
compilation terminated.
stdout
Standard output is empty