Files
aocpp/lib/include/aocpp/Parsing.hpp
2024-12-28 14:24:10 -06:00

68 lines
1.9 KiB
C++

#ifndef AOCPP_PARSING_HPP_
#define AOCPP_PARSING_HPP_
#include <string>
#include <iostream>
#include <iterator>
#include <vector>
#include <boost/spirit/home/qi.hpp>
namespace aocpp {
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;
}
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::phrase_parse(b, e, grammar, qi::ascii::space, result) || b != e) {
throw std::runtime_error{"Bad input file: " + content};
}
return result;
}
template <typename R>
auto ParseSimple(std::istream& in, auto p) -> R
{
R result;
namespace qi = boost::spirit::qi;
auto const content = std::string{std::istreambuf_iterator{in}, {}};
qi::rule<std::string::const_iterator, R()> r { std::move(p) };
auto it = content.begin();
auto const end = content.end();
bool success = qi::parse(it, end, r, result);
if (!success || it != end) {
throw std::runtime_error("Parsing failed or input was not fully consumed.");
}
return result;
}
}
#endif