more parser cleanups

master
Daniel Kolesa 2016-09-20 22:24:56 +02:00
parent 6f706dea86
commit 43e272c7e0
1 changed files with 27 additions and 40 deletions

View File

@ -54,24 +54,6 @@ static void cs_error_line(
throw CsErrorException(gs.cs, rfmt, ostd::forward<A>(args)...); throw CsErrorException(gs.cs, rfmt, ostd::forward<A>(args)...);
} }
static char const *parsestring(char const *p) {
while (*p) {
switch (*p) {
case '\r':
case '\n':
case '\"':
return p;
case '^':
if (*++p) {
break;
}
return p;
}
++p;
}
return p;
}
static ostd::ConstCharRange cs_parse_str(ostd::ConstCharRange str) { static ostd::ConstCharRange cs_parse_str(ostd::ConstCharRange str) {
while (!str.empty()) { while (!str.empty()) {
switch (*str) { switch (*str) {
@ -93,7 +75,22 @@ static ostd::ConstCharRange cs_parse_str(ostd::ConstCharRange str) {
ostd::ConstCharRange GenState::get_str() { ostd::ConstCharRange GenState::get_str() {
char const *beg = source + 1; char const *beg = source + 1;
source = parsestring(beg); source = beg;
for (; current(); next_char()) {
switch (current()) {
case '\r':
case '\n':
case '\"':
goto done;
case '^':
next_char();
if (current()) {
break;
}
goto done;
}
}
done:
auto ret = ostd::ConstCharRange(beg, source); auto ret = ostd::ConstCharRange(beg, source);
if (current() == '\"') { if (current() == '\"') {
next_char(); next_char();
@ -425,25 +422,19 @@ static inline char const *compileblock(
} }
static inline void compileunescapestr(GenState &gs, bool macro = false) { static inline void compileunescapestr(GenState &gs, bool macro = false) {
gs.next_char(); auto str = gs.get_str();
char const *end = parsestring(gs.source);
gs.code.push(macro ? CsCodeMacro : (CsCodeVal | CsRetString)); gs.code.push(macro ? CsCodeMacro : (CsCodeVal | CsRetString));
gs.code.reserve( gs.code.reserve(
gs.code.size() + (end - gs.source) / sizeof(ostd::Uint32) + 1 gs.code.size() + str.size() / sizeof(ostd::Uint32) + 1
); );
char *buf = reinterpret_cast<char *>(&gs.code[gs.code.size()]); char *buf = reinterpret_cast<char *>(&gs.code[gs.code.size()]);
auto writer = ostd::CharRange( auto writer = ostd::CharRange(
buf, (gs.code.capacity() - gs.code.size()) * sizeof(ostd::Uint32) buf, (gs.code.capacity() - gs.code.size()) * sizeof(ostd::Uint32)
); );
ostd::Size len = util::unescape_string( ostd::Size len = util::unescape_string(writer, str);
writer, ostd::ConstCharRange(gs.source, end)
);
writer.put('\0');
memset(&buf[len], 0, sizeof(ostd::Uint32) - len % sizeof(ostd::Uint32)); memset(&buf[len], 0, sizeof(ostd::Uint32) - len % sizeof(ostd::Uint32));
gs.code.back() |= len << 8; gs.code.back() |= len << 8;
gs.code.advance(len / sizeof(ostd::Uint32) + 1); gs.code.advance(len / sizeof(ostd::Uint32) + 1);
gs.source = end;
if (*gs.source == '\"') gs.next_char();
} }
static bool compilearg( static bool compilearg(
@ -827,29 +818,30 @@ static void compileblockmain(GenState &gs, int wordtype, int prevargs) {
int concs = 0; int concs = 0;
for (int brak = 1; brak;) { for (int brak = 1; brak;) {
gs.source += strcspn(gs.source, "@\"/[]\0"); gs.source += strcspn(gs.source, "@\"/[]\0");
char c = gs.next_char(); char c = gs.current();
switch (c) { switch (c) {
case '\0': case '\0':
cs_error_line(gs, line, "missing \"]\""); cs_error_line(gs, line, "missing \"]\"");
return; return;
case '\"': case '\"':
gs.source = parsestring(gs.source); gs.get_str();
if (gs.current() == '\"') {
gs.next_char();
}
break; break;
case '/': case '/':
gs.next_char();
if (gs.current() == '/') { if (gs.current() == '/') {
gs.source += strcspn(gs.source, "\n\0"); gs.source += strcspn(gs.source, "\n\0");
} }
break; break;
case '[': case '[':
gs.next_char();
brak++; brak++;
break; break;
case ']': case ']':
gs.next_char();
brak--; brak--;
break; break;
case '@': { case '@': {
gs.next_char();
char const *esc = gs.source; char const *esc = gs.source;
while (gs.current() == '@') { while (gs.current() == '@') {
gs.next_char(); gs.next_char();
@ -988,10 +980,7 @@ static bool compilearg(
case '\"': case '\"':
switch (wordtype) { switch (wordtype) {
case CsValPop: case CsValPop:
gs.source = parsestring(gs.source + 1); gs.get_str();
if (gs.current() == '\"') {
gs.next_char();
}
break; break;
case CsValCond: { case CsValCond: {
auto s = gs.get_str_dup(); auto s = gs.get_str_dup();
@ -1072,9 +1061,7 @@ static bool compilearg(
default: default:
switch (wordtype) { switch (wordtype) {
case CsValPop: { case CsValPop: {
char const *s = gs.source; return !gs.get_word().empty();
gs.source = parseword(gs.source);
return gs.source != s;
} }
case CsValCond: { case CsValCond: {
auto s = gs.get_word(); auto s = gs.get_word();