|
#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); |
|
} |
|
} |