You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

107 lines
2.8 KiB

3 months ago
  1. #pragma once
  2. #include "cell.h"
  3. #include <vector>
  4. #include <boost/tokenizer.hpp>
  5. #include <boost/fusion/adapted/struct.hpp>
  6. #include <boost/spirit/include/qi.hpp>
  7. #include <boost/spirit/include/phoenix.hpp>
  8. #include <boost/spirit/include/phoenix_operator.hpp>
  9. #include <boost/variant/recursive_wrapper.hpp>
  10. #include <boost/spirit/include/support_line_pos_iterator.hpp>
  11. namespace qi = boost::spirit::qi;
  12. namespace phoenix = boost::phoenix;
  13. typedef boost::spirit::line_pos_iterator<std::string::const_iterator> pos_iterator_t;
  14. typedef std::vector<cell> row;
  15. typedef std::vector<cell> cells;
  16. BOOST_FUSION_ADAPT_STRUCT(
  17. cell,
  18. (Type, type)
  19. (Color, color)
  20. )
  21. template<typename It>
  22. struct annotation_f {
  23. typedef void result_type;
  24. annotation_f(It first) : first(first) {}
  25. It const first;
  26. template<typename Val, typename First, typename Last>
  27. void operator()(Val& v, First f, Last l) const {
  28. do_annotate(v, f, l, first);
  29. }
  30. private:
  31. void static do_annotate(cell& c, It f, It l, It first) {
  32. c.row = get_line(f) - 1;
  33. c.column = get_column(first, f) / 2;
  34. }
  35. static void do_annotate(...) { std::cerr << "(not having LocationInfo)\n"; }
  36. };
  37. template <typename It>
  38. struct MinigridParser : qi::grammar<It, row()>
  39. {
  40. MinigridParser(It first) : MinigridParser::base_type(row_), annotate(first)
  41. {
  42. using namespace qi;
  43. type_.add
  44. ("W", Type::Wall)
  45. (" ", Type::Floor)
  46. ("D", Type::Door)
  47. ("L", Type::LockedDoor)
  48. ("K", Type::Key)
  49. ("A", Type::Ball)
  50. ("B", Type::Box)
  51. ("G", Type::Goal)
  52. ("V", Type::Lava)
  53. ("n", Type::SlipperyNorth)
  54. ("e", Type::SlipperyEast)
  55. ("s", Type::SlipperySouth)
  56. ("w", Type::SlipperyWest)
  57. ("a", Type::SlipperyNorthWest)
  58. ("b", Type::SlipperyNorthEast)
  59. ("c", Type::SlipperySouthWest)
  60. ("d", Type::SlipperySouthEast)
  61. ("X", Type::Agent)
  62. ("Z", Type::Adversary);
  63. color_.add
  64. ("R", Color::Red)
  65. ("G", Color::Green)
  66. ("B", Color::Blue)
  67. ("P", Color::Purple)
  68. ("Y", Color::Yellow)
  69. ("W", Color::White)
  70. (" ", Color::None);
  71. cell_ = type_ > color_;
  72. row_ = (cell_ % -qi::char_("\n"));
  73. auto set_location_info = annotate(_val, _1, _3);
  74. on_success(cell_, set_location_info);
  75. BOOST_SPIRIT_DEBUG_NODE(type_);
  76. BOOST_SPIRIT_DEBUG_NODE(color_);
  77. BOOST_SPIRIT_DEBUG_NODE(cell_);
  78. }
  79. private:
  80. phoenix::function<annotation_f<It>> annotate;
  81. qi::symbols<char, Type> type_;
  82. qi::symbols<char, Color> color_;
  83. qi::rule<It, cell()> cell_;
  84. qi::rule<It, row()> row_;
  85. };
  86. typedef boost::tokenizer< boost::escaped_list_separator<char> , std::string::const_iterator, std::string> Tokenizer;
  87. //std::ostream& operator<<(std::ostream& os, const row& r);