Skip to content

Instantly share code, notes, and snippets.

@plasma-effect
Last active October 14, 2016 02:35
Show Gist options
  • Save plasma-effect/ceb4fb3c3430fdf844da69474233377c to your computer and use it in GitHub Desktop.
Save plasma-effect/ceb4fb3c3430fdf844da69474233377c to your computer and use it in GitHub Desktop.
regexpr
#pragma once
// Copyright plasma-effect 2015
// Distributed under the Boost Software License, Version 1.0.
// (See http://www.boost.org/LICENSE_1_0.txt)
#include<type_traits>
#include<cinttypes>
#include<typeindex>
#include<vector>
#include<stack>
#include<boost/optional.hpp>
namespace regexpr
{
namespace detail
{
template<class Iterator>using is_char =
std::enable_if_t<std::is_same<typename std::iterator_traits<Iterator>::value_type, char>::value>;
template<class Iterator>using is_wchar =
std::enable_if_t<std::is_same<typename std::iterator_traits<Iterator>::value_type, wchar_t>::value>;
template<class T>struct getnum_t;
template<>struct getnum_t<char>
{
static constexpr char run(int v)
{
return '0' + v;
}
};
template<>struct getnum_t<wchar_t>
{
static constexpr wchar_t run(int v)
{
return L'0' + v;
}
};
template<class T>constexpr auto getnum(int v)
{
return getnum_t<T>::run(v);
}
template<class T>struct int_assign
{
T& val;
template<class IIterator>void operator()(IIterator first, IIterator last)const
{
val = 0;
for (;first != last;++first)
{
val = val * 10 + static_cast<T>(*first - getnum<typename std::iterator_traits<IIterator>::value_type>(0));
}
}
};
}
template<class T, class Action>struct integer_action_
{
Action action;
template<class IIterator>auto operator()(IIterator first, IIterator last)const
{
T val{};
while (first != last)
{
val = 10 * val + static_cast<T>(*first - detail::getnum<typename std::iterator_traits<IIterator>::value_type>(0));
++first;
}
action(val);
}
};
template<class T, class Action>auto integer_action(
Action action,
std::enable_if_t<std::is_integral<T>::value>* = nullptr)
{
return integer_action_<T, Action>{action};
}
template<class IIterator>struct expression_tree
{
std::type_index type;
IIterator first, last;
std::vector<expression_tree> child;
};
namespace expression
{
template<class Expr, class Action>struct action_
{
Expr expr;
Action action;
static constexpr bool left_recursion = Expr::left_recursion;
template<class IIterator, class Recur>auto parse(IIterator first, IIterator last, Recur const& recur)const
{
auto ret = expr.parse(first, last, recur);
if (ret)
{
action(first, ret->last);
}
return ret;
}
};
template<class Expr, std::size_t Index>struct indexed_expr_
{
Expr expr;
static constexpr bool left_recursion = Expr::left_recursion;
template<class IIterator,class Recur>
boost::optional<expression_tree<IIterator>>parse(
IIterator first,
IIterator last,
Recur const& recur)const
{
auto p = expr.parse(first, last, recur);
if (p)
{
p->type = typeid(std::integral_constant<std::size_t, Index>);
}
return p;
}
template<class Action>auto operator[](Action action)const
{
return action_<Action, indexed_expr_>{*this, action};
}
};
struct recursion_tag
{
static constexpr bool left_recursion = true;
template<class IIterator, class Recur>auto parse(IIterator first, IIterator last, Recur const& recur)const
{
return recur.parse(first, last, recur);
}
template<class Action>auto operator[](Action action)const
{
return action_<recursion_tag, Action>{*this, action};
}
};
template<class Expr>struct self_recursion
{
Expr expr;
static constexpr bool left_recursion = false;
template<class IIterator, class Recur>auto parse(IIterator first, IIterator last, Recur const&)const
{
return expr.parse(first, last, expr);
}
template<class Action>auto operator[](Action action)const
{
return action_<self_recursion, Action>{*this, action};
}
};
template<class Expr>struct ignore_
{
Expr expr;
static constexpr bool left_recursion = Expr::left_recursion;
template<class IIterator, class Recur>
boost::optional<expression_tree<IIterator>>parse(
IIterator first,
IIterator last,
Recur const& recur)const
{
auto p = expr.parse(first, last, recur);
if (p)
{
p->child.clear();
}
return p;
}
template<class Action>auto operator[](Action action)const
{
return action_<Action, ignore_>{*this, action};
}
};
struct number_
{
static constexpr bool left_recursion = false;
template<class IIterator,class Recur>boost::optional<expression_tree<IIterator>> parse(IIterator first, IIterator last, Recur const&)const
{
auto constexpr zero = detail::getnum<typename std::iterator_traits<IIterator>::value_type>(0);
auto constexpr nine = detail::getnum<typename std::iterator_traits<IIterator>::value_type>(9);
auto c = *first;
if (c<zero || c>nine)
return boost::none;
auto ite = std::next(first);
while (ite != last)
{
auto c = *ite;
if (c<zero || c>nine)
break;
++ite;
}
return expression_tree<IIterator>
{
typeid(number_), first, ite, std::vector<expression_tree<IIterator>>()
};
}
template<class T>std::enable_if_t<std::is_integral<T>::value, action_<number_, detail::int_assign<T>>> operator[](T& val)const
{
return action_<number_, detail::int_assign<T>>{number_{}, detail::int_assign<T>{val}};
}
template<class Action>std::enable_if_t<!std::is_integral<Action>::value, action_<number_, Action>> operator[](Action action)const
{
return action_<number_, Action>{ number_{}, action };
}
};
template<std::size_t I,class T>struct string_
{
static constexpr bool left_recursion = false;
T const* str;
template<class IIterator, class Recur>
auto parse(
IIterator first,
IIterator last,
Recur const&,
std::enable_if_t<std::is_same<T,typename std::iterator_traits<IIterator>::value_type>::value>* =nullptr)const
->boost::optional<expression_tree<IIterator>>
{
if (std::distance(first, last) < static_cast<int>(I))
{
return boost::none;
}
auto ite = first;
for (std::size_t i{};i < I;++i, ++ite)
{
if (*ite != str[i])
return boost::none;
}
return expression_tree<IIterator>
{
typeid(*this), first, ite, std::vector<expression_tree<IIterator>>()
};
}
template<class Action>action_<string_<I, T>, Action> operator[](Action action)const
{
return action_<string_<I, T>, Action>{ *this, action };
}
};
template<class Conditional, std::size_t I>struct conditional_
{
Conditional cond;
static constexpr bool left_recursion = false;
template<class IIterator,class Recur>
boost::optional<expression_tree<IIterator>> parse(
IIterator first,
IIterator last,
Recur const&)const
{
auto ite = first;
if (std::distance(first, last) < static_cast<int>(I))
return boost::none;
for (std::size_t i{};i < I;++i, ++ite)
{
if (!cond(*ite))
return boost::none;
}
while (ite != last)
{
if (!cond(*ite))
break;
++ite;
}
return expression_tree<IIterator>
{
typeid(*this),first,ite, std::vector<expression_tree<IIterator>>()
};
}
template<class Action>auto operator[](Action action)const
{
return action_<conditional_, Action>{*this, action};
}
};
template<class T>struct dynamic_string_
{
static constexpr bool left_recursion = false;
std::basic_string<T> bst;
template<class IIterator,class Recur>
boost::optional<expression_tree<IIterator>> parse(
IIterator first,
IIterator last,
Recur const&)const
{
if (std::distance(first, last) < static_cast<int>(bst.size()))
return boost::none;
auto ite = first;
for (std::size_t i{};i < bst.size();++i, ++ite)
{
if (bst[i] != *ite)
return boost::none;
}
return expression_tree<IIterator>
{
typeid(*this), first, ite, std::vector<expression_tree<IIterator>>()
};
}
template<class Action>auto operator[](Action action)const
{
return action_<dynamic_string_, Action>{*this, action};
}
};
template<class Conditional>struct single_
{
Conditional cond;
static constexpr bool left_recursion = false;
template<class IIterator,class Recur>
boost::optional<expression_tree<IIterator>> parse(
IIterator first,
IIterator last,
Recur const&)const
{
if (first != last&&cond(*first))
{
return expression_tree<IIterator>
{
typeid(*this), first, std::next(first), std::vector<expression_tree<IIterator>>()
};
}
return boost::none;
}
template<class Action>auto operator[](Action action)const
{
return action_<single_, Action>{*this, action};
}
};
template<class Expr>struct loop_
{
Expr expr;
static constexpr bool left_recursion = Expr::left_recursion;
template<class IIterator,class Recur>
boost::optional<expression_tree<IIterator>> parse(
IIterator first,
IIterator last,
Recur const& recur)const
{
std::vector<expression_tree<IIterator>> vec;
auto ite = first;
while (ite != last)
{
auto p = expr.parse(ite, last, recur);
if (!p)
break;
vec.emplace_back(*p);
ite = p->last;
}
return expression_tree<IIterator>
{
typeid(*this), first, ite, std::move(vec)
};
}
template<class Action>auto operator[](Action const& action)const
{
return action_<loop_<Expr>, Action>{*this, action};
}
};
template<class Expr>struct oneloop_
{
Expr expr;
static constexpr bool left_recursion = Expr::left_recursion;
template<class IIterator, class Recur>
boost::optional<expression_tree<IIterator>> parse(
IIterator first,
IIterator last,
Recur const& recur)const
{
std::vector<expression_tree<IIterator>> vec;
auto ite = first;
while (ite != last)
{
auto p = expr.parse(ite, last, recur);
if (!p)
break;
vec.emplace_back(*p);
ite = p->last;
}
if (vec.size() == 0)
return boost::none;
return expression_tree<IIterator>
{
typeid(*this), first, ite, std::move(vec)
};
}
template<class Action>auto operator[](Action const& action)const
{
return action_<oneloop_<Expr>, Action>{*this, action};
}
};
template<class... Ts>struct continue_
{
typedef typename std::tuple_element<0, std::tuple<Ts...>>::type type;
static constexpr bool left_recursion = type::left_recursion;
std::tuple<Ts...> exprs;
template<class IIterator, class Recur, std::size_t... Is>
boost::optional<expression_tree<IIterator>>parse(
IIterator first,
IIterator last,
Recur const& recur,
std::index_sequence<Is...>)const
{
typedef std::function<boost::optional<expression_tree<IIterator>>(
IIterator,
IIterator,
Recur const&)> function;
std::vector<function> funcs =
{
function([&](auto first,auto last,auto const& recur)
{
return std::get<Is>(this->exprs).parse(first,last,recur);
})...
};
auto ite = first;
std::vector<expression_tree<IIterator>> vec;
for (auto const& func : funcs)
{
auto v = func(ite, last, recur);
if (!v)
return boost::none;
ite = v->last;
vec.emplace_back(std::move(*v));
}
return expression_tree<IIterator>
{
typeid(*this), first, ite, std::move(vec)
};
}
template<class IIterator, class Recur>
boost::optional<expression_tree<IIterator>>parse(
IIterator first,
IIterator last,
Recur const& recur)const
{
return parse(first, last, recur, std::make_index_sequence<sizeof...(Ts)>());
}
};
template<class First, class Second>struct select_
{
First first_;
Second second_;
static constexpr bool left_recursion = First::left_recursion || Second::left_recursion;
template<class IIterator,class Recur>
boost::optional<expression_tree<IIterator>> parse(
IIterator first,
IIterator last,
Recur const& recur)const
{
if (auto p = first_.parse(first, last, recur))
{
return p;
}
return second_.parse(first, last, recur);
}
template<class Action>auto operator[](Action action)const
{
return action_<select_<First, Second>, Action>{*this, action};
}
};
template<class Expr>struct optional_
{
Expr expr;
static constexpr bool left_recursion = true;
template<class IIterator, class Recur>
boost::optional<expression_tree<IIterator>>parse(
IIterator first,
IIterator last,
Recur const& recur)const
{
if (auto p = expr.parse(first, last, recur))
{
return p;
}
return expression_tree<IIterator>
{
typeid(nullptr), first, first, std::vector<expression_tree<IIterator>>()
};
}
template<class Action>auto operator[](Action action)const
{
return action_<optional_, Action>{*this, action};
}
};
template<class Pred, class Expr>struct and_predicate_
{
Pred pred;
Expr expr;
static constexpr bool left_recursion = Pred::left_recursion || Expr::left_recursion;
template<class IIterator,class Recur>
boost::optional<expression_tree<IIterator>> parse(
IIterator first,
IIterator last,
Recur const& recur)const
{
if (auto p = pred.parse(first, last, recur))
{
return expr.parse(first, last, recur);
}
return boost::none;
}
template<class Action>auto operator[](Action action)const
{
return action_<and_predicate_, Action>{*this, action};
}
};
template<class Pred, class Expr>struct not_predicate_
{
Pred pred;
Expr expr;
static constexpr bool left_recursion = Pred::left_recursion || Expr::left_recursion;
template<class IIterator, class Recur>
boost::optional<expression_tree<IIterator>> parse(
IIterator first,
IIterator last,
Recur const& recur)const
{
if (auto p = pred.parse(first, last, recur))
{
return boost::none;
}
return expr.parse(first, last, recur);
}
template<class Action>auto operator[](Action action)const
{
return action_<not_predicate_, Action>{*this, action};
}
};
template<class Expr>loop_<Expr> operator*(Expr expr)
{
return loop_<Expr>{expr};
}
template<class T, std::size_t I, class... Ts>auto operator+(continue_<Ts...>lhs, const T(&ar)[I])
{
return lhs + string_<I - 1, T>{ar};
}
template<class T, std::size_t I, class... Ts>auto operator+(const T(&ar)[I], continue_<Ts...> rhs)
{
return string_<I - 1, T>{ar}+rhs;
}
template<class T, class... Ts>auto operator+(std::basic_string<T> lhs, continue_<Ts...>rhs)
{
return dynamic_string_<T>(std::move(lhs)) + rhs;
}
template<class T, class... Ts>auto operator+(continue_<Ts...>lhs, std::basic_string<T>rhs)
{
return lhs + dynamic_string_<T>(std::move(rhs));
}
template<class Lhs, class T, std::size_t I>auto operator+(Lhs lhs, const T(&ar)[I])
{
return lhs + string_<I - 1, T>{ar};
}
template<class Rhs, class T, std::size_t I>auto operator+(const T(&ar)[I], Rhs rhs)
{
return string_<I - 1, T>{ar} +rhs;
}
template<class Lhs, class T>auto operator+(Lhs lhs, std::basic_string<T> rhs)
{
return lhs + dynamic_string_<T>{std::move(rhs)};
}
template<class Rhs, class T>auto operator+(std::basic_string<T> lhs, Rhs rhs)
{
return dynamic_string_<T>{std::move(lhs)}+rhs;
}
template<class Lhs, class... Ts>auto operator+(Lhs lhs, continue_<Ts...> rhs)
->continue_<Lhs, Ts...>
{
return continue_<Lhs, Ts...>{std::tuple_cat(std::make_tuple(lhs), rhs.exprs)};
}
template<class Rhs, class... Ts>auto operator+(continue_<Ts...> lhs, Rhs rhs)
->continue_<Ts..., Rhs>
{
return continue_<Ts..., Rhs>{std::tuple_cat(lhs.exprs, std::make_tuple(rhs))};
}
template<class Lhs, class Rhs> continue_<Lhs, Rhs> operator+(Lhs lhs, Rhs rhs)
{
return continue_<Lhs, Rhs>{std::make_tuple(lhs, rhs)};
}
template<class Expr>oneloop_<Expr> operator+(Expr expr)
{
return oneloop_<Expr>{expr};
}
template<class First, class Second>select_<First, Second> operator/(First first, Second second)
{
return select_<First, Second>{first, second};
}
template<class Expr>optional_<Expr> operator-(Expr expr)
{
return optional_<Expr>{expr};
}
}
const expression::number_ number;
const expression::recursion_tag self;
template<class Expr>auto recursion(Expr expr)
->expression::self_recursion<Expr>
{
static_assert(!Expr::left_recursion, "this expression has left-recursion");
return expression::self_recursion<Expr>{expr};
}
template<class T, std::size_t I>auto string(T const(&ar)[I])
->expression::string_<I - 1, T>
{
return expression::string_<I - 1, T>{ar};
}
template<std::size_t I, class Cond>auto conditional(Cond cond)
->expression::conditional_<Cond, I>
{
return expression::conditional_<Cond, I>{cond};
}
template<class Conditional>auto single(Conditional cond)
->expression::single_<Conditional>
{
return expression::single_<Conditional>{cond};
}
template<class Expr, class IRange>auto parse(Expr const& expr, IRange const& range)
{
return expr.parse(std::begin(range), std::end(range), expr);
}
template<std::size_t Index, class Expr>auto index(Expr expr)
->expression::indexed_expr_<Expr, Index>
{
return expression::indexed_expr_<Expr, Index>{expr};
}
template<class Pred, class Expr>auto andpred(Pred pred, Expr expr)
->expression::and_predicate_<Pred, Expr>
{
return expression::and_predicate_<Pred, Expr>{pred, expr};
}
template<class Pred, class Expr>auto notpred(Pred pred, Expr expr)
->expression::not_predicate_<Pred, Expr>
{
return expression::not_predicate_<Pred, Expr>{pred, expr};
}
template<class T>auto string(std::basic_string<T>&& bst)
->expression::dynamic_string_<T>
{
if (bst.size() == 0)
throw std::invalid_argument("It is necessary that std::basic_string<T>::size() > 0");
return expression::dynamic_string_<T>{ std::move(bst) };
}
template<class T>auto string(std::basic_string<T> const& bst)
->expression::dynamic_string_<T>
{
if (bst.size() == 0)
throw std::invalid_argument("It is necessary that std::basic_string<T>::size() > 0");
return expression::dynamic_string_<T>{bst};
}
template<class Expr>auto ignore(Expr expr)
->expression::ignore_<Expr>
{
return expression::ignore_<Expr>{expr};
}
template<class Expr>auto remove_action(Expr const& expr);
template<class Expr, class Action>auto remove_action(expression::action_<Expr, Action>const& expr)
{
return remove_action(expr.expr);
}
template<class Expr>auto remove_action(expression::loop_<Expr>const& expr)
{
return *remove_action(expr.expr);
}
template<class Expr>auto remove_action(expression::oneloop_<Expr>const& expr)
{
return +remove_action(expr.expr);
}
template<class Lhs, class Rhs>auto remove_action(expression::continue_<Lhs, Rhs>const& expr)
{
return remove_action(expr.lhs) + remove_action(expr.rhs);
}
template<class First, class Second>auto remove_action(expression::select_<First, Second>const& expr)
{
return remove_action(expr.first_) / remove_action(expr.second_);
}
template<class Expr>auto remove_action(expression::optional_<Expr>const& expr)
{
return -remove_action(expr.expr);
}
template<class Pred, class Expr>auto remove_action(expression::and_predicate_<Pred, Expr>const& expr)
{
return andpred(expr.pred, remove_action(expr.expr));
}
template<class Pred, class Expr>auto remove_action(expression::not_predicate_<Pred, Expr>const& expr)
{
return notpred(expr.pred, remove_action(expr.expr));
}
template<class Expr, std::size_t I>auto remove_action(expression::indexed_expr_<Expr, I>const& expr)
{
return index<I>(remove_action(expr.expr));
}
template<class Expr>auto remove_action(expression::self_recursion<Expr> const& expr)
{
return recursion(remove_action(expr.expr));
}
template<class Expr>auto remove_action(expression::recursion_tag)
{
return expression::recursion_tag{};
}
template<class Expr>auto remove_action(Expr const& expr)
{
return expr;
}
}
#include<iostream>
#include<string>
#include"regexpr.hpp"
template<class T>auto& println(T const& t)
{
return std::cout << " " << t << std::endl;
}
int main()
{
using namespace regexpr;
std::cout << std::boolalpha << std::endl;
auto is_small = [](auto c) {return 'a' <= c&&c <= 'z';};
{
std::cout << "case 1" << std::endl;
auto const expr = number;
println(static_cast<bool>(parse(expr, "123")));
println(static_cast<bool>(parse(expr, "test")));
}
{
std::cout << "case 2" << std::endl;
auto const expr = string("test");
println(static_cast<bool>(parse(expr, "123")));
println(static_cast<bool>(parse(expr, "test")));
}
{
std::cout << "case 3" << std::endl;
auto const expr = conditional<3>(is_small);
println(static_cast<bool>(parse(expr, "Test")));
println(static_cast<bool>(parse(expr, "test")));
println(static_cast<bool>(parse(expr, "ng")));
}
{
std::cout << "case 4" << std::endl;
auto const expr = *(string("a"));
println(static_cast<bool>(parse(expr, "a")));
println(static_cast<bool>(parse(expr, "aaa")));
println(static_cast<bool>(parse(expr, "ba")));
}
{
std::cout << "case 5" << std::endl;
auto const expr = +(string("a"));
println(static_cast<bool>(parse(expr, "a")));
println(static_cast<bool>(parse(expr, "aaa")));
println(static_cast<bool>(parse(expr, "ba")));
}
{
std::cout << "case 6" << std::endl;
auto const expr = "case:" + number;
println(static_cast<bool>(parse(expr, "case:1")));
println(static_cast<bool>(parse(expr, "case:v")));
println(static_cast<bool>(parse(expr, "kase:1")));
}
{
std::cout << "case 7" << std::endl;
auto const expr = string("test") / string("hoge");
println(static_cast<bool>(parse(expr, "test")));
println(static_cast<bool>(parse(expr, "hoge")));
println(static_cast<bool>(parse(expr, "hage")));
}
{
std::cout << "case 8" << std::endl;
auto const expr = (-string("//")) + conditional<1>(is_small);
println(static_cast<bool>(parse(expr, "//test")));
println(static_cast<bool>(parse(expr, "/hoge")));
println(static_cast<bool>(parse(expr, "hage")));
}
{
std::cout << "case 9" << std::endl;
auto const expr = andpred(number, number + "yen") / conditional<1>(is_small);
println(static_cast<bool>(parse(expr, "100yen")));
println(static_cast<bool>(parse(expr, "100")));
println(static_cast<bool>(parse(expr, "test")));
}
{
std::cout << "case 10" << std::endl;
auto const expr = notpred(number, conditional<1>(is_small)) / number;
println(static_cast<bool>(parse(expr, "Test")));
println(static_cast<bool>(parse(expr, "100")));
println(static_cast<bool>(parse(expr, "test")));
}
{
std::cout << "case 11" << std::endl;
auto const expr = recursion(*("(" + self + ")")) + "\0";
println(static_cast<bool>(parse(expr, "()")));
println(static_cast<bool>(parse(expr, "(()(()(())))")));
println(static_cast<bool>(parse(expr, "(()(()(()))")));
}
{
std::cout << "case 12" << std::endl;
auto print= [](auto first, auto second)
{
std::cout << " " << std::string(first, second) << std::endl;
};
auto const expr = recursion((conditional<1>(is_small) / ("(" + self + ")")) + -self)[print];
println(static_cast<bool>(parse(expr, "(test)")));
println(static_cast<bool>(parse(expr, "(sum(a)(b))")));
println(static_cast<bool>(parse(expr, "(sum(x(y)))")));
println(static_cast<bool>(parse(expr, "(")));
}
{
std::cout << "case 13" << std::endl;
int val;
auto const expr = number[val];
println(static_cast<bool>(parse(expr, "1234")));
println(val);
println(static_cast<bool>(parse(expr, "5678")));
println(val);
println(static_cast<bool>(parse(expr, "test")));
println(val);
}
{
std::cout << "case 14" << std::endl;
auto const expr = number;
println(parse(expr, "123")->type.name());
println(parse(index<0>(expr), "123")->type.name());
}
{
std::cout << "case 15" << std::endl;
auto print = [](int v)
{
std::cout << " " << v << std::endl;
};
auto const expr = recursion((number[integer_action<int>(print)] / ("(" + self + ")") + -self)) + "\0";
println(static_cast<bool>(parse(andpred(remove_action(expr), expr), "123")));
println(static_cast<bool>(parse(andpred(remove_action(expr), expr), "123(456)")));
println(static_cast<bool>(parse(andpred(remove_action(expr), expr), "123((456)789(012))")));
println(static_cast<bool>(parse(andpred(remove_action(expr), expr), "123((456)789((012))")));
}
}
case 1
true
false
case 2
false
true
case 3
false
true
false
case 4
true
true
true
case 5
true
true
false
case 6
false
false
false
case 7
true
true
false
case 8
true
false
true
case 9
true
false
true
case 10
false
true
true
case 11
false
false
false
case 12
false
false
false
false
case 13
true
1234
true
5678
false
5678
case 14
struct regexpr::expression::number_
struct std::integer_sequence<unsigned __int64,0>
case 15
false
false
false
false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment