#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/fusion/include/boost_tuple.hpp>
#include <boost/lexical_cast.hpp>
#include <string>
#include <vector>
#include <stdexcept>
namespace qi = boost::spirit::qi;
using qi::grammar;
using qi::ascii::space_type;
using boost::variant;
using boost::tuple;
using boost::static_visitor;
using boost::apply_visitor;
using std::vector;
using std::string;
using std::cout;
using std::endl;
using std::runtime_error;
typedef variant<tuple<int,int>,int> year_entry;
template<typename Iterator>
struct year_parser : grammar<Iterator, year_entry(), space_type>
{
year_parser() : year_parser::base_type(start)
{
using qi::int_;
start %= (int_ >> '-' >> int_) | int_;
}
qi::rule<Iterator, year_entry(), space_type> start;
};
struct year_visitor : public static_visitor<vector<int>>
{
vector<int> operator()(const tuple<int,int> &interval) const
{
if (interval.get<0>() > interval.get<1>())
runtime_error("wtf the yearz are bad!");
vector<int> years;
for (int year = interval.get<0>();
year <= interval.get<1>();
++year) years.push_back(year);
return years;
}
vector<int> operator()(int year) const
{
return vector<int>{year};
}
};
int main()
{
string years("2034-2040,1924-1926,2312,3452,1234-1236");
vector<year_entry> years_vec;
typedef string::const_iterator iterator;
iterator i = years.begin();
year_parser<iterator> parser;
bool result = phrase_parse(i, years.cend(), parser % ',', qi::ascii::space, years_vec);
if (!result) throw std::runtime_error("lol the string sucks!!!");
vector<int> all_years;
for (auto &entry : years_vec)
{
vector<int> vec = apply_visitor(year_visitor(), entry);
all_years.insert(all_years.end(), vec.begin(), vec.end());
}
for (auto year : all_years) cout << year << " ";
cout << endl;
return 0;
}