remove parselist
parent
a3c3b65251
commit
2260c1ec0a
151
cubescript.cc
151
cubescript.cc
|
@ -3801,93 +3801,6 @@ void cs_init_lib_base_loops(CsState &cs) {
|
|||
});
|
||||
}
|
||||
|
||||
static const char *liststart = nullptr, *listend = nullptr, *listquotestart = nullptr, *listquoteend = nullptr;
|
||||
|
||||
static inline void skiplist(const char *&p) {
|
||||
for (;;) {
|
||||
p += strspn(p, " \t\r\n");
|
||||
if (p[0] != '/' || p[1] != '/') break;
|
||||
p += strcspn(p, "\n\0");
|
||||
}
|
||||
}
|
||||
|
||||
static bool parselist(const char *&s, const char *&start = liststart, const char *&end = listend, const char *"estart = listquotestart, const char *"eend = listquoteend) {
|
||||
skiplist(s);
|
||||
switch (*s) {
|
||||
case '"':
|
||||
quotestart = s++;
|
||||
start = s;
|
||||
s = parsestring(s);
|
||||
end = s;
|
||||
if (*s == '"') s++;
|
||||
quoteend = s;
|
||||
break;
|
||||
case '(':
|
||||
case '[':
|
||||
quotestart = s;
|
||||
start = s + 1;
|
||||
for (int braktype = *s++, brak = 1;;) {
|
||||
s += strcspn(s, "\"/;()[]\0");
|
||||
int c = *s++;
|
||||
switch (c) {
|
||||
case '\0':
|
||||
s--;
|
||||
quoteend = end = s;
|
||||
return true;
|
||||
case '"':
|
||||
s = parsestring(s);
|
||||
if (*s == '"') s++;
|
||||
break;
|
||||
case '/':
|
||||
if (*s == '/') s += strcspn(s, "\n\0");
|
||||
break;
|
||||
case '(':
|
||||
case '[':
|
||||
if (c == braktype) brak++;
|
||||
break;
|
||||
case ')':
|
||||
if (braktype == '(' && --brak <= 0) goto endblock;
|
||||
break;
|
||||
case ']':
|
||||
if (braktype == '[' && --brak <= 0) goto endblock;
|
||||
break;
|
||||
}
|
||||
}
|
||||
endblock:
|
||||
end = s - 1;
|
||||
quoteend = s;
|
||||
break;
|
||||
case '\0':
|
||||
case ')':
|
||||
case ']':
|
||||
return false;
|
||||
default:
|
||||
quotestart = start = s;
|
||||
s = parseword(s);
|
||||
quoteend = end = s;
|
||||
break;
|
||||
}
|
||||
skiplist(s);
|
||||
if (*s == ';') s++;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline ostd::String listelem(const char *start, const char *end, const char *quotestart) {
|
||||
ostd::Size len = end - start;
|
||||
ostd::String s;
|
||||
s.reserve(len);
|
||||
if (*quotestart == '"') {
|
||||
auto writer = s.iter_cap();
|
||||
util::unescape_string(writer, ostd::ConstCharRange(start, end));
|
||||
writer.put('\0');
|
||||
} else {
|
||||
memcpy(s.data(), start, len);
|
||||
s[len] = '\0';
|
||||
}
|
||||
s.advance(len);
|
||||
return s;
|
||||
}
|
||||
|
||||
struct ListParser {
|
||||
ostd::ConstCharRange input;
|
||||
ostd::ConstCharRange quote = ostd::ConstCharRange();
|
||||
|
@ -4093,35 +4006,38 @@ void init_lib_list(CsState &cs) {
|
|||
if (!numargs)
|
||||
return;
|
||||
ostd::ConstCharRange str = args[0].get_str();
|
||||
const char *start = str.data(),
|
||||
*end = &str[str.size()],
|
||||
*qstart = "";
|
||||
ListParser p(str);
|
||||
p.item = str;
|
||||
for (int i = 1; i < numargs; ++i) {
|
||||
const char *list = start;
|
||||
p.input = str;
|
||||
int pos = args[i].get_int();
|
||||
for (; pos > 0; --pos)
|
||||
if (!parselist(list)) break;
|
||||
if (pos > 0 || !parselist(list, start, end, qstart))
|
||||
start = end = qstart = "";
|
||||
if (!p.parse()) break;
|
||||
if (pos > 0 || !p.parse())
|
||||
p.item = p.quote = ostd::ConstCharRange();
|
||||
}
|
||||
cs.result->set_str(listelem(start, end, qstart).disown());
|
||||
cs.result->set_str(p.element().disown());
|
||||
});
|
||||
|
||||
cs.add_command("sublist", "siiN", [](CsState &cs, const char *s,
|
||||
int *skip, int *count, int *numargs) {
|
||||
int offset = ostd::max(*skip, 0),
|
||||
len = (*numargs >= 3) ? ostd::max(*count, 0) : -1;
|
||||
ListParser p(s);
|
||||
for (int i = 0; i < offset; ++i)
|
||||
if (!parselist(s)) break;
|
||||
if (!p.parse()) break;
|
||||
if (len < 0) {
|
||||
if (offset > 0)
|
||||
skiplist(s);
|
||||
cs.result->set_str(cs_dup_ostr(s));
|
||||
p.skip();
|
||||
cs.result->set_str(cs_dup_ostr(p.input));
|
||||
return;
|
||||
}
|
||||
const char *list = s, *start, *end, *qstart, *qend = s;
|
||||
if (len > 0 && parselist(s, start, end, list, qend))
|
||||
while (--len > 0 && parselist(s, start, end, qstart, qend));
|
||||
|
||||
const char *list = p.input.data();
|
||||
p.quote = ostd::ConstCharRange();
|
||||
if (len > 0 && p.parse())
|
||||
while (--len > 0 && p.parse());
|
||||
const char *qend = !p.quote.empty() ? &p.quote[p.quote.size()] : list;
|
||||
cs.result->set_str(cs_dup_ostr(ostd::ConstCharRange(list, qend - list)));
|
||||
});
|
||||
|
||||
|
@ -4390,35 +4306,36 @@ found:
|
|||
int *count) {
|
||||
int offset = ostd::max(*skip, 0);
|
||||
int len = ostd::max(*count, 0);
|
||||
const char *list = s, *start, *end, *qstart, *qend = s;
|
||||
const char *list = s;
|
||||
ListParser p(s);
|
||||
for (int i = 0; i < offset; ++i)
|
||||
if (!parselist(s, start, end, qstart, qend))
|
||||
if (!p.parse())
|
||||
break;
|
||||
ostd::Vector<char> p;
|
||||
const char *qend = !p.quote.empty() ? &p.quote[p.quote.size()] : list;
|
||||
ostd::Vector<char> buf;
|
||||
if (qend > list)
|
||||
p.push_n(list, qend - list);
|
||||
buf.push_n(list, qend - list);
|
||||
if (*vals) {
|
||||
if (!p.empty())
|
||||
p.push(' ');
|
||||
p.push_n(vals, strlen(vals));
|
||||
if (!buf.empty())
|
||||
buf.push(' ');
|
||||
buf.push_n(vals, strlen(vals));
|
||||
}
|
||||
for (int i = 0; i < len; ++i)
|
||||
if (!parselist(s))
|
||||
if (!p.parse())
|
||||
break;
|
||||
skiplist(s);
|
||||
switch (*s) {
|
||||
case '\0':
|
||||
p.skip();
|
||||
if (!p.input.empty()) switch (p.input.front()) {
|
||||
case ')':
|
||||
case ']':
|
||||
break;
|
||||
default:
|
||||
if (!p.empty())
|
||||
p.push(' ');
|
||||
p.push_n(s, strlen(s));
|
||||
if (!buf.empty())
|
||||
buf.push(' ');
|
||||
buf.push_n(p.input.data(), p.input.size());
|
||||
break;
|
||||
}
|
||||
p.push('\0');
|
||||
cs.result->set_str(p.disown());
|
||||
buf.push('\0');
|
||||
cs.result->set_str(buf.disown());
|
||||
});
|
||||
|
||||
cs_init_lib_list_sort(cs);
|
||||
|
|
Loading…
Reference in New Issue