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
107 lines
2.8 KiB
#pragma once
|
|
|
|
#include "cell.h"
|
|
|
|
#include <vector>
|
|
|
|
#include <boost/tokenizer.hpp>
|
|
#include <boost/fusion/adapted/struct.hpp>
|
|
#include <boost/spirit/include/qi.hpp>
|
|
#include <boost/spirit/include/phoenix.hpp>
|
|
#include <boost/spirit/include/phoenix_operator.hpp>
|
|
#include <boost/variant/recursive_wrapper.hpp>
|
|
#include <boost/spirit/include/support_line_pos_iterator.hpp>
|
|
|
|
namespace qi = boost::spirit::qi;
|
|
namespace phoenix = boost::phoenix;
|
|
|
|
typedef boost::spirit::line_pos_iterator<std::string::const_iterator> pos_iterator_t;
|
|
|
|
typedef std::vector<cell> row;
|
|
typedef std::vector<cell> cells;
|
|
|
|
BOOST_FUSION_ADAPT_STRUCT(
|
|
cell,
|
|
(Type, type)
|
|
(Color, color)
|
|
)
|
|
|
|
template<typename It>
|
|
struct annotation_f {
|
|
typedef void result_type;
|
|
|
|
annotation_f(It first) : first(first) {}
|
|
It const first;
|
|
|
|
template<typename Val, typename First, typename Last>
|
|
void operator()(Val& v, First f, Last l) const {
|
|
do_annotate(v, f, l, first);
|
|
}
|
|
|
|
private:
|
|
void static do_annotate(cell& c, It f, It l, It first) {
|
|
c.row = get_line(f) - 1;
|
|
c.column = get_column(first, f) / 2;
|
|
}
|
|
static void do_annotate(...) { std::cerr << "(not having LocationInfo)\n"; }
|
|
};
|
|
|
|
template <typename It>
|
|
struct MinigridParser : qi::grammar<It, row()>
|
|
{
|
|
MinigridParser(It first) : MinigridParser::base_type(row_), annotate(first)
|
|
{
|
|
using namespace qi;
|
|
type_.add
|
|
("W", Type::Wall)
|
|
(" ", Type::Floor)
|
|
("D", Type::Door)
|
|
("L", Type::LockedDoor)
|
|
("K", Type::Key)
|
|
("A", Type::Ball)
|
|
("B", Type::Box)
|
|
("G", Type::Goal)
|
|
("V", Type::Lava)
|
|
("n", Type::SlipperyNorth)
|
|
("e", Type::SlipperyEast)
|
|
("s", Type::SlipperySouth)
|
|
("w", Type::SlipperyWest)
|
|
("a", Type::SlipperyNorthWest)
|
|
("b", Type::SlipperyNorthEast)
|
|
("c", Type::SlipperySouthWest)
|
|
("d", Type::SlipperySouthEast)
|
|
("X", Type::Agent)
|
|
("Z", Type::Adversary);
|
|
color_.add
|
|
("R", Color::Red)
|
|
("G", Color::Green)
|
|
("B", Color::Blue)
|
|
("P", Color::Purple)
|
|
("Y", Color::Yellow)
|
|
("W", Color::White)
|
|
(" ", Color::None);
|
|
|
|
cell_ = type_ > color_;
|
|
|
|
row_ = (cell_ % -qi::char_("\n"));
|
|
|
|
auto set_location_info = annotate(_val, _1, _3);
|
|
on_success(cell_, set_location_info);
|
|
|
|
BOOST_SPIRIT_DEBUG_NODE(type_);
|
|
BOOST_SPIRIT_DEBUG_NODE(color_);
|
|
BOOST_SPIRIT_DEBUG_NODE(cell_);
|
|
}
|
|
|
|
private:
|
|
phoenix::function<annotation_f<It>> annotate;
|
|
|
|
qi::symbols<char, Type> type_;
|
|
qi::symbols<char, Color> color_;
|
|
|
|
qi::rule<It, cell()> cell_;
|
|
qi::rule<It, row()> row_;
|
|
};
|
|
|
|
typedef boost::tokenizer< boost::escaped_list_separator<char> , std::string::const_iterator, std::string> Tokenizer;
|
|
//std::ostream& operator<<(std::ostream& os, const row& r);
|