replace list_parser with a simpler api
parent
704f9217f7
commit
9d0494a9da
|
@ -75,6 +75,7 @@ struct OSTD_EXPORT cs_strref {
|
||||||
|
|
||||||
cs_strref() = delete;
|
cs_strref() = delete;
|
||||||
cs_strref(cs_shared_state &cs, ostd::string_range str);
|
cs_strref(cs_shared_state &cs, ostd::string_range str);
|
||||||
|
cs_strref(cs_state &cs, ostd::string_range str);
|
||||||
|
|
||||||
cs_strref(cs_strref const &ref);
|
cs_strref(cs_strref const &ref);
|
||||||
|
|
||||||
|
@ -379,6 +380,7 @@ static inline void *cs_default_alloc(void *, void *p, size_t, size_t ns) {
|
||||||
struct OSTD_EXPORT cs_state {
|
struct OSTD_EXPORT cs_state {
|
||||||
friend struct cs_error;
|
friend struct cs_error;
|
||||||
friend struct cs_strman;
|
friend struct cs_strman;
|
||||||
|
friend struct cs_strref;
|
||||||
friend struct cs_value;
|
friend struct cs_value;
|
||||||
friend struct cs_gen_state;
|
friend struct cs_gen_state;
|
||||||
|
|
||||||
|
@ -649,6 +651,19 @@ private:
|
||||||
bool p_pushed;
|
bool p_pushed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct cs_list_parse_state {
|
||||||
|
cs_list_parse_state(ostd::string_range s = ostd::string_range{}): input{s} {}
|
||||||
|
|
||||||
|
ostd::string_range input{};
|
||||||
|
ostd::string_range item{};
|
||||||
|
ostd::string_range quoted_item{};
|
||||||
|
};
|
||||||
|
|
||||||
|
OSTD_EXPORT bool list_parse(cs_list_parse_state &ps, cs_state &cs);
|
||||||
|
OSTD_EXPORT std::size_t list_count(cs_list_parse_state &ps, cs_state &cs);
|
||||||
|
OSTD_EXPORT cs_strref list_get_item(cs_list_parse_state &ps, cs_state &cs);
|
||||||
|
OSTD_EXPORT void list_find_item(cs_list_parse_state &ps);
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
template<typename R>
|
template<typename R>
|
||||||
inline R &&escape_string(R &&writer, ostd::string_range str) {
|
inline R &&escape_string(R &&writer, ostd::string_range str) {
|
||||||
|
@ -743,90 +758,6 @@ namespace util {
|
||||||
cs_state &cs, ostd::string_range str
|
cs_state &cs, ostd::string_range str
|
||||||
);
|
);
|
||||||
|
|
||||||
struct list_range;
|
|
||||||
|
|
||||||
struct OSTD_EXPORT list_parser {
|
|
||||||
list_parser() = delete;
|
|
||||||
list_parser(cs_state &cs, ostd::string_range src):
|
|
||||||
p_state(cs), p_input(src)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void skip();
|
|
||||||
bool parse();
|
|
||||||
size_t count();
|
|
||||||
|
|
||||||
template<typename R>
|
|
||||||
R &&get_item(R &&writer) const {
|
|
||||||
if (!p_quote.empty() && (*p_quote == '"')) {
|
|
||||||
return unescape_string(std::forward<R>(writer), p_item);
|
|
||||||
} else {
|
|
||||||
ostd::range_put_all(writer, p_item);
|
|
||||||
return std::forward<R>(writer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cs_string get_item() const {
|
|
||||||
return std::move(get_item(ostd::appender<cs_string>()).get());
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::string_range &get_raw_item(bool quoted = false) {
|
|
||||||
return quoted ? p_quote : p_item;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::string_range const &get_raw_item(bool quoted = false) const {
|
|
||||||
return quoted ? p_quote : p_item;
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::string_range &get_input() {
|
|
||||||
return p_input;
|
|
||||||
}
|
|
||||||
|
|
||||||
list_range iter() noexcept;
|
|
||||||
|
|
||||||
private:
|
|
||||||
ostd::string_range p_quote = ostd::string_range();
|
|
||||||
ostd::string_range p_item = ostd::string_range();
|
|
||||||
cs_state &p_state;
|
|
||||||
ostd::string_range p_input;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct list_range: ostd::input_range<list_range> {
|
|
||||||
using range_category = ostd::forward_range_tag;
|
|
||||||
using value_type = ostd::string_range;
|
|
||||||
using reference = ostd::string_range;
|
|
||||||
using size_type = std::size_t;
|
|
||||||
|
|
||||||
list_range() = delete;
|
|
||||||
|
|
||||||
list_range(list_parser &p) noexcept: p_parser(&p) {
|
|
||||||
pop_front();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool empty() const noexcept {
|
|
||||||
return !bool(p_item);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pop_front() noexcept {
|
|
||||||
if (p_parser->parse()) {
|
|
||||||
p_item = p_parser->get_item();
|
|
||||||
} else {
|
|
||||||
p_item.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ostd::string_range front() const noexcept {
|
|
||||||
return *p_item;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
list_parser *p_parser;
|
|
||||||
std::optional<cs_string> p_item{};
|
|
||||||
};
|
|
||||||
|
|
||||||
inline list_range list_parser::iter() noexcept {
|
|
||||||
return list_range{*this};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename R>
|
template<typename R>
|
||||||
inline void format_int(R &&writer, cs_int val) {
|
inline void format_int(R &&writer, cs_int val) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -17,14 +17,10 @@ ostd::string_range cs_gen_state::get_str() {
|
||||||
return ret.slice(1, ret.size() - 1);
|
return ret.slice(1, ret.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
cs_string cs_gen_state::get_str_dup(bool unescape) {
|
cs_string cs_gen_state::get_str_dup() {
|
||||||
auto str = get_str();
|
auto str = get_str();
|
||||||
auto app = ostd::appender<cs_string>();
|
auto app = ostd::appender<cs_string>();
|
||||||
if (unescape) {
|
util::unescape_string(app, str);
|
||||||
util::unescape_string(app, str);
|
|
||||||
} else {
|
|
||||||
app.get() = str;
|
|
||||||
}
|
|
||||||
return std::move(app.get());
|
return std::move(app.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
215
src/cs_util.cc
215
src/cs_util.cc
|
@ -357,107 +357,120 @@ end:
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
void list_parser::skip() {
|
|
||||||
for (;;) {
|
|
||||||
while (!p_input.empty()) {
|
|
||||||
char c = *p_input;
|
|
||||||
if ((c == ' ') || (c == '\t') || (c == '\r') || (c == '\n')) {
|
|
||||||
++p_input;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((p_input.size() < 2) || (p_input[0] != '/') || (p_input[1] != '/')) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
p_input = ostd::find(p_input, '\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool list_parser::parse() {
|
|
||||||
skip();
|
|
||||||
if (p_input.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
switch (*p_input) {
|
|
||||||
case '"':
|
|
||||||
p_quote = p_input;
|
|
||||||
p_input = parse_string(p_state, p_input);
|
|
||||||
p_quote = p_quote.slice(0, &p_input[0] - &p_quote[0]);
|
|
||||||
p_item = p_quote.slice(1, p_quote.size() - 1);
|
|
||||||
break;
|
|
||||||
case '(':
|
|
||||||
case '[': {
|
|
||||||
p_quote = p_input;
|
|
||||||
++p_input;
|
|
||||||
p_item = p_input;
|
|
||||||
char btype = *p_quote;
|
|
||||||
int brak = 1;
|
|
||||||
for (;;) {
|
|
||||||
p_input = ostd::find_one_of(
|
|
||||||
p_input, ostd::string_range("\"/;()[]")
|
|
||||||
);
|
|
||||||
if (p_input.empty()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
char c = *p_input;
|
|
||||||
++p_input;
|
|
||||||
switch (c) {
|
|
||||||
case '"':
|
|
||||||
p_input = parse_string(p_state, p_input);
|
|
||||||
break;
|
|
||||||
case '/':
|
|
||||||
if (!p_input.empty() && (*p_input == '/')) {
|
|
||||||
p_input = ostd::find(p_input, '\n');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '(':
|
|
||||||
case '[':
|
|
||||||
brak += (c == btype);
|
|
||||||
break;
|
|
||||||
case ')':
|
|
||||||
if ((btype == '(') && (--brak <= 0)) {
|
|
||||||
goto endblock;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ']':
|
|
||||||
if ((btype == '[') && (--brak <= 0)) {
|
|
||||||
goto endblock;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
endblock:
|
|
||||||
p_item = p_item.slice(0, &p_input[0] - &p_item[0]);
|
|
||||||
p_item.pop_back();
|
|
||||||
p_quote = p_quote.slice(0, &p_input[0] - &p_quote[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ')':
|
|
||||||
case ']':
|
|
||||||
return false;
|
|
||||||
default: {
|
|
||||||
ostd::string_range e = parse_word(p_state, p_input);
|
|
||||||
p_quote = p_item = p_input.slice(0, &e[0] - &p_input[0]);
|
|
||||||
p_input = e;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
skip();
|
|
||||||
if (!p_input.empty() && (*p_input == ';')) {
|
|
||||||
++p_input;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t list_parser::count() {
|
|
||||||
size_t ret = 0;
|
|
||||||
while (parse()) {
|
|
||||||
++ret;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
} /* namespace util */
|
} /* namespace util */
|
||||||
|
|
||||||
|
OSTD_EXPORT bool list_parse(cs_list_parse_state &ps, cs_state &cs) {
|
||||||
|
list_find_item(ps);
|
||||||
|
if (ps.input.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
switch (*ps.input) {
|
||||||
|
case '"':
|
||||||
|
ps.quoted_item = ps.input;
|
||||||
|
ps.input = util::parse_string(cs, ps.input);
|
||||||
|
ps.quoted_item = ps.quoted_item.slice(
|
||||||
|
0, &ps.input[0] - &ps.quoted_item[0]
|
||||||
|
);
|
||||||
|
ps.item = ps.quoted_item.slice(1, ps.quoted_item.size() - 1);
|
||||||
|
break;
|
||||||
|
case '(':
|
||||||
|
case '[': {
|
||||||
|
ps.quoted_item = ps.input;
|
||||||
|
++ps.input;
|
||||||
|
ps.item = ps.input;
|
||||||
|
char btype = *ps.quoted_item;
|
||||||
|
int brak = 1;
|
||||||
|
for (;;) {
|
||||||
|
ps.input = ostd::find_one_of(
|
||||||
|
ps.input, ostd::string_range("\"/;()[]")
|
||||||
|
);
|
||||||
|
if (ps.input.empty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
char c = *ps.input;
|
||||||
|
++ps.input;
|
||||||
|
switch (c) {
|
||||||
|
case '"':
|
||||||
|
ps.input = util::parse_string(cs, ps.input);
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
if (!ps.input.empty() && (*ps.input == '/')) {
|
||||||
|
ps.input = ostd::find(ps.input, '\n');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '(':
|
||||||
|
case '[':
|
||||||
|
brak += (c == btype);
|
||||||
|
break;
|
||||||
|
case ')':
|
||||||
|
if ((btype == '(') && (--brak <= 0)) {
|
||||||
|
goto endblock;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ']':
|
||||||
|
if ((btype == '[') && (--brak <= 0)) {
|
||||||
|
goto endblock;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endblock:
|
||||||
|
ps.item = ps.item.slice(0, &ps.input[0] - &ps.item[0]);
|
||||||
|
ps.item.pop_back();
|
||||||
|
ps.quoted_item = ps.quoted_item.slice(
|
||||||
|
0, &ps.input[0] - &ps.quoted_item[0]
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ')':
|
||||||
|
case ']':
|
||||||
|
return false;
|
||||||
|
default: {
|
||||||
|
ostd::string_range e = util::parse_word(cs, ps.input);
|
||||||
|
ps.quoted_item = ps.item = ps.input.slice(0, &e[0] - &ps.input[0]);
|
||||||
|
ps.input = e;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list_find_item(ps);
|
||||||
|
if (!ps.input.empty() && (*ps.input == ';')) {
|
||||||
|
++ps.input;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSTD_EXPORT std::size_t list_count(cs_list_parse_state &ps, cs_state &cs) {
|
||||||
|
size_t ret = 0;
|
||||||
|
while (list_parse(ps, cs)) {
|
||||||
|
++ret;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSTD_EXPORT cs_strref list_get_item(cs_list_parse_state &ps, cs_state &cs) {
|
||||||
|
if (!ps.quoted_item.empty() && (*ps.quoted_item == '"')) {
|
||||||
|
auto app = ostd::appender<cs_string>();
|
||||||
|
util::unescape_string(app, ps.item);
|
||||||
|
return cs_strref{cs, app.get()};
|
||||||
|
}
|
||||||
|
return cs_strref{cs, ps.item};
|
||||||
|
}
|
||||||
|
|
||||||
|
OSTD_EXPORT void list_find_item(cs_list_parse_state &ps) {
|
||||||
|
for (;;) {
|
||||||
|
while (!ps.input.empty()) {
|
||||||
|
char c = *ps.input;
|
||||||
|
if ((c == ' ') || (c == '\t') || (c == '\r') || (c == '\n')) {
|
||||||
|
++ps.input;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((ps.input.size() < 2) || (ps.input[0] != '/') || (ps.input[1] != '/')) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ps.input = ostd::find(ps.input, '\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace cscript */
|
} /* namespace cscript */
|
||||||
|
|
|
@ -13,6 +13,12 @@ cs_strref::cs_strref(cs_shared_state &cs, ostd::string_range str):
|
||||||
p_str = cs.strman->add(str);
|
p_str = cs.strman->add(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cs_strref::cs_strref(cs_state &cs, ostd::string_range str):
|
||||||
|
p_state{cs.p_state}
|
||||||
|
{
|
||||||
|
p_str = p_state->strman->add(str);
|
||||||
|
}
|
||||||
|
|
||||||
cs_strref::cs_strref(cs_strref const &ref): p_state{ref.p_state}, p_str{ref.p_str}
|
cs_strref::cs_strref(cs_strref const &ref): p_state{ref.p_state}, p_str{ref.p_str}
|
||||||
{
|
{
|
||||||
p_state->strman->ref(p_str);
|
p_state->strman->ref(p_str);
|
||||||
|
|
|
@ -195,7 +195,7 @@ struct cs_gen_state {
|
||||||
}
|
}
|
||||||
|
|
||||||
ostd::string_range get_str();
|
ostd::string_range get_str();
|
||||||
cs_string get_str_dup(bool unescape = true);
|
cs_string get_str_dup();
|
||||||
|
|
||||||
ostd::string_range get_word();
|
ostd::string_range get_word();
|
||||||
|
|
||||||
|
|
171
src/lib_list.cc
171
src/lib_list.cc
|
@ -35,13 +35,13 @@ static inline void cs_list_find(
|
||||||
) {
|
) {
|
||||||
cs_int n = 0, skip = args[2].get_int();
|
cs_int n = 0, skip = args[2].get_int();
|
||||||
T val = cs_arg_val<T>::get(args[1]);
|
T val = cs_arg_val<T>::get(args[1]);
|
||||||
for (util::list_parser p(cs, args[0].get_str()); p.parse(); ++n) {
|
for (cs_list_parse_state p{args[0].get_str()}; list_parse(p, cs); ++n) {
|
||||||
if (cmp(p, val)) {
|
if (cmp(p, val)) {
|
||||||
res.set_int(n);
|
res.set_int(n);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < skip; ++i) {
|
for (int i = 0; i < skip; ++i) {
|
||||||
if (!p.parse()) {
|
if (!list_parse(p, cs)) {
|
||||||
goto notfound;
|
goto notfound;
|
||||||
}
|
}
|
||||||
++n;
|
++n;
|
||||||
|
@ -56,14 +56,14 @@ static inline void cs_list_assoc(
|
||||||
cs_state &cs, cs_value_r args, cs_value &res, F cmp
|
cs_state &cs, cs_value_r args, cs_value &res, F cmp
|
||||||
) {
|
) {
|
||||||
T val = cs_arg_val<T>::get(args[1]);
|
T val = cs_arg_val<T>::get(args[1]);
|
||||||
for (util::list_parser p(cs, args[0].get_str()); p.parse();) {
|
for (cs_list_parse_state p{args[0].get_str()}; list_parse(p, cs);) {
|
||||||
if (cmp(p, val)) {
|
if (cmp(p, val)) {
|
||||||
if (p.parse()) {
|
if (list_parse(p, cs)) {
|
||||||
res.set_str(p.get_item());
|
res.set_str(list_get_item(p, cs));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!p.parse()) {
|
if (!list_parse(p, cs)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,8 +79,8 @@ static void cs_loop_list_conc(
|
||||||
}
|
}
|
||||||
cs_string r;
|
cs_string r;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (util::list_parser p(cs, list); p.parse(); ++n) {
|
for (cs_list_parse_state p{list}; list_parse(p, cs); ++n) {
|
||||||
idv.set_str(p.get_item());
|
idv.set_str(list_get_item(p, cs));
|
||||||
idv.push();
|
idv.push();
|
||||||
if (n && space) {
|
if (n && space) {
|
||||||
r += ' ';
|
r += ' ';
|
||||||
|
@ -104,8 +104,8 @@ int cs_list_includes(
|
||||||
cs_state &cs, ostd::string_range list, ostd::string_range needle
|
cs_state &cs, ostd::string_range list, ostd::string_range needle
|
||||||
) {
|
) {
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
for (util::list_parser p(cs, list); p.parse();) {
|
for (cs_list_parse_state p{list}; list_parse(p, cs);) {
|
||||||
if (p.get_raw_item() == needle) {
|
if (p.item == needle) {
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
++offset;
|
++offset;
|
||||||
|
@ -126,12 +126,12 @@ static inline void cs_list_merge(
|
||||||
if (Swap) {
|
if (Swap) {
|
||||||
std::swap(list, elems);
|
std::swap(list, elems);
|
||||||
}
|
}
|
||||||
for (util::list_parser p(cs, list); p.parse();) {
|
for (cs_list_parse_state p{list}; list_parse(p, cs);) {
|
||||||
if (cmp(cs_list_includes(cs, elems, p.get_raw_item()), 0)) {
|
if (cmp(cs_list_includes(cs, elems, p.item), 0)) {
|
||||||
if (!buf.empty()) {
|
if (!buf.empty()) {
|
||||||
buf += ' ';
|
buf += ' ';
|
||||||
}
|
}
|
||||||
buf += p.get_raw_item(true);
|
buf += p.quoted_item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res.set_str(buf);
|
res.set_str(buf);
|
||||||
|
@ -141,7 +141,8 @@ static void cs_init_lib_list_sort(cs_state &cs);
|
||||||
|
|
||||||
void cs_init_lib_list(cs_state &gcs) {
|
void cs_init_lib_list(cs_state &gcs) {
|
||||||
gcs.new_command("listlen", "s", [](auto &cs, auto args, auto &res) {
|
gcs.new_command("listlen", "s", [](auto &cs, auto args, auto &res) {
|
||||||
res.set_int(cs_int(util::list_parser(cs, args[0].get_str()).count()));
|
cs_list_parse_state p{args[0].get_str()};
|
||||||
|
res.set_int(cs_int(list_count(p, cs)));
|
||||||
});
|
});
|
||||||
|
|
||||||
gcs.new_command("at", "si1V", [](auto &cs, auto args, auto &res) {
|
gcs.new_command("at", "si1V", [](auto &cs, auto args, auto &res) {
|
||||||
|
@ -149,51 +150,51 @@ void cs_init_lib_list(cs_state &gcs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cs_strref str = args[0].get_str();
|
cs_strref str = args[0].get_str();
|
||||||
util::list_parser p(cs, str);
|
cs_list_parse_state p{str};
|
||||||
p.get_raw_item() = str;
|
p.item = str;
|
||||||
for (size_t i = 1; i < args.size(); ++i) {
|
for (size_t i = 1; i < args.size(); ++i) {
|
||||||
p.get_input() = str;
|
p.input = str;
|
||||||
cs_int pos = args[i].get_int();
|
cs_int pos = args[i].get_int();
|
||||||
for (; pos > 0; --pos) {
|
for (; pos > 0; --pos) {
|
||||||
if (!p.parse()) {
|
if (!list_parse(p, cs)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pos > 0 || !p.parse()) {
|
if (pos > 0 || !list_parse(p, cs)) {
|
||||||
p.get_raw_item() = p.get_raw_item(true) = ostd::string_range();
|
p.item = p.quoted_item = ostd::string_range();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res.set_str(p.get_item());
|
res.set_str(list_get_item(p, cs));
|
||||||
});
|
});
|
||||||
|
|
||||||
gcs.new_command("sublist", "siiN", [](auto &cs, auto args, auto &res) {
|
gcs.new_command("sublist", "siiN", [](auto &cs, auto args, auto &res) {
|
||||||
cs_int skip = args[1].get_int(),
|
cs_int skip = args[1].get_int(),
|
||||||
count = args[2].get_int(),
|
count = args[2].get_int(),
|
||||||
numargs = args[3].get_int();
|
numargs = args[3].get_int();
|
||||||
|
|
||||||
cs_int offset = std::max(skip, cs_int(0)),
|
cs_int offset = std::max(skip, cs_int(0)),
|
||||||
len = (numargs >= 3) ? std::max(count, cs_int(0)) : -1;
|
len = (numargs >= 3) ? std::max(count, cs_int(0)) : -1;
|
||||||
|
|
||||||
util::list_parser p(cs, args[0].get_str());
|
cs_list_parse_state p{args[0].get_str()};
|
||||||
for (cs_int i = 0; i < offset; ++i) {
|
for (cs_int i = 0; i < offset; ++i) {
|
||||||
if (!p.parse()) break;
|
if (!list_parse(p, cs)) break;
|
||||||
}
|
}
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
if (offset > 0) {
|
if (offset > 0) {
|
||||||
p.skip();
|
list_find_item(p);
|
||||||
}
|
}
|
||||||
res.set_str(cs_string{p.get_input()});
|
res.set_str(cs_string{p.input});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char const *list = p.get_input().data();
|
char const *list = p.input.data();
|
||||||
p.get_raw_item(true) = ostd::string_range();
|
p.quoted_item = ostd::string_range();
|
||||||
if (len > 0 && p.parse()) {
|
if (len > 0 && list_parse(p, cs)) {
|
||||||
while (--len > 0 && p.parse());
|
while (--len > 0 && list_parse(p, cs));
|
||||||
}
|
}
|
||||||
ostd::string_range quote = p.get_raw_item(true);
|
ostd::string_range quote = p.quoted_item;
|
||||||
char const *qend = !quote.empty() ? "e[quote.size()] : list;
|
char const *qend = !quote.empty() ? "e[quote.size()] : list;
|
||||||
res.set_str(cs_string{list, size_t(qend - list)});
|
res.set_str(ostd::string_range{list, qend});
|
||||||
});
|
});
|
||||||
|
|
||||||
gcs.new_command("listfind", "rse", [](auto &cs, auto args, auto &res) {
|
gcs.new_command("listfind", "rse", [](auto &cs, auto args, auto &res) {
|
||||||
|
@ -204,9 +205,9 @@ void cs_init_lib_list(cs_state &gcs) {
|
||||||
}
|
}
|
||||||
auto body = args[2].get_code();
|
auto body = args[2].get_code();
|
||||||
int n = -1;
|
int n = -1;
|
||||||
for (util::list_parser p(cs, args[1].get_str()); p.parse();) {
|
for (cs_list_parse_state p{args[1].get_str()}; list_parse(p, cs);) {
|
||||||
++n;
|
++n;
|
||||||
idv.set_str(cs_string{p.get_raw_item()});
|
idv.set_str(cs_string{p.item});
|
||||||
idv.push();
|
idv.push();
|
||||||
if (cs.run_bool(body)) {
|
if (cs.run_bool(body)) {
|
||||||
res.set_int(cs_int(n));
|
res.set_int(cs_int(n));
|
||||||
|
@ -223,17 +224,17 @@ void cs_init_lib_list(cs_state &gcs) {
|
||||||
}
|
}
|
||||||
auto body = args[2].get_code();
|
auto body = args[2].get_code();
|
||||||
int n = -1;
|
int n = -1;
|
||||||
for (util::list_parser p(cs, args[1].get_str()); p.parse();) {
|
for (cs_list_parse_state p{args[1].get_str()}; list_parse(p, cs);) {
|
||||||
++n;
|
++n;
|
||||||
idv.set_str(cs_string{p.get_raw_item()});
|
idv.set_str(cs_string{p.item});
|
||||||
idv.push();
|
idv.push();
|
||||||
if (cs.run_bool(body)) {
|
if (cs.run_bool(body)) {
|
||||||
if (p.parse()) {
|
if (list_parse(p, cs)) {
|
||||||
res.set_str(p.get_item());
|
res.set_str(list_get_item(p, cs));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!p.parse()) {
|
if (!list_parse(p, cs)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,44 +242,44 @@ void cs_init_lib_list(cs_state &gcs) {
|
||||||
|
|
||||||
gcs.new_command("listfind=", "i", [](auto &cs, auto args, auto &res) {
|
gcs.new_command("listfind=", "i", [](auto &cs, auto args, auto &res) {
|
||||||
cs_list_find<cs_int>(
|
cs_list_find<cs_int>(
|
||||||
cs, args, res, [](const util::list_parser &p, cs_int val) {
|
cs, args, res, [](cs_list_parse_state const &p, cs_int val) {
|
||||||
return cs_parse_int(p.get_raw_item()) == val;
|
return cs_parse_int(p.item) == val;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
gcs.new_command("listfind=f", "f", [](auto &cs, auto args, auto &res) {
|
gcs.new_command("listfind=f", "f", [](auto &cs, auto args, auto &res) {
|
||||||
cs_list_find<cs_float>(
|
cs_list_find<cs_float>(
|
||||||
cs, args, res, [](const util::list_parser &p, cs_float val) {
|
cs, args, res, [](cs_list_parse_state const &p, cs_float val) {
|
||||||
return cs_parse_float(p.get_raw_item()) == val;
|
return cs_parse_float(p.item) == val;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
gcs.new_command("listfind=s", "s", [](auto &cs, auto args, auto &res) {
|
gcs.new_command("listfind=s", "s", [](auto &cs, auto args, auto &res) {
|
||||||
cs_list_find<ostd::string_range>(
|
cs_list_find<ostd::string_range>(
|
||||||
cs, args, res, [](const util::list_parser &p, ostd::string_range val) {
|
cs, args, res, [](cs_list_parse_state const &p, ostd::string_range val) {
|
||||||
return p.get_raw_item() == val;
|
return p.item == val;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
gcs.new_command("listassoc=", "i", [](auto &cs, auto args, auto &res) {
|
gcs.new_command("listassoc=", "i", [](auto &cs, auto args, auto &res) {
|
||||||
cs_list_assoc<cs_int>(
|
cs_list_assoc<cs_int>(
|
||||||
cs, args, res, [](const util::list_parser &p, cs_int val) {
|
cs, args, res, [](cs_list_parse_state const &p, cs_int val) {
|
||||||
return cs_parse_int(p.get_raw_item()) == val;
|
return cs_parse_int(p.item) == val;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
gcs.new_command("listassoc=f", "f", [](auto &cs, auto args, auto &res) {
|
gcs.new_command("listassoc=f", "f", [](auto &cs, auto args, auto &res) {
|
||||||
cs_list_assoc<cs_float>(
|
cs_list_assoc<cs_float>(
|
||||||
cs, args, res, [](const util::list_parser &p, cs_float val) {
|
cs, args, res, [](cs_list_parse_state const &p, cs_float val) {
|
||||||
return cs_parse_float(p.get_raw_item()) == val;
|
return cs_parse_float(p.item) == val;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
gcs.new_command("listassoc=s", "s", [](auto &cs, auto args, auto &res) {
|
gcs.new_command("listassoc=s", "s", [](auto &cs, auto args, auto &res) {
|
||||||
cs_list_assoc<ostd::string_range>(
|
cs_list_assoc<ostd::string_range>(
|
||||||
cs, args, res, [](const util::list_parser &p, ostd::string_range val) {
|
cs, args, res, [](cs_list_parse_state const &p, ostd::string_range val) {
|
||||||
return p.get_raw_item() == val;
|
return p.item == val;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -290,8 +291,8 @@ void cs_init_lib_list(cs_state &gcs) {
|
||||||
}
|
}
|
||||||
auto body = args[2].get_code();
|
auto body = args[2].get_code();
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (util::list_parser p(cs, args[1].get_str()); p.parse(); ++n) {
|
for (cs_list_parse_state p{args[1].get_str()}; list_parse(p, cs); ++n) {
|
||||||
idv.set_str(p.get_item());
|
idv.set_str(list_get_item(p, cs));
|
||||||
idv.push();
|
idv.push();
|
||||||
switch (cs.run_loop(body)) {
|
switch (cs.run_loop(body)) {
|
||||||
case cs_loop_state::BREAK:
|
case cs_loop_state::BREAK:
|
||||||
|
@ -312,10 +313,10 @@ end:
|
||||||
}
|
}
|
||||||
auto body = args[3].get_code();
|
auto body = args[3].get_code();
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (util::list_parser p(cs, args[2].get_str()); p.parse(); n += 2) {
|
for (cs_list_parse_state p{args[2].get_str()}; list_parse(p, cs); n += 2) {
|
||||||
idv1.set_str(p.get_item());
|
idv1.set_str(list_get_item(p, cs));
|
||||||
if (p.parse()) {
|
if (list_parse(p, cs)) {
|
||||||
idv2.set_str(p.get_item());
|
idv2.set_str(list_get_item(p, cs));
|
||||||
} else {
|
} else {
|
||||||
idv2.set_str("");
|
idv2.set_str("");
|
||||||
}
|
}
|
||||||
|
@ -341,15 +342,15 @@ end:
|
||||||
}
|
}
|
||||||
auto body = args[4].get_code();
|
auto body = args[4].get_code();
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (util::list_parser p(cs, args[3].get_str()); p.parse(); n += 3) {
|
for (cs_list_parse_state p{args[3].get_str()}; list_parse(p, cs); n += 3) {
|
||||||
idv1.set_str(p.get_item());
|
idv1.set_str(list_get_item(p, cs));
|
||||||
if (p.parse()) {
|
if (list_parse(p, cs)) {
|
||||||
idv2.set_str(p.get_item());
|
idv2.set_str(list_get_item(p, cs));
|
||||||
} else {
|
} else {
|
||||||
idv2.set_str("");
|
idv2.set_str("");
|
||||||
}
|
}
|
||||||
if (p.parse()) {
|
if (list_parse(p, cs)) {
|
||||||
idv3.set_str(p.get_item());
|
idv3.set_str(list_get_item(p, cs));
|
||||||
} else {
|
} else {
|
||||||
idv3.set_str("");
|
idv3.set_str("");
|
||||||
}
|
}
|
||||||
|
@ -391,14 +392,14 @@ end:
|
||||||
auto body = args[2].get_code();
|
auto body = args[2].get_code();
|
||||||
cs_string r;
|
cs_string r;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (util::list_parser p(cs, args[1].get_str()); p.parse(); ++n) {
|
for (cs_list_parse_state p{args[1].get_str()}; list_parse(p, cs); ++n) {
|
||||||
idv.set_str(cs_string{p.get_raw_item()});
|
idv.set_str(p.item);
|
||||||
idv.push();
|
idv.push();
|
||||||
if (cs.run_bool(body)) {
|
if (cs.run_bool(body)) {
|
||||||
if (r.size()) {
|
if (r.size()) {
|
||||||
r += ' ';
|
r += ' ';
|
||||||
}
|
}
|
||||||
r += p.get_raw_item(true);
|
r += p.quoted_item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res.set_str(r);
|
res.set_str(r);
|
||||||
|
@ -411,8 +412,8 @@ end:
|
||||||
}
|
}
|
||||||
auto body = args[2].get_code();
|
auto body = args[2].get_code();
|
||||||
int n = 0, r = 0;
|
int n = 0, r = 0;
|
||||||
for (util::list_parser p(cs, args[1].get_str()); p.parse(); ++n) {
|
for (cs_list_parse_state p{args[1].get_str()}; list_parse(p, cs); ++n) {
|
||||||
idv.set_str(cs_string{p.get_raw_item()});
|
idv.set_str(p.item);
|
||||||
idv.push();
|
idv.push();
|
||||||
if (cs.run_bool(body)) {
|
if (cs.run_bool(body)) {
|
||||||
r++;
|
r++;
|
||||||
|
@ -425,14 +426,14 @@ end:
|
||||||
auto buf = ostd::appender<cs_string>();
|
auto buf = ostd::appender<cs_string>();
|
||||||
ostd::string_range s = args[0].get_str();
|
ostd::string_range s = args[0].get_str();
|
||||||
ostd::string_range conj = args[1].get_str();
|
ostd::string_range conj = args[1].get_str();
|
||||||
size_t len = util::list_parser(cs, s).count();
|
cs_list_parse_state p{s};
|
||||||
|
size_t len = list_count(p, cs);
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
for (util::list_parser p(cs, s); p.parse(); ++n) {
|
for (p.input = s; list_parse(p, cs); ++n) {
|
||||||
if (!p.get_raw_item(true).empty() &&
|
if (!p.quoted_item.empty() && (p.quoted_item.front() == '"')) {
|
||||||
(p.get_raw_item(true).front() == '"')) {
|
util::unescape_string(buf, p.item);
|
||||||
util::unescape_string(buf, p.get_raw_item());
|
|
||||||
} else {
|
} else {
|
||||||
ostd::range_put_all(buf, p.get_raw_item());
|
ostd::range_put_all(buf, p.item);
|
||||||
}
|
}
|
||||||
if ((n + 1) < len) {
|
if ((n + 1) < len) {
|
||||||
if ((len > 2) || conj.empty()) {
|
if ((len > 2) || conj.empty()) {
|
||||||
|
@ -470,13 +471,13 @@ end:
|
||||||
ostd::string_range s = args[0].get_str();
|
ostd::string_range s = args[0].get_str();
|
||||||
ostd::string_range vals = args[1].get_str();
|
ostd::string_range vals = args[1].get_str();
|
||||||
char const *list = s.data();
|
char const *list = s.data();
|
||||||
util::list_parser p(cs, s);
|
cs_list_parse_state p{s};
|
||||||
for (cs_int i = 0; i < offset; ++i) {
|
for (cs_int i = 0; i < offset; ++i) {
|
||||||
if (!p.parse()) {
|
if (!list_parse(p, cs)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ostd::string_range quote = p.get_raw_item(true);
|
ostd::string_range quote = p.quoted_item;
|
||||||
char const *qend = !quote.empty() ? "e[quote.size()] : list;
|
char const *qend = !quote.empty() ? "e[quote.size()] : list;
|
||||||
cs_string buf;
|
cs_string buf;
|
||||||
if (qend > list) {
|
if (qend > list) {
|
||||||
|
@ -489,13 +490,13 @@ end:
|
||||||
buf += vals;
|
buf += vals;
|
||||||
}
|
}
|
||||||
for (cs_int i = 0; i < len; ++i) {
|
for (cs_int i = 0; i < len; ++i) {
|
||||||
if (!p.parse()) {
|
if (!list_parse(p, cs)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.skip();
|
list_find_item(p);
|
||||||
if (!p.get_input().empty()) {
|
if (!p.input.empty()) {
|
||||||
switch (p.get_input().front()) {
|
switch (p.input.front()) {
|
||||||
case ')':
|
case ')':
|
||||||
case ']':
|
case ']':
|
||||||
break;
|
break;
|
||||||
|
@ -503,7 +504,7 @@ end:
|
||||||
if (!buf.empty()) {
|
if (!buf.empty()) {
|
||||||
buf += ' ';
|
buf += ' ';
|
||||||
}
|
}
|
||||||
buf += p.get_input();
|
buf += p.input;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -545,14 +546,14 @@ static void cs_list_sort(
|
||||||
cs_vector<ListSortItem> items;
|
cs_vector<ListSortItem> items;
|
||||||
size_t total = 0;
|
size_t total = 0;
|
||||||
|
|
||||||
for (util::list_parser p(cs, list); p.parse();) {
|
for (cs_list_parse_state p{list}; list_parse(p, cs);) {
|
||||||
ListSortItem item = { p.get_raw_item(), p.get_raw_item(true) };
|
ListSortItem item = { p.item, p.quoted_item };
|
||||||
items.push_back(item);
|
items.push_back(item);
|
||||||
total += item.quote.size();
|
total += item.quote.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (items.empty()) {
|
if (items.empty()) {
|
||||||
res.set_str(cs_string{list});
|
res.set_str(list);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue