Skip to content

Instantly share code, notes, and snippets.

@plasma-effect
Last active January 2, 2017 08:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save plasma-effect/98f2bc0a6cef9599a1badc7c3ea3237c to your computer and use it in GitHub Desktop.
Save plasma-effect/98f2bc0a6cef9599a1badc7c3ea3237c to your computer and use it in GitHub Desktop.
#pragma once
#include<optional>
#include<variant>
#include<tuple>
#include<string_view>
#include<functional>
#include<array>
#include<set>
namespace single_parse
{
namespace helper
{
template<std::size_t I>struct index_t
{
};
namespace detail
{
template<char... Cs>constexpr std::size_t make_index()
{
char ar[] = { Cs... };
std::size_t ret{};
for (std::size_t i{};i < sizeof...(Cs);++i)
{
ret = 10 * ret;
ret = ar[i] - '0' + ret;
}
return ret;
}
}
template<std::size_t Lhs, std::size_t Rhs>constexpr auto operator,(index_t<Lhs>, index_t<Rhs>)
{
return std::make_tuple(index_t<Lhs>(), index_t<Rhs>());
}
template<std::size_t Rhs, std::size_t... Is>constexpr auto operator,(std::tuple<index_t<Is>...>, index_t<Rhs>)
{
return std::make_tuple(index_t<Is>()..., index_t<Rhs>());
}
}
template<char... Cs>constexpr auto operator"" _()
{
return helper::index_t<helper::detail::make_index<Cs...>()>();
}
namespace atomic_type
{
struct space_type
{
constexpr bool operator()(char c)const
{
return c == ' ';
}
constexpr bool operator()(wchar_t c)const
{
return c == L' ';
}
constexpr bool operator()(char16_t c)const
{
return c == u' ';
}
constexpr bool operator()(char32_t c)const
{
return c == U' ';
}
};
}
constexpr atomic_type::space_type space{};
namespace detail
{
template<class CharT, std::size_t I>struct skip_check_t
{
std::array<std::function<bool(CharT)>, I> funcs;
bool operator()(CharT c)const
{
for (auto const& f : funcs)
{
if (f(c))
{
return true;
}
}
return false;
}
};
template<class CharT, class Expr>auto parse(std::basic_string_view<CharT> view, Expr const& expr)
{
return expr.parse(view, [&](auto view) {return parse(view, expr);});
}
template<class CharT, class Expr, class Skipper>auto phrase_parse(std::basic_string_view<CharT> view, Expr const& expr, Skipper const& skipper)
{
return expr.phrase_parse(view, [&](auto view) {return phrase_parse(view, expr, skipper);}, skipper);
}
}
template<class CharT, class Expr>auto parse(std::basic_string<CharT>const& str, Expr const& expr)
->typename Expr::template result_t<CharT>
{
return detail::parse(std::basic_string_view<CharT>(str), expr);
}
template<class CharT, class Expr, class... Ts>auto phrase_parse(std::basic_string<CharT>const& str, Expr const& expr, Ts&&... skipper)
->typename Expr::template result_t<CharT>
{
detail::skip_check_t<CharT, sizeof...(Ts)> skip{ std::array<std::function<bool(CharT)>,sizeof...(Ts)>{ std::function<bool(CharT)>(skipper)... } };
return detail::phrase_parse(std::basic_string_view<CharT>(str), expr, skip);
}
namespace type
{
namespace detail
{
char zero(char)
{
return '0';
}
wchar_t zero(wchar_t)
{
return L'0';
}
char16_t zero(char16_t)
{
return u'0';
}
char32_t zero(char32_t)
{
return U'0';
}
char minus(char)
{
return '-';
}
wchar_t minus(wchar_t)
{
return L'-';
}
char16_t minus(char16_t)
{
return u'-';
}
char32_t minus(char32_t)
{
return U'-';
}
}
struct integer_parsing
{
template<class CharT>struct result
{
long long value;
std::basic_string_view<CharT> view;
};
template<class CharT>using result_t = std::optional<result<CharT>>;
template<class CharT, class Recur>std::optional<result<CharT>> parse(std::basic_string_view<CharT> view, Recur const& recur)const
{
auto z = detail::zero(CharT());
if (view.size() == 0)
{
return std::nullopt;
}
bool f = view.front() == detail::minus(CharT());
std::basic_string_view<CharT> nview = f ? view.substr(1) : view;
if (nview.size() == 0 || !(nview.front() >= z&&nview.front() < (z + 10)))
{
return std::nullopt;
}
long long ret{};
for (std::size_t i{};i < nview.size();++i)
{
if (!(nview[i] >= z&&nview[i] < (z + 10)))
{
return result<CharT>{(f ? -ret : ret), view.substr(0, i + f)};
}
long long v = nview[i] - z;
ret *= 10;
ret += v;
if (ret < 0)
{
return std::nullopt;
}
}
return result<CharT>{(f ? -ret : ret), view};
}
template<class CharT, class Recur, class T>std::optional<result<CharT>> phrase_parse(std::basic_string_view<CharT> v, Recur const& recur, T const& skip)const
{
std::size_t s{};
for (;s < v.size();++s)
{
if (!skip(v[s]))
{
break;
}
}
std::basic_string_view<CharT> view = v.substr(s);
auto z = detail::zero(CharT());
if (view.size() == 0)
{
return std::nullopt;
}
bool f = view.front() == detail::minus(CharT());
std::basic_string_view<CharT> nview = f ? view.substr(1) : view;
if (nview.size() == 0 || !(nview.front() >= z&&nview.front() < (z + 10)))
{
return std::nullopt;
}
long long ret{};
for (std::size_t i{};i < nview.size();++i)
{
if (!(nview[i] >= z&&nview[i] < (z + 10)))
{
return result<CharT>{(f ? -ret : ret), view.substr(0, i + f)};
}
long long v = nview[i] - z;
ret *= 10;
ret += v;
if (ret < 0)
{
return std::nullopt;
}
}
return result<CharT>{(f ? -ret : ret), view};
}
};
template<class CharT>struct literal_parsing
{
std::set<CharT> set;
template<std::size_t I>literal_parsing(CharT const (&ar)[I])
{
for (auto c : ar)
{
set.emplace(c);
}
}
struct result
{
CharT c;
std::basic_string_view<CharT> view;
};
template<class>using result_t = std::optional<result>;
template<class CharT, class Recur>std::optional<result> parse(std::basic_string_view<CharT> view, Recur const& recur)const
{
if (view.size() == 0)
{
return std::nullopt;
}
if (set.count(view.front()))
{
return result{ view.front(),view.substr(0,1) };
}
return std::nullopt;
}
template<class CharT, class Recur,class Skipper>std::optional<result> phrase_parse(std::basic_string_view<CharT> view, Recur const& recur,Skipper const& skipper)const
{
for (std::size_t s{};s < view.size();++s)
{
if (!skipper(view[s]))
{
return parse(view.substr(s), recur);
}
}
return std::nullopt;
}
};
}
const type::integer_parsing int_;
template<class CharT, std::size_t I>type::literal_parsing<CharT> literal_(CharT const(&ar)[I])
{
return type::literal_parsing<CharT>(ar);
}
}

使い方

#include<iostream>
#include<string>
#include"single_parse.hpp"

int main()
{
	using namespace single_parse;
	std::string str;
	std::getline(std::cin, str);
	if (auto p = parse(str, int_))
	{
		std::cout << p->value << std::endl;
	}
	if (auto p = phrase_parse(str, int_, space))
	{
		std::cout << p->value << std::endl;
	}
}

って感じで使う。今のところint_にのみ対応している。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment