extract parser driver
This commit is contained in:
parent
a38a105e6f
commit
c221dc9bf2
34
2022/13.cpp
34
2022/13.cpp
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include <doctest.h>
|
#include <doctest.h>
|
||||||
|
|
||||||
|
#include <aocpp/Parsing.hpp>
|
||||||
#include <aocpp/Startup.hpp>
|
#include <aocpp/Startup.hpp>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -69,13 +70,12 @@ auto operator<(Packet const& lhs, Packet const& rhs) -> bool {
|
||||||
// Packets can be integer literals or a list of packets.
|
// Packets can be integer literals or a list of packets.
|
||||||
// A list of packets is bracketed with square brackets and is comma-separated.
|
// A list of packets is bracketed with square brackets and is comma-separated.
|
||||||
// No additional whitespace is tolerated in the input stream.
|
// No additional whitespace is tolerated in the input stream.
|
||||||
template <typename It>
|
class Grammar : public qi::grammar<std::string::const_iterator, PacketPairs()> {
|
||||||
class Grammar : public qi::grammar<It, PacketPairs()> {
|
qi::rule<iterator_type, std::int64_t> integer;
|
||||||
qi::rule<It, std::int64_t> integer;
|
qi::rule<iterator_type, Packets()> packets;
|
||||||
qi::rule<It, Packets()> packets;
|
qi::rule<iterator_type, Packet()> packet;
|
||||||
qi::rule<It, Packet()> packet;
|
qi::rule<iterator_type, PacketPair()> packetPair;
|
||||||
qi::rule<It, PacketPair()> packetPair;
|
qi::rule<iterator_type, PacketPairs()> packetPairs;
|
||||||
qi::rule<It, PacketPairs()> packetPairs;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Grammar() : Grammar::base_type{packetPairs} {
|
Grammar() : Grammar::base_type{packetPairs} {
|
||||||
|
@ -91,22 +91,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Parse the complete input stream according to the rules defined in 'Grammar'.
|
|
||||||
/// Throws: std::runtime_error on failed parse
|
|
||||||
auto Parse(std::istream & in) -> PacketPairs
|
|
||||||
{
|
|
||||||
auto result = PacketPairs{};
|
|
||||||
auto const content = std::string{std::istreambuf_iterator{in}, {}};
|
|
||||||
auto b = content.begin(); // updated on successful parse
|
|
||||||
auto const e = content.end();
|
|
||||||
|
|
||||||
if (!qi::parse(b, e, Grammar<decltype(b)>{}, result) || b != e) {
|
|
||||||
throw std::runtime_error{"Bad packet: " + content};
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the sum 1-based indexes of the pairs where the first element is less than the second.
|
// Return the sum 1-based indexes of the pairs where the first element is less than the second.
|
||||||
auto Part1(PacketPairs const& packetPairs) -> std::size_t
|
auto Part1(PacketPairs const& packetPairs) -> std::size_t
|
||||||
{
|
{
|
||||||
|
@ -183,7 +167,7 @@ TEST_SUITE("2022-13 examples") {
|
||||||
"[1,[2,[3,[4,[5,6,7]]]],8,9]\n"
|
"[1,[2,[3,[4,[5,6,7]]]],8,9]\n"
|
||||||
"[1,[2,[3,[4,[5,6,0]]]],8,9]\n"
|
"[1,[2,[3,[4,[5,6,0]]]],8,9]\n"
|
||||||
};
|
};
|
||||||
auto const packetPairs = Parse(in);
|
auto const packetPairs = aocpp::ParseGrammar(Grammar{}, in);
|
||||||
CHECK(13 == Part1(packetPairs));
|
CHECK(13 == Part1(packetPairs));
|
||||||
CHECK(140 == Part2(packetPairs));
|
CHECK(140 == Part2(packetPairs));
|
||||||
}
|
}
|
||||||
|
@ -191,7 +175,7 @@ TEST_SUITE("2022-13 examples") {
|
||||||
|
|
||||||
auto Main(std::istream & in, std::ostream & out) -> void
|
auto Main(std::istream & in, std::ostream & out) -> void
|
||||||
{
|
{
|
||||||
auto const packetPairs = Parse(in);
|
auto const packetPairs = aocpp::ParseGrammar(Grammar{}, in);
|
||||||
out << "Part 1: " << Part1(packetPairs) << std::endl;
|
out << "Part 1: " << Part1(packetPairs) << std::endl;
|
||||||
out << "Part 2: " << Part2(packetPairs) << std::endl;
|
out << "Part 2: " << Part2(packetPairs) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
30
2022/14.cpp
30
2022/14.cpp
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#include <doctest.h>
|
#include <doctest.h>
|
||||||
|
|
||||||
|
#include <aocpp/Parsing.hpp>
|
||||||
#include <aocpp/Startup.hpp>
|
#include <aocpp/Startup.hpp>
|
||||||
#include <aocpp/Coord.hpp>
|
#include <aocpp/Coord.hpp>
|
||||||
|
|
||||||
|
@ -28,11 +29,10 @@ using Input = std::vector<std::vector<aocpp::Coord>>;
|
||||||
const aocpp::Coord TOP {500, 0};
|
const aocpp::Coord TOP {500, 0};
|
||||||
|
|
||||||
// Input file grammar
|
// Input file grammar
|
||||||
template <typename It>
|
class Grammar : public qi::grammar<std::string::const_iterator, Input()> {
|
||||||
class Grammar : public qi::grammar<It, Input()> {
|
qi::rule<iterator_type, aocpp::Coord> coord;
|
||||||
qi::rule<It, aocpp::Coord> coord;
|
qi::rule<iterator_type, std::vector<aocpp::Coord>()> line;
|
||||||
qi::rule<It, std::vector<aocpp::Coord>()> line;
|
qi::rule<iterator_type, Input()> input;
|
||||||
qi::rule<It, Input()> input;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Grammar() : Grammar::base_type{input} {
|
Grammar() : Grammar::base_type{input} {
|
||||||
|
@ -46,22 +46,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Parse the complete input stream according to the rules defined in 'Grammar'.
|
|
||||||
/// Throws: std::runtime_error on failed parse
|
|
||||||
auto Parse(std::istream & in) -> Input
|
|
||||||
{
|
|
||||||
auto result = Input{};
|
|
||||||
auto const content = std::string{std::istreambuf_iterator{in}, {}};
|
|
||||||
auto b = content.begin(); // updated on successful parse
|
|
||||||
auto const e = content.end();
|
|
||||||
|
|
||||||
if (!qi::parse(b, e, Grammar<decltype(b)>{}, result) || b != e) {
|
|
||||||
throw std::runtime_error{"Bad input file: " + content};
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ExpandLines(Input const& lines) -> std::unordered_set<aocpp::Coord>
|
auto ExpandLines(Input const& lines) -> std::unordered_set<aocpp::Coord>
|
||||||
{
|
{
|
||||||
auto result = std::unordered_set<aocpp::Coord>{};
|
auto result = std::unordered_set<aocpp::Coord>{};
|
||||||
|
@ -175,7 +159,7 @@ TEST_SUITE("2022-14 examples") {
|
||||||
"498,4 -> 498,6 -> 496,6\n"
|
"498,4 -> 498,6 -> 496,6\n"
|
||||||
"503,4 -> 502,4 -> 502,9 -> 494,9\n"
|
"503,4 -> 502,4 -> 502,9 -> 494,9\n"
|
||||||
};
|
};
|
||||||
auto const input = Parse(in);
|
auto const input = aocpp::ParseGrammar(Grammar{}, in);
|
||||||
auto const bottom = FindBottom(input);
|
auto const bottom = FindBottom(input);
|
||||||
auto world = ExpandLines(input);
|
auto world = ExpandLines(input);
|
||||||
CHECK(24 == Part1(bottom, world));
|
CHECK(24 == Part1(bottom, world));
|
||||||
|
@ -185,7 +169,7 @@ TEST_SUITE("2022-14 examples") {
|
||||||
|
|
||||||
auto Main(std::istream & in, std::ostream & out) -> void
|
auto Main(std::istream & in, std::ostream & out) -> void
|
||||||
{
|
{
|
||||||
auto const input = Parse(in);
|
auto const input = aocpp::ParseGrammar(Grammar{}, in);
|
||||||
auto const bottom = FindBottom(input);
|
auto const bottom = FindBottom(input);
|
||||||
auto world = ExpandLines(input);
|
auto world = ExpandLines(input);
|
||||||
out << "Part 1: " << Part1(bottom, world) << std::endl;
|
out << "Part 1: " << Part1(bottom, world) << std::endl;
|
||||||
|
|
30
2022/15.cpp
30
2022/15.cpp
|
@ -12,6 +12,7 @@
|
||||||
#include <doctest.h>
|
#include <doctest.h>
|
||||||
|
|
||||||
#include <aocpp/Coord.hpp>
|
#include <aocpp/Coord.hpp>
|
||||||
|
#include <aocpp/Parsing.hpp>
|
||||||
#include <aocpp/Startup.hpp>
|
#include <aocpp/Startup.hpp>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -27,11 +28,10 @@ struct Entry {
|
||||||
using Input = std::vector<Entry>;
|
using Input = std::vector<Entry>;
|
||||||
|
|
||||||
// Input file grammar
|
// Input file grammar
|
||||||
template <typename It>
|
class Grammar : public qi::grammar<std::string::const_iterator, Input()> {
|
||||||
class Grammar : public qi::grammar<It, Input()> {
|
qi::rule<iterator_type, aocpp::Coord> coord;
|
||||||
qi::rule<It, aocpp::Coord> coord;
|
qi::rule<iterator_type, Entry()> entry;
|
||||||
qi::rule<It, Entry()> entry;
|
qi::rule<iterator_type, Input()> input;
|
||||||
qi::rule<It, Input()> input;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Grammar() : Grammar::base_type{input} {
|
Grammar() : Grammar::base_type{input} {
|
||||||
|
@ -50,22 +50,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Parse the complete input stream according to the rules defined in 'Grammar'.
|
|
||||||
/// Throws: std::runtime_error on failed parse
|
|
||||||
auto Parse(std::istream & in) -> Input
|
|
||||||
{
|
|
||||||
auto result = Input{};
|
|
||||||
auto const content = std::string{std::istreambuf_iterator{in}, {}};
|
|
||||||
auto b = content.begin(); // updated on successful parse
|
|
||||||
auto const e = content.end();
|
|
||||||
|
|
||||||
if (!qi::parse(b, e, Grammar<decltype(b)>{}, result) || b != e) {
|
|
||||||
throw std::runtime_error{"Bad input file: " + content};
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Range {
|
struct Range {
|
||||||
std::int64_t lo, hi;
|
std::int64_t lo, hi;
|
||||||
auto operator<=>(Range const& rhs) const = default;
|
auto operator<=>(Range const& rhs) const = default;
|
||||||
|
@ -235,7 +219,7 @@ TEST_SUITE("2022-15 examples") {
|
||||||
"Sensor at x=14, y=3: closest beacon is at x=15, y=3\n"
|
"Sensor at x=14, y=3: closest beacon is at x=15, y=3\n"
|
||||||
"Sensor at x=20, y=1: closest beacon is at x=15, y=3\n"
|
"Sensor at x=20, y=1: closest beacon is at x=15, y=3\n"
|
||||||
};
|
};
|
||||||
auto const input = Parse(in);
|
auto const input = aocpp::ParseGrammar(Grammar{}, in);
|
||||||
CHECK(26 == Part1(input, 10));
|
CHECK(26 == Part1(input, 10));
|
||||||
CHECK(56000011 == Part2(input, 20));
|
CHECK(56000011 == Part2(input, 20));
|
||||||
}
|
}
|
||||||
|
@ -243,7 +227,7 @@ TEST_SUITE("2022-15 examples") {
|
||||||
|
|
||||||
auto Main(std::istream & in, std::ostream & out) -> void
|
auto Main(std::istream & in, std::ostream & out) -> void
|
||||||
{
|
{
|
||||||
auto const input = Parse(in);
|
auto const input = aocpp::ParseGrammar(Grammar{}, in);
|
||||||
out << "Part 1: " << Part1(input, 2'000'000) << std::endl;
|
out << "Part 1: " << Part1(input, 2'000'000) << std::endl;
|
||||||
out << "Part 2: " << Part2(input, 4'000'000) << std::endl;
|
out << "Part 2: " << Part2(input, 4'000'000) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
45
2022/16.cpp
45
2022/16.cpp
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include <doctest.h>
|
#include <doctest.h>
|
||||||
|
|
||||||
|
#include <aocpp/Parsing.hpp>
|
||||||
#include <aocpp/Startup.hpp>
|
#include <aocpp/Startup.hpp>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -80,25 +81,16 @@ struct Room {
|
||||||
std::vector<std::string> connections;
|
std::vector<std::string> connections;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Parse the input file
|
class Grammar : public qi::grammar<std::string::const_iterator, std::vector<Room>()> {
|
||||||
/// @param[in,out] in input stream
|
qi::rule<iterator_type, std::string()> name;
|
||||||
/// @return Vector of parsed rooms, one per input line
|
qi::rule<iterator_type, Room()> room_description;
|
||||||
///
|
qi::rule<iterator_type, std::vector<Room>()> room_descriptions;
|
||||||
/// The parser will consume input until the end of the stream.
|
|
||||||
///
|
|
||||||
/// Input lines should follow the following pattern:
|
|
||||||
/// * Valve **name** has flow rate= **number** ; tunnels lead to valves **name**, **name** ...
|
|
||||||
/// * Valve **name** has flow rate= **number** ; tunnel leads to valve **name**
|
|
||||||
auto Parse(std::istream & in) -> std::vector<Room>
|
|
||||||
{
|
|
||||||
auto result = std::vector<Room>{};
|
|
||||||
auto line = std::string{};
|
|
||||||
while (std::getline(in, line)) {
|
|
||||||
using namespace qi::labels;
|
|
||||||
using It = std::string::const_iterator;
|
|
||||||
|
|
||||||
qi::rule<It, std::string()> const name = qi::as_string[+qi::alpha];
|
public:
|
||||||
qi::rule<It, Room()> const room_description =
|
Grammar() : grammar::base_type{room_descriptions} {
|
||||||
|
using namespace qi::labels;
|
||||||
|
name = qi::as_string[+qi::alpha];
|
||||||
|
room_description =
|
||||||
"Valve " >>
|
"Valve " >>
|
||||||
name [ phx::bind(&Room::name, _val) = _1 ] >>
|
name [ phx::bind(&Room::name, _val) = _1 ] >>
|
||||||
" has flow rate=" >>
|
" has flow rate=" >>
|
||||||
|
@ -107,18 +99,11 @@ auto Parse(std::istream & in) -> std::vector<Room>
|
||||||
" lead" >> -qi::string("s") >>
|
" lead" >> -qi::string("s") >>
|
||||||
" to valve" >> -qi::string("s") >>
|
" to valve" >> -qi::string("s") >>
|
||||||
" " >>
|
" " >>
|
||||||
(name % ", ") [ phx::bind(&Room::connections, _val) = _1 ];
|
(name % ", ") [ phx::bind(&Room::connections, _val) = _1 ] >>
|
||||||
|
"\n";
|
||||||
auto b = line.cbegin();
|
room_descriptions = *room_description;
|
||||||
auto const e = line.cend();
|
|
||||||
result.emplace_back();
|
|
||||||
if (!qi::parse(b, e, room_description, result.back()) || b != e) {
|
|
||||||
throw std::runtime_error{"bad input line"};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Rearrange the rooms so that those with flows come first
|
/// @brief Rearrange the rooms so that those with flows come first
|
||||||
/// @param[in,out] rooms vector of rooms that gets reordered
|
/// @param[in,out] rooms vector of rooms that gets reordered
|
||||||
|
@ -287,7 +272,7 @@ auto Part2(
|
||||||
/// @param[in,out] out output text
|
/// @param[in,out] out output text
|
||||||
auto Main(std::istream & in, std::ostream & out) -> void
|
auto Main(std::istream & in, std::ostream & out) -> void
|
||||||
{
|
{
|
||||||
auto rooms = Parse(in);
|
auto rooms = aocpp::ParseGrammar(Grammar{}, in);
|
||||||
auto const n = FlowsFirst(rooms); // reorders rooms
|
auto const n = FlowsFirst(rooms); // reorders rooms
|
||||||
auto const [start, distances] = GenerateDistances(rooms);
|
auto const [start, distances] = GenerateDistances(rooms);
|
||||||
rooms.resize(n); // forget about the rooms with no flow
|
rooms.resize(n); // forget about the rooms with no flow
|
||||||
|
|
38
2022/21.cpp
38
2022/21.cpp
|
@ -15,6 +15,7 @@
|
||||||
#include <z3++.h>
|
#include <z3++.h>
|
||||||
|
|
||||||
#include <aocpp/Overloaded.hpp>
|
#include <aocpp/Overloaded.hpp>
|
||||||
|
#include <aocpp/Parsing.hpp>
|
||||||
#include <aocpp/Startup.hpp>
|
#include <aocpp/Startup.hpp>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -38,14 +39,13 @@ struct Entry {
|
||||||
using Input = std::vector<Entry>;
|
using Input = std::vector<Entry>;
|
||||||
|
|
||||||
// Input file grammar
|
// Input file grammar
|
||||||
template <typename It>
|
class Grammar : public qi::grammar<std::string::const_iterator, Input()> {
|
||||||
class Grammar : public qi::grammar<It, Input()> {
|
qi::rule<iterator_type, std::string()> variable;
|
||||||
qi::rule<It, std::string()> variable;
|
qi::rule<iterator_type, Op()> op;
|
||||||
qi::rule<It, Op()> op;
|
qi::rule<iterator_type, Expr()> expr;
|
||||||
qi::rule<It, Expr()> expr;
|
qi::rule<iterator_type, std::variant<std::int64_t, Expr>()> rhs;
|
||||||
qi::rule<It, std::variant<std::int64_t, Expr>()> rhs;
|
qi::rule<iterator_type, Entry()> line;
|
||||||
qi::rule<It, Entry()> line;
|
qi::rule<iterator_type, Input()> input;
|
||||||
qi::rule<It, Input()> input;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Grammar() : Grammar::base_type{input} {
|
Grammar() : Grammar::base_type{input} {
|
||||||
|
@ -69,22 +69,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Parse the complete input stream according to the rules defined in 'Grammar'.
|
|
||||||
/// Throws: std::runtime_error on failed parse
|
|
||||||
auto Parse(std::istream & in) -> Input
|
|
||||||
{
|
|
||||||
auto result = Input{};
|
|
||||||
auto const content = std::string{std::istreambuf_iterator{in}, {}};
|
|
||||||
auto b = content.begin(); // updated on successful parse
|
|
||||||
auto const e = content.end();
|
|
||||||
|
|
||||||
if (!qi::parse(b, e, Grammar<decltype(b)>{}, result) || b != e) {
|
|
||||||
throw std::runtime_error{"Bad input file: " + content};
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Eval(
|
auto Eval(
|
||||||
std::unordered_map<std::string, double> & values,
|
std::unordered_map<std::string, double> & values,
|
||||||
std::unordered_map<std::string, Expr> const& exprs,
|
std::unordered_map<std::string, Expr> const& exprs,
|
||||||
|
@ -191,15 +175,15 @@ TEST_SUITE("2022-21 examples") {
|
||||||
"drzm: hmdt - zczc\n"
|
"drzm: hmdt - zczc\n"
|
||||||
"hmdt: 32\n"
|
"hmdt: 32\n"
|
||||||
};
|
};
|
||||||
auto const input = Parse(in);
|
auto const input = aocpp::ParseGrammar(Grammar(), in);
|
||||||
CHECK(152 == Part1(input));
|
CHECK(152 == Part1(input));
|
||||||
CHECK(301 == Part2(input));
|
CHECK(301 == Part2(input));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Main(std::istream & in, std::ostream & out) -> void
|
auto Main(std::istream & in, std::ostream & out) -> void
|
||||||
{
|
{
|
||||||
auto const input = Parse(in);
|
auto const input = aocpp::ParseGrammar(Grammar(), in);
|
||||||
out << "Part 1: " << Part1(input) << std::endl;
|
out << "Part 1: " << Part1(input) << std::endl;
|
||||||
out << "Part 2: " << Part2(input) << std::endl;
|
out << "Part 2: " << Part2(input) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
66
2022/24.cpp
Normal file
66
2022/24.cpp
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <boost/range/adaptor/indexed.hpp>
|
||||||
|
|
||||||
|
#include <doctest.h>
|
||||||
|
|
||||||
|
#include <aocpp/Coord.hpp>
|
||||||
|
#include <aocpp/Startup.hpp>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct World {
|
||||||
|
std::vector<aocpp::Coord> ups, downs, lefts, rights;
|
||||||
|
std::size_t height, width;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto Parse(std::istream & in) -> World
|
||||||
|
{
|
||||||
|
auto result = World{};
|
||||||
|
auto y = std::size_t{0};
|
||||||
|
auto line = std::string{};
|
||||||
|
|
||||||
|
while (std::getline(in, line)) {
|
||||||
|
for (auto const [x,c] : boost::adaptors::index(line)) {
|
||||||
|
switch (c) {
|
||||||
|
case '>': result.rights.emplace_back(x-1,y-1); break;
|
||||||
|
case '<': result.lefts.emplace_back(x-1,y-1); break;
|
||||||
|
case '^': result.ups.emplace_back(x-1,y-1); break;
|
||||||
|
case 'v': result.downs.emplace_back(x-1,y-1); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++y;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.height = y - 2;
|
||||||
|
result.width = line.size() - 2;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST_SUITE("2022-24 examples") {
|
||||||
|
TEST_CASE("example") {
|
||||||
|
std::istringstream in {
|
||||||
|
"#.#####\n"
|
||||||
|
"#.....#\n"
|
||||||
|
"#>....#\n"
|
||||||
|
"#.....#\n"
|
||||||
|
"#...v.#\n"
|
||||||
|
"#.....#\n"
|
||||||
|
"#####.#\n"
|
||||||
|
};
|
||||||
|
auto const world = Parse(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Main(std::istream & in, std::ostream & out) -> void
|
||||||
|
{
|
||||||
|
auto const input = Parse(in);
|
||||||
|
//out << "Part 1: " << Part1(in) << std::endl;
|
||||||
|
}
|
|
@ -1,2 +1,3 @@
|
||||||
add_library(aocpp src/Startup.cpp src/Coord.cpp src/Parsing.cpp)
|
add_library(aocpp src/Startup.cpp src/Coord.cpp src/Parsing.cpp)
|
||||||
target_include_directories(aocpp PUBLIC include)
|
target_include_directories(aocpp PUBLIC include)
|
||||||
|
target_link_libraries(aocpp Boost::headers)
|
|
@ -2,12 +2,34 @@
|
||||||
#define AOCPP_PARSING_HPP_
|
#define AOCPP_PARSING_HPP_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <boost/spirit/home/qi.hpp>
|
||||||
|
|
||||||
namespace aocpp {
|
namespace aocpp {
|
||||||
|
|
||||||
auto SplitOn(std::string const& stuff, std::string const& sep) -> std::vector<std::string>;
|
auto SplitOn(std::string const& stuff, std::string const& sep) -> std::vector<std::string>;
|
||||||
|
|
||||||
|
/// Parse the complete input stream according to the rules defined in 'Grammar'.
|
||||||
|
/// Throws: std::runtime_error on failed parse
|
||||||
|
template <typename G>
|
||||||
|
auto ParseGrammar(G const& grammar, std::istream & in) -> typename G::start_type::attr_type
|
||||||
|
{
|
||||||
|
namespace qi = boost::spirit::qi;
|
||||||
|
auto result = typename G::start_type::attr_type {};
|
||||||
|
auto const content = std::string{std::istreambuf_iterator{in}, {}};
|
||||||
|
auto b = content.begin(); // updated on successful parse
|
||||||
|
auto const e = content.end();
|
||||||
|
|
||||||
|
if (!qi::parse(b, e, grammar, result) || b != e) {
|
||||||
|
throw std::runtime_error{"Bad input file: " + content};
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue
Block a user