Skip to content

Instantly share code, notes, and snippets.

@plasma-effect
Last active June 30, 2022 02:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save plasma-effect/f5be7d5d0154ea9bc97bba57c5a7ad19 to your computer and use it in GitHub Desktop.
Save plasma-effect/f5be7d5d0154ea9bc97bba57c5a7ad19 to your computer and use it in GitHub Desktop.
parser定期

あとで書く

// Copyright plasma-effect 2017.
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
#pragma once
#include<vector>
#include<optional>
#include<tuple>
#include<utility>
#include<map>
#include<array>
#include<algorithm>
#include<memory>
#include<string>
namespace parsing_expression_light
{
namespace detail
{
template<class Type>struct type_tag
{
};
typedef ::std::size_t index_t;
enum class table_tag
{
range,
string,
sequence,
select,
loop,
lahead,
nlahead,
variable
};
struct table_next
{
table_tag tag;
index_t index;
bool operator==(table_next t)const
{
return tag == t.tag&&index == t.index;
}
};
template<class V>index_t exist(std::vector<V>const& vec, V const& val)
{
for (index_t i = 0; i < vec.size(); ++i)
{
if (vec[i] == val)
{
return i;
}
}
return vec.size();
}
}
template<class InputIterator, class VariableTag>class parsing_result
{
InputIterator first;
InputIterator last;
bool flag;
std::vector<parsing_result> childs;
std::optional<VariableTag> tag;
static parsing_result none;
public:
parsing_result(InputIterator fir, InputIterator las, std::vector<parsing_result>&& chil, std::optional<VariableTag> t):first(fir), last(las), flag(true), childs(std::move(chil)), tag(t)
{
}
parsing_result() = default;
parsing_result(parsing_result const&) = delete;
parsing_result& operator=(parsing_result const&) = delete;
parsing_result(parsing_result&&) = default;
parsing_result& operator=(parsing_result&&) = default;
~parsing_result() = default;
auto begin()const
{
return first;
}
auto end()const
{
return last;
}
operator bool()const
{
return flag;
}
std::size_t size()const
{
return childs.size();
}
auto const& operator[](std::size_t index)const
{
if (index < childs.size())
{
return childs[index];
}
else
{
return none;
}
}
auto const& get_tag()const
{
return tag;
}
void change_tag(VariableTag t)
{
tag = t;
}
};
template<class InputIterator, class VariableTag>parsing_result<InputIterator,VariableTag> parsing_result<InputIterator, VariableTag>::none;
namespace types
{
typedef detail::table_next table_next;
typedef detail::table_tag table_tag;
template<class CharT, class VariableTag>struct variable_t
{
typedef CharT value_type;
typedef detail::table_next table_next;
struct place_holder_t
{
virtual detail::table_next initialize(
std::vector<std::pair<value_type, value_type>>& range_table,
std::vector<std::basic_string<value_type>>& string_table,
std::vector<std::vector<table_next>>& sequence_table,
std::vector<std::vector<table_next>>& select_table,
std::vector<std::pair<table_next, std::pair<detail::index_t, detail::index_t>>>& loop_table,
std::vector<std::pair<bool, table_next>>& lahead_table,
std::vector<std::pair<table_next, VariableTag>>& variable_table)const = 0;
};
template<class T>struct type_eraser :place_holder_t
{
T val;
type_eraser(T const& v):val(v)
{
}
virtual detail::table_next initialize(
std::vector<std::pair<value_type, value_type>>& range_table,
std::vector<std::basic_string<value_type>>& string_table,
std::vector<std::vector<table_next>>& sequence_table,
std::vector<std::vector<table_next>>& select_table,
std::vector<std::pair<table_next, std::pair<detail::index_t, detail::index_t>>>& loop_table,
std::vector<std::pair<bool, table_next>>& lahead_table,
std::vector<std::pair<table_next, VariableTag>>& variable_table)const
{
return val.initialize(range_table, string_table, sequence_table, select_table, loop_table, lahead_table, variable_table);
}
};
VariableTag t;
std::shared_ptr<place_holder_t> place_holder;
variable_t(VariableTag tag):t(tag), place_holder()
{
}
template<class T>void operator=(T const& rhs)
{
place_holder = std::make_shared<type_eraser<T>>(rhs);
}
detail::table_next initialize(
std::vector<std::pair<value_type, value_type>>&,
std::vector<std::basic_string<value_type>>&,
std::vector<std::vector<table_next>>&,
std::vector<std::vector<table_next>>&,
std::vector<std::pair<table_next, std::pair<detail::index_t, detail::index_t>>>&,
std::vector<std::pair<bool, table_next>>&,
std::vector<std::pair<table_next, VariableTag>>& variable_table)const
{
for (detail::index_t i = 0; i < variable_table.size(); ++i)
{
if (variable_table[i].second == t)
{
return table_next{ detail::table_tag::variable,i };
}
}
variable_table.emplace_back(table_next{}, t);
return table_next{ detail::table_tag::variable,variable_table.size() - 1 };
}
void value_init(
std::vector<std::pair<value_type, value_type>>& range_table,
std::vector<std::basic_string<value_type>>& string_table,
std::vector<std::vector<table_next>>& sequence_table,
std::vector<std::vector<table_next>>& select_table,
std::vector<std::pair<table_next, std::pair<detail::index_t, detail::index_t>>>& loop_table,
std::vector<std::pair<bool, table_next>>& lahead_table,
std::vector<std::pair<table_next, VariableTag>>& variable_table)const
{
detail::index_t i;
for (i = 0; i < variable_table.size(); ++i)
{
if (variable_table[i].second == t)
{
break;
}
}
if (i == variable_table.size())
{
variable_table.emplace_back(table_next{}, t);
}
variable_table[i].first = place_holder->initialize(range_table, string_table, sequence_table, select_table, loop_table, lahead_table, variable_table);
}
};
template<class CharT>struct range_t
{
CharT min;
CharT max;
typedef CharT value_type;
template<class VariableTag>
detail::table_next initialize(
std::vector<std::pair<value_type, value_type>>& range_table,
std::vector<std::basic_string<value_type>>&,
std::vector<std::vector<table_next>>&,
std::vector<std::vector<table_next>>&,
std::vector<std::pair<table_next, std::pair<detail::index_t, detail::index_t>>>&,
std::vector<std::pair<bool, table_next>>&,
std::vector<std::pair<table_next, VariableTag>>&)const
{
auto i = detail::exist(range_table, std::make_pair(min, max));
if (i == range_table.size())
{
range_table.emplace_back(min, max);
}
return table_next{ table_tag::range,i };
}
};
template<class CharT>struct strings_t
{
std::basic_string<CharT> str;
typedef CharT value_type;
template<class VariableTag>
table_next initialize(
std::vector<std::pair<value_type, value_type>>&,
std::vector<std::basic_string<value_type>>& string_table,
std::vector<std::vector<table_next>>&,
std::vector<std::vector<table_next>>&,
std::vector<std::pair<table_next, std::pair<detail::index_t, detail::index_t>>>&,
std::vector<std::pair<bool, table_next>>&,
std::vector<std::pair<table_next, VariableTag>>&)const
{
auto i = detail::exist(string_table, str);
if (i == string_table.size())
{
string_table.emplace_back(std::move(str));
}
return table_next{ table_tag::string,i };
}
};
template<class Expr>struct loop_t
{
Expr expr;
std::size_t min;
std::size_t max;
template<class VariableTag, class value_type>
detail::table_next initialize(
std::vector<std::pair<value_type, value_type>>& range_table,
std::vector<std::basic_string<value_type>>& string_table,
std::vector<std::vector<table_next>>& sequence_table,
std::vector<std::vector<table_next>>& select_table,
std::vector<std::pair<table_next, std::pair<detail::index_t, detail::index_t>>>& loop_table,
std::vector<std::pair<bool, table_next>>& lahead_table,
std::vector<std::pair<table_next, VariableTag>>& variable_table)const
{
auto t = expr.initialize(range_table, string_table, sequence_table, select_table, loop_table, lahead_table, variable_table);
auto i = detail::exist(loop_table, std::make_pair(t, std::make_pair(min, max)));
if (i == loop_table.size())
{
loop_table.emplace_back(t, std::make_pair(min, max));
}
return table_next{ table_tag::loop,i };
}
};
template<class... Exprs>struct sequence_t
{
std::tuple<Exprs...> exprs;
template<class VariableTag, class value_type>
table_next initialize(
std::vector<std::pair<value_type, value_type>>& range_table,
std::vector<std::basic_string<value_type>>& string_table,
std::vector<std::vector<table_next>>& sequence_table,
std::vector<std::vector<table_next>>& select_table,
std::vector<std::pair<table_next, std::pair<detail::index_t, detail::index_t>>>& loop_table,
std::vector<std::pair<bool, table_next>>& lahead_table,
std::vector<std::pair<table_next, VariableTag>>& variable_table)const
{
return initialize(range_table, string_table, sequence_table, select_table, loop_table, lahead_table, variable_table, std::make_index_sequence<sizeof...(Exprs)>());
}
template<class VariableTag, class value_type, std::size_t... Is>table_next initialize(
std::vector<std::pair<value_type, value_type>>& range_table,
std::vector<std::basic_string<value_type>>& string_table,
std::vector<std::vector<table_next>>& sequence_table,
std::vector<std::vector<table_next>>& select_table,
std::vector<std::pair<table_next, std::pair<detail::index_t, detail::index_t>>>& loop_table,
std::vector<std::pair<bool, table_next>>& lahead_table,
std::vector<std::pair<table_next, VariableTag>>& variable_table,
std::index_sequence<Is...>)const
{
std::vector<table_next> vec = { std::get<Is>(exprs).initialize(range_table,string_table,sequence_table,select_table,loop_table,lahead_table,variable_table)... };
auto i = detail::exist(sequence_table, vec);
if (i == sequence_table.size())
{
sequence_table.emplace_back(std::move(vec));
}
return table_next{ table_tag::sequence,i };
}
};
template<class... Exprs>struct select_t
{
std::tuple<Exprs...> exprs;
template<class VariableTag, class value_type>
table_next initialize(
std::vector<std::pair<value_type, value_type>>& range_table,
std::vector<std::basic_string<value_type>>& string_table,
std::vector<std::vector<table_next>>& sequence_table,
std::vector<std::vector<table_next>>& select_table,
std::vector<std::pair<table_next, std::pair<detail::index_t, detail::index_t>>>& loop_table,
std::vector<std::pair<bool, table_next>>& lahead_table,
std::vector<std::pair<table_next, VariableTag>>& variable_table)const
{
return initialize(range_table, string_table, sequence_table, select_table, loop_table, lahead_table, variable_table, std::make_index_sequence<sizeof...(Exprs)>());
}
template<class VariableTag, class value_type, std::size_t... Is>table_next initialize(
std::vector<std::pair<value_type, value_type>>& range_table,
std::vector<std::basic_string<value_type>>& string_table,
std::vector<std::vector<table_next>>& sequence_table,
std::vector<std::vector<table_next>>& select_table,
std::vector<std::pair<table_next, std::pair<detail::index_t, detail::index_t>>>& loop_table,
std::vector<std::pair<bool, table_next>>& lahead_table,
std::vector<std::pair<table_next, VariableTag>>& variable_table,
std::index_sequence<Is...>)const
{
std::vector<table_next> vec = { std::get<Is>(exprs).initialize(range_table,string_table,sequence_table,select_table,loop_table,lahead_table,variable_table)... };
auto i = detail::exist(select_table, vec);
if (i == select_table.size())
{
select_table.emplace_back(std::move(vec));
}
return table_next{ table_tag::select,i };
}
};
template<class Expr>struct lahead_t
{
Expr expr;
template<class VariableTag, class value_type>
table_next initialize(
std::vector<std::pair<value_type, value_type>>& range_table,
std::vector<std::basic_string<value_type>>& string_table,
std::vector<std::vector<table_next>>& sequence_table,
std::vector<std::vector<table_next>>& select_table,
std::vector<std::pair<table_next, std::pair<detail::index_t, detail::index_t>>>& loop_table,
std::vector<std::pair<bool, table_next>>& lahead_table,
std::vector<std::pair<table_next, VariableTag>>& variable_table)const
{
auto t = expr.initialize(range_table, string_table, sequence_table, select_table, loop_table, lahead_table, variable_table);
auto i = detail::exist(lahead_table, std::make_pair(true, t));
if (i == lahead_table.size())
{
lahead_table.emplace_back(true, t);
}
return table_next{ table_tag::lahead,i };
}
};
template<class Expr>struct not_lahead_t
{
Expr expr;
template<class VariableTag, class value_type>
table_next initialize(
std::vector<std::pair<value_type, value_type>>& range_table,
std::vector<std::basic_string<value_type>>& string_table,
std::vector<std::vector<table_next>>& sequence_table,
std::vector<std::vector<table_next>>& select_table,
std::vector<std::pair<table_next, std::pair<detail::index_t, detail::index_t>>>& loop_table,
std::vector<std::pair<bool, table_next>>& lahead_table,
std::vector<std::pair<table_next, VariableTag>>& variable_table)const
{
auto t = expr.initialize(range_table, string_table, sequence_table, select_table, loop_table, lahead_table, variable_table);
auto i = detail::exist(lahead_table, std::make_pair(false, t));
if (i == lahead_table.size())
{
lahead_table.emplace_back(false, t);
}
return table_next{ table_tag::lahead,i };
}
};
template<class Expr>auto operator*(Expr expr)
{
return loop_t<Expr>{expr, 0, std::numeric_limits<std::size_t>::max()};
}
template<class Expr>auto operator+(Expr expr)
{
return loop_t<Expr>{expr, 1, std::numeric_limits<std::size_t>::max()};
}
template<class Expr>auto operator-(Expr expr)
{
return loop_t<Expr>{expr, 0, 1};
}
template<class Expr>auto operator!(Expr expr)
{
return lahead_t<Expr>{expr};
}
template<class Expr>auto operator~(Expr expr)
{
return not_lahead_t<Expr>{expr};
}
template<class Expr1, class Expr2>auto operator<<(Expr1 expr1, Expr2 expr2)
{
return sequence_t<Expr1, Expr2>{std::make_tuple(expr1, expr2)};
}
template<class Expr, class... Exprs>auto operator<<(sequence_t<Exprs...> seq, Expr expr)
{
return sequence_t<Exprs..., Expr>{std::tuple_cat(seq.exprs, std::make_tuple(expr))};
}
template<class Expr1, class Expr2>auto operator/(Expr1 expr1, Expr2 expr2)
{
return select_t<Expr1, Expr2>{std::make_tuple(expr1, expr2)};
}
template<class Expr, class... Exprs>auto operator/(select_t<Exprs...> sel, Expr expr)
{
return select_t<Exprs..., Expr>{std::tuple_cat(sel.exprs, std::make_tuple(expr))};
}
}
template<class CharT>auto range(CharT min, CharT max)
{
return types::range_t<CharT>{min, max};
}
namespace literals
{
auto operator""_e(char const* str, std::size_t)
{
return types::strings_t<char>{std::string(str)};
}
auto operator""_e(wchar_t const* str, std::size_t)
{
return types::strings_t<wchar_t>{std::wstring(str)};
}
}
template<class CharT, class VariableTag>using variable_t = types::variable_t<CharT, VariableTag>;
template<class CharT,class VariableTag>class expression
{
typedef CharT value_type;
typedef detail::table_tag table_tag;
typedef detail::table_next table_next;
std::vector<std::pair<value_type, value_type>> range_table;
std::vector<std::basic_string<value_type>> string_table;
std::vector<std::vector<table_next>> sequence_table;
std::vector<std::vector<table_next>> select_table;
std::vector<std::pair<table_next, std::pair<detail::index_t, detail::index_t>>> loop_table;
std::vector<std::pair<bool, table_next>> lahead_table;
std::vector<std::pair<table_next, VariableTag>> variable_table;
detail::index_t start_variable;
template<class InputIterator>struct parsing_object
{
typedef parsing_result<InputIterator, VariableTag> return_type;
struct result_data
{
InputIterator end;
std::size_t size;
detail::index_t select;
};
typedef detail::table_tag table_tag;
typedef detail::table_next table_next;
expression const& expr;
std::array<std::vector<std::map<InputIterator, std::optional<result_data>>>, 6>memo;
std::optional<result_data> parsei_string(InputIterator, InputIterator now, InputIterator last, table_next next, detail::index_t)
{
if (memo[0][next.index].count(now))
{
return memo[0][next.index][now];
}
auto const& str = expr.string_table[next.index];
if (std::size_t(std::distance(now, last)) >= str.size() && std::equal(str.begin(), str.end(), now))
{
return memo[0][next.index][now] = result_data{ std::next(now,str.size()),0,0 };
}
else
{
return memo[0][next.index][now] = std::nullopt;
}
}
std::optional<result_data> parsei_sequence(InputIterator first, InputIterator now, InputIterator last, table_next next, detail::index_t variable)
{
if (memo[1][next.index].count(now))
{
return memo[1][next.index][now];
}
auto n = now;
for (auto const& nex : expr.sequence_table[next.index])
{
if (auto ret = parsei(first, now, last, nex, variable))
{
now = ret->end;
}
else
{
return memo[1][next.index][n] = std::nullopt;
}
}
return memo[1][next.index][n] = result_data{ now,expr.sequence_table[next.index].size(),0 };
}
std::optional<result_data> parsei_select(InputIterator first, InputIterator now, InputIterator last, table_next next, detail::index_t variable)
{
if (memo[2][next.index].count(now))
{
return memo[2][next.index][now];
}
std::size_t index = 0;
for (auto const& nex : expr.select_table[next.index])
{
if (auto ret = parsei(first, now, last, nex, variable))
{
return memo[2][next.index][now] = result_data{ ret->end,1,index };
}
else
{
++index;
}
}
return memo[2][next.index][now] = std::nullopt;
}
std::optional<result_data> parsei_loop(InputIterator first, InputIterator now, InputIterator last, table_next next, detail::index_t variable)
{
if (memo[3][next.index].count(now))
{
return memo[3][next.index][now];
}
auto n = now;
for (std::size_t i = 0; i < expr.loop_table[next.index].second.second; ++i)
{
if (auto ret = parsei(first, now, last, expr.loop_table[next.index].first, variable))
{
now = ret->end;
}
else if (i < expr.loop_table[next.index].second.first)
{
return memo[3][next.index][n] = std::nullopt;
}
else
{
return memo[3][next.index][n] = result_data{ now,i,0 };
}
}
return memo[3][next.index][n] = result_data{ now,expr.loop_table[next.index].second.second,0 };
}
std::optional<result_data> parsei_variable(InputIterator first, InputIterator now, InputIterator last, table_next next, detail::index_t variable)
{
if (memo[4][next.index].count(now))
{
return memo[4][next.index][now];
}
if (next.index == variable&&first == now)
{
throw std::invalid_argument("this parser does NOT support Left-Recursion.");
}
if (auto ret = parsei(now, now, last, expr.variable_table[next.index].first, next.index))
{
return memo[4][next.index][now] = result_data{ ret->end,0,0 };
}
else
{
return memo[4][next.index][now] = std::nullopt;
}
}
std::optional<result_data> parsei_lahead(InputIterator first, InputIterator now, InputIterator last, table_next next, detail::index_t variable)
{
if (memo[5][next.index].count(now))
{
return memo[5][next.index][now];
}
if (static_cast<bool>(parsei(first, now, last, expr.lahead_table[next.index].second, variable)) == expr.lahead_table[next.index].first)
{
return memo[5][next.index][now] = result_data{ now,0,0 };
}
else
{
return memo[5][next.index][now] = std::nullopt;
}
}
std::optional<result_data> parsei(InputIterator first, InputIterator now, InputIterator last, table_next next, detail::index_t variable)
{
switch (next.tag)
{
case table_tag::string:
return parsei_string(first, now, last, next, variable);
case table_tag::sequence:
return parsei_sequence(first, now, last, next, variable);
case table_tag::select:
return parsei_select(first, now, last, next, variable);
case table_tag::loop:
return parsei_loop(first, now, last, next, variable);
case table_tag::variable:
return parsei_variable(first, now, last, next, variable);
case table_tag::range:
if (now != last&&expr.range_table[next.index].first <= *now&&*now <= expr.range_table[next.index].second)
{
return result_data{ std::next(now),0,0 };
}
else
{
return std::nullopt;
}
default:
return parsei_lahead(first, now, last, next, variable);
}
}
return_type construct_result_string(InputIterator first, detail::index_t index)
{
return return_type(first, std::next(first, expr.string_table[index].size()), {}, std::nullopt);
}
return_type construct_result_sequence(InputIterator first, detail::index_t index)
{
auto n = first;
std::vector<return_type> ret;
ret.reserve(expr.sequence_table[index].size());
for (auto const& d : expr.sequence_table[index])
{
ret.emplace_back(construct_result(first, d.index, d.tag));
first = ret.back().end();
}
return return_type(n, first, std::move(ret), std::nullopt);
}
return_type construct_result_select(InputIterator first, detail::index_t index)
{
auto d = memo[2][index][first];
auto s = expr.select_table[index][d->select];
return construct_result(first, s.index, s.tag);
}
return_type construct_result_loop(InputIterator first, detail::index_t index)
{
auto n = first;
auto d = memo[3][index][first];
auto t = expr.loop_table[index].first;
std::vector<return_type> ret;
ret.reserve(d->size);
if (t.tag != table_tag::range)
{
for (std::size_t i = 0; i < d->size; ++i)
{
ret.emplace_back(construct_result(first, t.index, t.tag));
first = ret.back().end();
}
}
else
{
first = d->end;
}
return return_type(n, first, std::move(ret), std::nullopt);
}
return_type construct_result_variable(InputIterator first, detail::index_t index)
{
auto d = expr.variable_table[index].first;
auto t = expr.variable_table[index].second;
auto ret = construct_result(first, d.index, d.tag);
if (!ret.get_tag())
{
ret.change_tag(t);
}
return ret;
}
return_type construct_result_lahead(InputIterator first, detail::index_t)
{
return return_type(first, first, {}, std::nullopt);
}
return_type construct_result_range(InputIterator first, detail::index_t)
{
return return_type(first, std::next(first), {}, std::nullopt);
}
return_type construct_result(InputIterator first, detail::index_t index, table_tag tag)
{
switch (tag)
{
case table_tag::string:
return construct_result_string(first, index);
case table_tag::sequence:
return construct_result_sequence(first, index);
case table_tag::select:
return construct_result_select(first, index);
case table_tag::loop:
return construct_result_loop(first, index);
case table_tag::variable:
return construct_result_variable(first, index);
case table_tag::range:
return construct_result_range(first, index);
default:
return construct_result_lahead(first, index);
}
}
std::optional<return_type> parse(InputIterator first, InputIterator last)
{
if (auto ret = parsei(first, first, last, table_next{ table_tag::variable,expr.start_variable }, 99999999))
{
return construct_result_variable(first, expr.start_variable);
}
return std::nullopt;
}
};
public:
template<class InputIterator>auto parse(InputIterator first, InputIterator last)
{
parsing_object<InputIterator> obj{ *this,{} };
obj.memo[0].resize(this->string_table.size());
obj.memo[1].resize(this->sequence_table.size());
obj.memo[2].resize(this->select_table.size());
obj.memo[3].resize(this->loop_table.size());
obj.memo[4].resize(this->variable_table.size());
obj.memo[5].resize(this->lahead_table.size());
return obj.parse(first, last);
}
expression(VariableTag start, std::vector<variable_t<CharT, VariableTag>>vars):
range_table{},
string_table{},
sequence_table{},
select_table{},
loop_table{},
lahead_table{},
variable_table{},
start_variable{}
{
for (auto const& v : vars)
{
v.value_init(range_table, string_table, sequence_table, select_table, loop_table, lahead_table, variable_table);
}
for (detail::index_t i = 0; i < variable_table.size(); ++i)
{
if (variable_table[i].second == start)
{
start_variable = i;
return;
}
}
}
};
}
#include"parser.hpp"
#include<iostream>
#include<string>
using namespace parsing_expression_light;
using namespace literals;
enum class tag
{
sum,
mul,
val,
atomic
};
typedef variable_t<char, tag> test;
void print(parsing_result<std::string::const_iterator, tag>const& result)
{
if (result.get_tag() == tag::sum)
{
auto s = result[0].size();
if (s != 0)
{
std::cout << "(+ ";
for (std::size_t i = 0; i < s; ++i)
{
print(result[0][i][0]);
std::cout << " ";
}
print(result[1]);
std::cout << ")";
}
else
{
print(result[1]);
}
}
else if (result.get_tag() == tag::mul)
{
auto s = result[0].size();
if (s != 0)
{
std::cout << "(* ";
for (std::size_t i = 0; i < s; ++i)
{
print(result[0][i][0]);
std::cout << " ";
}
print(result[1]);
std::cout << ")";
}
else
{
print(result[1]);
}
}
else if (result.get_tag() == tag::val)
{
print(result[1]);
}
else if (result.get_tag() == tag::atomic)
{
std::cout << std::string(result.begin(), result.end());
}
else
{
throw std::invalid_argument("error");
}
}
int main()
{
test sum(tag::sum), mul(tag::mul),val(tag::val), atomic(tag::atomic);
sum = *(mul << "+"_e) << mul;
mul = *(val << "*"_e) << val;
val = atomic / ("("_e << sum << ")"_e);
atomic = +range('0', '9');
expression<char, tag> parser(tag::sum, { sum,mul,val,atomic });
std::string str;
while (std::getline(std::cin, str))
{
if (str == "end")
{
break;
}
if (auto result = parser.parse(str.cbegin(), str.cend()))
{
print(*result);
std::cout << std::endl;
}
else
{
std::cout << "parse error" << std::endl;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment