あとで書く
Last active
June 30, 2022 02:07
-
-
Save plasma-effect/f5be7d5d0154ea9bc97bba57c5a7ad19 to your computer and use it in GitHub Desktop.
parser定期
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
// 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; | |
} | |
} | |
} | |
}; | |
} |
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"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