forked from OctaForge/libcubescript
130 lines
3.7 KiB
C++
130 lines
3.7 KiB
C++
#ifndef LIB_LIST_HH
|
|
#define LIB_LIST_HH
|
|
|
|
#include "cubescript.hh"
|
|
|
|
namespace cscript {
|
|
|
|
ostd::ConstCharRange cs_parse_str(ostd::ConstCharRange str);
|
|
char const *parseword(char const *p);
|
|
|
|
struct ListParser {
|
|
ostd::ConstCharRange input;
|
|
ostd::ConstCharRange quote = ostd::ConstCharRange();
|
|
ostd::ConstCharRange item = ostd::ConstCharRange();
|
|
|
|
ListParser() = delete;
|
|
ListParser(ostd::ConstCharRange src): input(src) {}
|
|
|
|
void skip() {
|
|
for (;;) {
|
|
while (!input.empty()) {
|
|
char c = input.front();
|
|
if ((c == ' ') || (c == '\t') || (c == '\r') || (c == '\n'))
|
|
input.pop_front();
|
|
else
|
|
break;
|
|
}
|
|
if ((input.size() < 2) || (input[0] != '/') || (input[1] != '/'))
|
|
break;
|
|
input = ostd::find(input, '\n');
|
|
}
|
|
}
|
|
|
|
bool parse() {
|
|
skip();
|
|
if (input.empty())
|
|
return false;
|
|
switch (input.front()) {
|
|
case '"':
|
|
quote = input;
|
|
input.pop_front();
|
|
item = input;
|
|
input = cs_parse_str(input);
|
|
item = ostd::slice_until(item, input);
|
|
if (!input.empty() && (input.front() == '"'))
|
|
input.pop_front();
|
|
quote = ostd::slice_until(quote, input);
|
|
break;
|
|
case '(':
|
|
case '[': {
|
|
quote = input;
|
|
input.pop_front();
|
|
item = input;
|
|
char btype = quote.front();
|
|
int brak = 1;
|
|
for (;;) {
|
|
input = ostd::find_one_of(input,
|
|
ostd::ConstCharRange("\"/;()[]"));
|
|
if (input.empty())
|
|
return true;
|
|
char c = input.front();
|
|
input.pop_front();
|
|
switch (c) {
|
|
case '"':
|
|
input = cs_parse_str(input);
|
|
if (!input.empty() && (input.front() == '"'))
|
|
input.pop_front();
|
|
break;
|
|
case '/':
|
|
if (!input.empty() && (input.front() == '/'))
|
|
input = ostd::find(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:
|
|
item = ostd::slice_until(item, input);
|
|
item.pop_back();
|
|
quote = ostd::slice_until(quote, input);
|
|
break;
|
|
}
|
|
case ')':
|
|
case ']':
|
|
return false;
|
|
default: {
|
|
char const *e = parseword(input.data());
|
|
item = input;
|
|
input.pop_front_n(e - input.data());
|
|
item = ostd::slice_until(item, input);
|
|
quote = item;
|
|
break;
|
|
}
|
|
}
|
|
skip();
|
|
if (!input.empty() && (input.front() == ';'))
|
|
input.pop_front();
|
|
return true;
|
|
}
|
|
|
|
ostd::String element() {
|
|
ostd::String s;
|
|
s.reserve(item.size());
|
|
if (!quote.empty() && (quote.front() == '"')) {
|
|
auto writer = s.iter_cap();
|
|
util::unescape_string(writer, item);
|
|
writer.put('\0');
|
|
} else {
|
|
memcpy(s.data(), item.data(), item.size());
|
|
s[item.size()] = '\0';
|
|
}
|
|
s.advance(item.size());
|
|
return s;
|
|
}
|
|
};
|
|
|
|
} /*namespace cscript */
|
|
|
|
#endif
|