Created
November 14, 2016 06:27
-
-
Save plasma-effect/44f30344f28c0b0131c7887402ebb02f to your computer and use it in GitHub Desktop.
regexpr2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#ifndef PLASMA_REGEXPR_ | |
#define PLASMA_REGEXPR_ | |
#include<string> | |
#include<array> | |
#include<vector> | |
#include<memory> | |
#include<typeindex> | |
#include<boost/utility/string_view.hpp> | |
#include<boost/optional.hpp> | |
#include<boost/lexical_cast.hpp> | |
namespace regexpr | |
{ | |
template<class CharT>struct expression_tree | |
{ | |
boost::basic_string_view<CharT> result; | |
std::vector<expression_tree<CharT>> child; | |
std::type_index index; | |
expression_tree( | |
boost::basic_string_view<CharT>&& r, | |
std::vector<expression_tree<CharT>>&& c, | |
std::type_index i) : | |
result(std::move(r)), | |
child(std::move(c)), | |
index(i) | |
{ | |
} | |
}; | |
template<class CharT>class conpact_tree | |
{ | |
std::shared_ptr<std::basic_string<CharT>> str_; | |
boost::optional<expression_tree<CharT>> tree_; | |
template<class Expr, class CharT2>friend boost::optional<conpact_tree<CharT2>>parse(Expr const& expr, std::basic_string<CharT2>&& str); | |
conpact_tree(std::basic_string<CharT>&& s) : | |
str_(std::make_shared<std::basic_string<CharT>>(std::move(s))), | |
child{ *this }, | |
result{ *this }, | |
index{ *this } {} | |
void assign(expression_tree<CharT>&& t) | |
{ | |
tree_.emplace(std::move(t)); | |
} | |
public: | |
struct child_container | |
{ | |
conpact_tree<CharT>& tree; | |
expression_tree<CharT>const& operator[](std::size_t index)const | |
{ | |
return tree.tree_->child[index]; | |
} | |
auto begin()const | |
{ | |
return tree.tree_->child.begin(); | |
} | |
auto end()const | |
{ | |
return tree.tree_->child.end(); | |
} | |
}; | |
child_container child; | |
struct result_container | |
{ | |
conpact_tree<CharT>& tree; | |
operator boost::basic_string_view<CharT>const&()const | |
{ | |
return tree.tree_->result; | |
} | |
}; | |
result_container result; | |
struct index_container | |
{ | |
conpact_tree<CharT>& tree; | |
operator std::type_index()const | |
{ | |
return tree.tree_->index; | |
} | |
}; | |
index_container index; | |
}; | |
namespace detail | |
{ | |
template<class CharT>expression_tree<CharT> make_expression( | |
boost::basic_string_view<CharT>&& result, | |
std::vector<expression_tree<CharT>>&& child, | |
std::type_index i) | |
{ | |
return expression_tree<CharT>(std::move(result), std::move(child), std::move(i)); | |
} | |
} | |
namespace types | |
{ | |
struct recursion_point | |
{ | |
template<class CharT>struct inside | |
{ | |
static std::function<boost::optional<expression_tree<CharT>>(boost::basic_string_view<CharT>)> point; | |
}; | |
template<class CharT>static void set(std::function<boost::optional<expression_tree<CharT>>(boost::basic_string_view<CharT>)> func) | |
{ | |
inside<CharT>::point = func; | |
} | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
return inside<CharT>::point(view); | |
} | |
}; | |
template<class Expr>struct recursion_cover | |
{ | |
Expr expr; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
auto point = recursion_point::inside<CharT>::point; | |
recursion_point::set(std::function<boost::optional<expression_tree<CharT>>(boost::basic_string_view<CharT>)>([&](auto view) {return expr.parse(view);})); | |
auto p = expr.parse(view); | |
recursion_point::set(point); | |
return p; | |
} | |
}; | |
template<class CharT>std::function<boost::optional<expression_tree<CharT>>(boost::basic_string_view<CharT>)> recursion_point::inside<CharT>::point; | |
template<class Expr, class Action>struct action_ | |
{ | |
typedef std::remove_const_t<std::remove_reference_t<Expr>> Exprs; | |
Exprs expr; | |
Action action; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
if (auto p = expr.parse(view)) | |
{ | |
action(p->result); | |
return p; | |
} | |
return boost::none; | |
} | |
}; | |
template<class Expr>struct skip_ | |
{ | |
Expr expr; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
return expr.parse(view); | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
}; | |
template<class Lhs, class Rhs>struct continue_ | |
{ | |
Lhs lhs; | |
Rhs rhs; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
if (auto opt = parse(view, boost::none)) | |
{ | |
auto size = opt->second; | |
return expression_tree<CharT>(view.substr(0, size), std::move(opt->first), typeid(*this)); | |
} | |
return boost::none; | |
} | |
template<class CharT>boost::optional<std::pair<std::vector<expression_tree<CharT>>,std::size_t>> parse(boost::basic_string_view<CharT>view, boost::none_t)const | |
{ | |
std::vector<expression_tree<CharT>> child; | |
std::size_t size{}; | |
if (auto p = lhs.parse(view)) | |
{ | |
if (auto q = rhs.parse(view.substr(p->result.size()))) | |
{ | |
size = p->result.size() + q->result.size(); | |
child.emplace_back(std::move(*p)); | |
child.emplace_back(std::move(*q)); | |
return std::make_pair(std::move(child), size); | |
} | |
} | |
return boost::none; | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
}; | |
template<class Lhs, class Rhs>struct continue_<skip_<Lhs>, Rhs> | |
{ | |
skip_<Lhs> lhs; | |
Rhs rhs; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
if (auto opt = parse(view, boost::none)) | |
{ | |
auto size = opt->second; | |
return expression_tree<CharT>(view.substr(0, size), std::move(opt->first), typeid(*this)); | |
} | |
return boost::none; | |
} | |
template<class CharT>boost::optional<std::pair<std::vector<expression_tree<CharT>>, std::size_t>> parse(boost::basic_string_view<CharT>view, boost::none_t)const | |
{ | |
std::vector<expression_tree<CharT>> child; | |
std::size_t size{}; | |
if (auto p = lhs.parse(view)) | |
{ | |
if (auto q = rhs.parse(view.substr(p->result.size()))) | |
{ | |
size = p->result.size() + q->result.size(); | |
child.emplace_back(std::move(*q)); | |
return std::make_pair(std::move(child), size); | |
} | |
} | |
return boost::none; | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
}; | |
template<class Lhs, class Rhs>struct continue_<Lhs, skip_<Rhs>> | |
{ | |
Lhs lhs; | |
skip_<Rhs> rhs; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
if (auto opt = parse(view, boost::none)) | |
{ | |
auto size = opt->second; | |
return expression_tree<CharT>(view.substr(0, size), std::move(opt->first), typeid(*this)); | |
} | |
return boost::none; | |
} | |
template<class CharT>boost::optional<std::pair<std::vector<expression_tree<CharT>>, std::size_t>> parse(boost::basic_string_view<CharT>view, boost::none_t)const | |
{ | |
std::vector<expression_tree<CharT>> child; | |
std::size_t size{}; | |
if (auto p = lhs.parse(view)) | |
{ | |
if (auto q = rhs.parse(view.substr(p->result.size()))) | |
{ | |
size = p->result.size() + q->result.size(); | |
child.emplace_back(std::move(*p)); | |
return std::make_pair(std::move(child), size); | |
} | |
} | |
return boost::none; | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
}; | |
template<class Lhs, class Rhs>struct continue_<skip_<Lhs>, skip_<Rhs>> | |
{ | |
skip_<Lhs> lhs; | |
skip_<Rhs> rhs; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
if (auto opt = parse(view, boost::none)) | |
{ | |
auto size = opt->second; | |
return expression_tree<CharT>(view.substr(0, size), std::move(opt->first), typeid(*this)); | |
} | |
return boost::none; | |
} | |
template<class CharT>boost::optional<std::pair<std::vector<expression_tree<CharT>>, std::size_t>> parse(boost::basic_string_view<CharT>view, boost::none_t)const | |
{ | |
std::vector<expression_tree<CharT>> child; | |
std::size_t size{}; | |
if (auto p = lhs.parse(view)) | |
{ | |
if (auto q = rhs.parse(view.substr(p->result.size()))) | |
{ | |
size = p->result.size() + q->result.size(); | |
return std::make_pair(std::move(child), size); | |
} | |
} | |
return boost::none; | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
}; | |
template<class L0, class L1, class Rhs>struct continue_<continue_<L0, L1>, Rhs> | |
{ | |
continue_<L0, L1> lhs; | |
Rhs rhs; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
if (auto opt = parse(view, boost::none)) | |
{ | |
auto size = opt->second; | |
return expression_tree<CharT>(view.substr(0, size), std::move(opt->first), typeid(*this)); | |
} | |
return boost::none; | |
} | |
template<class CharT>boost::optional<std::pair<std::vector<expression_tree<CharT>>, std::size_t>> parse(boost::basic_string_view<CharT>view, boost::none_t)const | |
{ | |
if (auto p = lhs.parse(view, boost::none)) | |
{ | |
if (auto q = rhs.parse(view.substr(p->second))) | |
{ | |
p->second += q->result.size(); | |
p->first.emplace_back(std::move(*q)); | |
return p; | |
} | |
} | |
return boost::none; | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
}; | |
template<class L0, class L1, class Rhs>struct continue_<continue_<L0, L1>, skip_<Rhs>> | |
{ | |
continue_<L0, L1> lhs; | |
skip_<Rhs> rhs; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
if (auto opt = parse(view, boost::none)) | |
{ | |
auto size = opt->second; | |
return expression_tree<CharT>(view.substr(0, size), std::move(opt->first), typeid(*this)); | |
} | |
return boost::none; | |
} | |
template<class CharT>boost::optional<std::pair<std::vector<expression_tree<CharT>>, std::size_t>> parse(boost::basic_string_view<CharT>view, boost::none_t)const | |
{ | |
if (auto p = lhs.parse(view, boost::none)) | |
{ | |
if (auto q = rhs.parse(view.substr(p->second))) | |
{ | |
p->second += q->result.size(); | |
return p; | |
} | |
} | |
return boost::none; | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
}; | |
template<class Expr>struct loop_ | |
{ | |
Expr expr; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
std::vector<expression_tree<CharT>> child; | |
std::size_t size{}; | |
while (auto p = expr.parse(view.substr(size))) | |
{ | |
size += p->result.size(); | |
child.emplace_back(std::move(*p)); | |
} | |
return detail::make_expression(view.substr(0, size), std::move(child), typeid(*this)); | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
}; | |
template<class Expr>struct oneloop_ | |
{ | |
Expr expr; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
std::vector<expression_tree<CharT>> child; | |
std::size_t size{}; | |
if (auto p = expr.parse(view)) | |
{ | |
size += p->result.size(); | |
child.emplace_back(std::move(*p)); | |
} | |
else | |
{ | |
return boost::none; | |
} | |
while (auto p = expr.parse(view.substr(size))) | |
{ | |
size += p->result.size(); | |
child.emplace_back(std::move(*p)); | |
} | |
return detail::make_expression(view.substr(0, size), std::move(child), typeid(*this)); | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
}; | |
template<class Expr, std::size_t Min, std::size_t Max>struct countloop_ | |
{ | |
Expr expr; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
static_assert(Min <= Max, R"(regexpr::count<Min, Max> requires "Min <= Max")"); | |
std::vector<expression_tree<CharT>> child; | |
std::size_t size{}; | |
for (std::size_t i{};i < Min;++i) | |
{ | |
if (auto p = expr.parse(view.substr(size))) | |
{ | |
size += p->result.size(); | |
child.emplace_back(std::move(*p)); | |
} | |
else | |
{ | |
return boost::none; | |
} | |
} | |
for (std::size_t i = Min;i < Max;++i) | |
{ | |
if (auto p = expr.parse(view.substr(size))) | |
{ | |
size += p->result.size(); | |
child.emplace_back(std::move(*p)); | |
} | |
else | |
{ | |
break; | |
} | |
} | |
return detail::make_expression(view.substr(0, size), std::move(child), typeid(*this)); | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
}; | |
template<class Expr, std::size_t Min>struct countloop_<Expr, Min, 0> | |
{ | |
Expr expr; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
std::vector<expression_tree<CharT>> child; | |
std::size_t size{}; | |
for (std::size_t i{};i < Min;++i) | |
{ | |
if (auto p = expr.parse(view.substr(size))) | |
{ | |
size += p->result.size(); | |
child.emplace_back(std::move(*p)); | |
} | |
else | |
{ | |
return boost::none; | |
} | |
} | |
while (auto p = expr.parse(view.substr(size))) | |
{ | |
size += p->result.size(); | |
child.emplace_back(std::move(*p)); | |
} | |
return detail::make_expression(view.substr(0, size), std::move(child), typeid(*this)); | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
}; | |
template<class Expr, std::size_t Max>struct countloop_<Expr, 0, Max> | |
{ | |
Expr expr; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
std::vector<expression_tree<CharT>> child; | |
std::size_t size{}; | |
for (std::size_t i{};i < Max;++i) | |
{ | |
if (auto p = expr.parse(view.substr(size))) | |
{ | |
size += p->result.size(); | |
child.emplace_back(std::move(*p)); | |
} | |
else | |
{ | |
break; | |
} | |
} | |
return detail::make_expression(view.substr(0, size), std::move(child), typeid(*this)); | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
}; | |
template<class Expr>struct countloop_<Expr, 0, 0> | |
{ | |
Expr expr; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
static_assert(sizeof(expr) != sizeof(expr), R"(regexpr::count<Min, Max> requires "Min != 0 or Max != 0")"); | |
throw boost::none; | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
}; | |
template<class Expr>struct optional_ | |
{ | |
Expr expr; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
if (auto p = expr.parse(view)) | |
{ | |
return p; | |
} | |
return detail::make_expression(view.substr(0, 0), {}, typeid(boost::none)); | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
}; | |
template<class Lhs, class Rhs>struct select_ | |
{ | |
Lhs lhs; | |
Rhs rhs; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
if (auto p = lhs.parse(view)) | |
{ | |
return p; | |
} | |
return rhs.parse(view); | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
}; | |
template<std::size_t Index, class Expr>struct indexed_ | |
{ | |
Expr expr; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
if (auto p = expr.parse(view)) | |
{ | |
p->index = typeid(std::integral_constant<std::size_t, Index>); | |
return p; | |
} | |
return boost::none; | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
}; | |
template<class CharT>struct string_ | |
{ | |
std::basic_string<CharT> ar_; | |
boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
const auto I = ar_.size(); | |
if (I > view.size()) | |
{ | |
return boost::none; | |
} | |
for (std::size_t i{};i < I;++i) | |
{ | |
if (ar_[i] != view[i]) | |
{ | |
return boost::none; | |
} | |
} | |
return expression_tree<CharT>(view.substr(0, I), {}, typeid(*this)); | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
}; | |
struct number_ | |
{ | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
auto size = view.size(); | |
if (size == 0 || !is_number_atomic(view[0])) | |
{ | |
return boost::none; | |
} | |
for (std::size_t i{};i < size;++i) | |
{ | |
if (!is_number_atomic(view[i])) | |
{ | |
return expression_tree<CharT>(view.substr(0, i), {}, typeid(*this)); | |
} | |
} | |
return expression_tree<CharT>(view.substr(0), {}, typeid(*this)); | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
template<class Integer>auto operator[](Integer& value)const | |
{ | |
return operator()([&value = value](auto view) {value = boost::lexical_cast<Integer>(view);}); | |
} | |
private: | |
static bool is_number_atomic(char c) | |
{ | |
return '0' <= c&&c <= '9'; | |
} | |
static bool is_number_atomic(wchar_t c) | |
{ | |
return L'0' <= c&&c <= L'9'; | |
} | |
static bool is_number_atomic(char16_t c) | |
{ | |
return u'0' <= c&&c <= u'9'; | |
} | |
static bool is_number_atomic(char32_t c) | |
{ | |
return U'0' <= c&&c <= U'9'; | |
} | |
}; | |
template<class Pred>struct single_ | |
{ | |
Pred pred; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
if (view.size() > 0 && pred(view[0])) | |
{ | |
return detail::make_expression(view.substr(0, 1), {}, typeid(*this)); | |
} | |
return boost::none; | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
}; | |
struct any_ | |
{ | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
if (view.size() > 0) | |
{ | |
return detail::make_expression(view.substr(0, 1), {}, typeid(*this)); | |
} | |
return boost::none; | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
}; | |
template<class Pred>struct predicate_ | |
{ | |
Pred pred; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
if (pred.parse(view)) | |
{ | |
return detail::make_expression(view.substr(0, 0), {}, typeid(*this)); | |
} | |
return boost::none; | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
}; | |
template<class Pred>struct not_predicate_ | |
{ | |
Pred pred; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
if (!pred.parse(view)) | |
{ | |
return detail::make_expression(view.substr(0, 0), {}, typeid(*this)); | |
} | |
return boost::none; | |
} | |
template<class Action>auto operator()(Action action)const | |
{ | |
return action_<decltype(*this), Action>{*this, action}; | |
} | |
}; | |
template<class Expr>struct user_defined_expression | |
{ | |
Expr expr; | |
template<class CharT>boost::optional<expression_tree<CharT>> parse(boost::basic_string_view<CharT> view)const | |
{ | |
return expr.parse(view); | |
} | |
}; | |
template<class Lhs, class Rhs>auto operator+(Lhs const& lhs, Rhs const& rhs) | |
->continue_<Lhs, Rhs> | |
{ | |
return continue_<Lhs, Rhs>{lhs, rhs}; | |
} | |
template<class Lhs, class Rhs>auto operator/(Lhs const& lhs, Rhs const& rhs) | |
->select_<Lhs, Rhs> | |
{ | |
return select_<Lhs, Rhs>{lhs, rhs}; | |
} | |
template<class Expr>auto operator+(Expr const& expr) | |
->oneloop_<Expr> | |
{ | |
return oneloop_<Expr>{expr}; | |
} | |
template<class Expr>auto operator*(Expr const& expr) | |
->loop_<Expr> | |
{ | |
return loop_<Expr>{expr}; | |
} | |
template<class Expr>auto operator-(Expr const& expr) | |
->optional_<Expr> | |
{ | |
return optional_<Expr>{expr}; | |
} | |
} | |
const auto self = types::recursion_point{}; | |
template<class Expr>types::recursion_cover<Expr> recursion(Expr const& expr) | |
{ | |
return types::recursion_cover<Expr>{expr}; | |
} | |
template<class Expr>types::skip_<Expr> skip(Expr const& expr) | |
{ | |
return types::skip_<Expr>{expr}; | |
} | |
template<std::size_t Min, std::size_t Max, class Expr>types::countloop_<Expr, Min, Max> count(Expr const& expr) | |
{ | |
return types::countloop_<Expr, Min, Max>{expr}; | |
} | |
template<std::size_t Index, class Expr>types::indexed_<Index, Expr> index(Expr const& expr) | |
{ | |
return types::indexed_<Index, Expr>{expr}; | |
} | |
template<class Pred>types::predicate_<Pred> pred(Pred const& pred) | |
{ | |
return types::predicate_<Pred>{pred}; | |
} | |
template<class Pred>types::not_predicate_<Pred> notpred(Pred const& pred) | |
{ | |
return types::not_predicate_<Pred>{pred}; | |
} | |
template<class CharT>types::string_<CharT> string(const CharT* ptr) | |
{ | |
return types::string_<CharT>{std::basic_string<CharT>(ptr)}; | |
} | |
template<class CharT>types::string_<CharT> string(std::basic_string<CharT>&& ptr) | |
{ | |
return types::string_<CharT>{std::move(ptr)}; | |
} | |
template<class CharT>types::string_<CharT> string(std::basic_string<CharT>const& ptr) | |
{ | |
return types::string_<CharT>{ptr}; | |
} | |
template<class Pred>types::single_<Pred> single(Pred const& pred) | |
{ | |
return types::single_<Pred>{pred}; | |
} | |
const auto number = types::number_{}; | |
const auto any = types::any_{}; | |
template<class Expr>types::user_defined_expression<Expr> user_define(Expr expr) | |
{ | |
return types::user_defined_expression<Expr>{std::move(expr)}; | |
} | |
template<class Expr, class CharT>auto parse(Expr const& expr, boost::basic_string_view<CharT>view) | |
->boost::optional<expression_tree<CharT>> | |
{ | |
types::recursion_point::set(std::function<boost::optional<expression_tree<CharT>>(boost::basic_string_view<CharT>)>([&](auto view) {return parse(expr, view);})); | |
return expr.parse(view); | |
} | |
template<class Expr, class CharT>auto parse(Expr const& expr, std::basic_string<CharT> const& str) | |
->boost::optional<expression_tree<CharT>> | |
{ | |
return parse(expr, boost::basic_string_view<CharT>(str)); | |
} | |
template<class Expr, class CharT>auto parse(Expr const& expr, std::basic_string<CharT>&& str) | |
->boost::optional<conpact_tree<CharT>> | |
{ | |
conpact_tree<CharT> ret(std::move(str)); | |
if (auto p = parse(expr, *ret.str_)) | |
{ | |
ret.assign(std::move(*p)); | |
return ret; | |
} | |
return boost::none; | |
} | |
} | |
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include"regexpr2.hpp" | |
#include<string> | |
#include<iostream> | |
#include<boost/lexical_cast.hpp> | |
using namespace regexpr; | |
int main() | |
{ | |
std::vector<std::string> vec; | |
std::cout << "演算子入力(noneで次へ)" << std::endl; | |
while (true) | |
{ | |
std::string str; | |
std::cin >> str; | |
if (str == "none") | |
{ | |
break; | |
} | |
vec.emplace_back(std::move(str)); | |
} | |
struct test | |
{ | |
std::reference_wrapper<std::vector<std::string>> vecref; | |
test(std::reference_wrapper<std::vector<std::string>> v) :vecref(v) | |
{ | |
} | |
boost::optional<expression_tree<char>> parse(boost::string_view view)const | |
{ | |
for (auto const& str : vecref.get()) | |
{ | |
if (view.size() < str.size()) | |
{ | |
continue; | |
} | |
if (view.substr(0, str.size()) == str) | |
{ | |
return detail::make_expression(view.substr(0, str.size()), {}, typeid(*this)); | |
} | |
} | |
return boost::none; | |
} | |
}; | |
auto ignore = skip(*string(" ")); | |
auto token = +single([](char c) {return ('0' <= c&&c <= '9') || ('a' <= c&&c <= 'z') || ('A' <= c&&c <= 'Z');}); | |
auto expr = | |
ignore + | |
index<0>(string("(") + self + string(")") + ignore + -(user_define(test(std::ref(vec))) + ignore + self)) / | |
index<1>(token + ignore + -(user_define(test(std::ref(vec))) + ignore + self)) + | |
ignore; | |
std::function<void(expression_tree<char>const&, int)> print = | |
[&](expression_tree<char>const& tree, int val) | |
{ | |
auto const& e = tree.child[0]; | |
if (e.index == typeid(std::integral_constant<std::size_t, 0>)) | |
{ | |
if (e.child[3].index == typeid(boost::none)) | |
{ | |
print(e.child[1], val); | |
} | |
else | |
{ | |
for (int i{};i < val;++i) | |
{ | |
std::cout << " "; | |
} | |
std::cout << e.child[3].child[0].result << std::endl; | |
print(e.child[1], val + 1); | |
print(e.child[3].child[1], val + 1); | |
} | |
} | |
else | |
{ | |
for (int i{};i < val;++i) | |
{ | |
std::cout << " "; | |
} | |
if (e.child[1].index == typeid(boost::none)) | |
{ | |
std::cout << e.child[0].result << std::endl; | |
} | |
else | |
{ | |
std::cout << e.child[1].child[0].result << std::endl; | |
for (int i{};i < val + 1;++i) | |
{ | |
std::cout << " "; | |
} | |
std::cout << e.child[0].result << std::endl; | |
print(e.child[1].child[1], val + 1); | |
} | |
} | |
}; | |
std::string str; | |
std::cout << "式を入力(endで終了)" << std::endl; | |
while (std::getline(std::cin, str)) | |
{ | |
if (str == "end") | |
{ | |
break; | |
} | |
if (auto p = parse(expr, str)) | |
{ | |
print(*p, 0); | |
} | |
else | |
{ | |
std::cout << " invalid expression" << std::endl; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment