Skip to content

Instantly share code, notes, and snippets.

@plasma-effect
Created November 14, 2016 06:27
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/44f30344f28c0b0131c7887402ebb02f to your computer and use it in GitHub Desktop.
Save plasma-effect/44f30344f28c0b0131c7887402ebb02f to your computer and use it in GitHub Desktop.
regexpr2
#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
#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