clean up parser a bit

master
Daniel Kolesa 2016-09-22 00:20:23 +02:00
parent 33c6479539
commit 73f770552c
2 changed files with 75 additions and 77 deletions

View File

@ -8,50 +8,11 @@
namespace cscript { namespace cscript {
static ostd::ConstCharRange cs_debug_line(
ostd::ConstCharRange p, ostd::ConstCharRange srcf, ostd::ConstCharRange srcs,
ostd::ConstCharRange fmt, ostd::CharRange buf
) {
if (srcs.empty()) {
return fmt;
}
ostd::Size num = 1;
ostd::ConstCharRange line(srcs);
for (;;) {
ostd::ConstCharRange end = ostd::find(line, '\n');
if (!end.empty()) {
line = ostd::slice_until(line, end);
}
if (&p[0] >= &line[0] && &p[0] <= &line[line.size()]) {
ostd::CharRange r(buf);
if (!srcf.empty()) {
ostd::format(r, "%s:%d: %s", srcf, num, fmt);
} else {
ostd::format(r, "%d: %s", num, fmt);
}
r.put('\0');
return buf.data(); /* trigger strlen */
}
if (end.empty()) {
break;
}
line = end;
line.pop_front();
++num;
}
return fmt;
}
template<typename ...A> template<typename ...A>
static void cs_error_line( static void cs_error_line(
GenState &gs, ostd::ConstCharRange p, ostd::ConstCharRange fmt, A &&...args GenState &gs, ostd::ConstCharRange fmt, A &&...args
) { ) {
ostd::Array<char, 256> buf; throw CsErrorException(gs.cs, fmt, ostd::forward<A>(args)...);
auto rfmt = cs_debug_line(
p, gs.src_file, gs.src_str, fmt,
ostd::CharRange(buf.data(), buf.size())
);
throw CsErrorException(gs.cs, rfmt, ostd::forward<A>(args)...);
} }
static ostd::ConstCharRange cs_parse_str(ostd::ConstCharRange str) { static ostd::ConstCharRange cs_parse_str(ostd::ConstCharRange str) {
@ -94,7 +55,7 @@ ostd::ConstCharRange GenState::get_str() {
done: done:
auto ret = ostd::ConstCharRange(beg, source); auto ret = ostd::ConstCharRange(beg, source);
if (current() != '\"') { if (current() != '\"') {
cs_error_line(*this, ln, "unfinished string '%s'", ln); cs_error_line(*this, "unfinished string '%s'", ln);
} }
next_char(); next_char();
return ret; return ret;
@ -111,13 +72,51 @@ CsString GenState::get_str_dup(bool unescape) {
return ostd::move(app.get()); return ostd::move(app.get());
} }
static inline void skipcomments(char const *&p) { ostd::ConstCharRange GenState::read_macro_name() {
char const *op = source;
char c = current();
if (!isalpha(c) && (c != '_')) {
return nullptr;
}
for (; isalnum(c) || (c == '_'); c = current()) {
next_char();
}
return ostd::ConstCharRange(op, source);
}
char GenState::skip_until(ostd::ConstCharRange chars) {
char c = current();
while (c && ostd::find(chars, c).empty()) {
next_char();
c = current();
}
return c;
}
char GenState::skip_until(char cf) {
char c = current();
while (c && (c != cf)) {
next_char();
c = current();
}
return c;
}
static bool cs_is_hspace(char c) {
return (c == ' ') || (c == '\t') || (c == '\r');
}
void GenState::skip_comments() {
for (;;) { for (;;) {
p += strspn(p, " \t\r"); for (char c = current(); cs_is_hspace(c); c = current()) {
if (p[0] != '/' || p[1] != '/') { next_char();
break; }
if ((current() != '/') || (current(1) != '/')) {
return;
}
while (current() != '\n') {
next_char();
} }
p += strcspn(p, "\n\0");
} }
} }
@ -596,7 +595,6 @@ done:
static bool compileblocksub(GenState &gs, int prevargs) { static bool compileblocksub(GenState &gs, int prevargs) {
CsString lookup; CsString lookup;
char const *op;
switch (gs.current()) { switch (gs.current()) {
case '(': case '(':
if (!compilearg(gs, CsValCany, prevargs)) { if (!compilearg(gs, CsValCany, prevargs)) {
@ -613,11 +611,7 @@ static bool compileblocksub(GenState &gs, int prevargs) {
lookup = gs.get_str_dup(); lookup = gs.get_str_dup();
goto lookupid; goto lookupid;
default: { default: {
op = gs.source; lookup = gs.read_macro_name();
while (isalnum(gs.current()) || gs.current() == '_') {
gs.next_char();
}
lookup = ostd::ConstCharRange(op, gs.source - op);
if (lookup.empty()) { if (lookup.empty()) {
return false; return false;
} }
@ -656,14 +650,12 @@ done:
} }
static void compileblockmain(GenState &gs, int wordtype, int prevargs) { static void compileblockmain(GenState &gs, int wordtype, int prevargs) {
char const *line = gs.source, *start = gs.source; char const *start = gs.source;
int concs = 0; int concs = 0;
for (int brak = 1; brak;) { for (int brak = 1; brak;) {
gs.source += strcspn(gs.source, "@\"/[]\0"); switch (gs.skip_until("@\"/[]")) {
char c = gs.current();
switch (c) {
case '\0': case '\0':
cs_error_line(gs, line, "missing \"]\""); cs_error_line(gs, "missing \"]\"");
return; return;
case '\"': case '\"':
gs.get_str(); gs.get_str();
@ -671,7 +663,7 @@ static void compileblockmain(GenState &gs, int wordtype, int prevargs) {
case '/': case '/':
gs.next_char(); gs.next_char();
if (gs.current() == '/') { if (gs.current() == '/') {
gs.source += strcspn(gs.source, "\n\0"); gs.skip_until('\n');
} }
break; break;
case '[': case '[':
@ -692,7 +684,7 @@ static void compileblockmain(GenState &gs, int wordtype, int prevargs) {
if (brak > level) { if (brak > level) {
continue; continue;
} else if (brak < level) { } else if (brak < level) {
cs_error_line(gs, line, "too many @s"); cs_error_line(gs, "too many @s");
return; return;
} }
if (!concs && prevargs >= MaxResults) { if (!concs && prevargs >= MaxResults) {
@ -817,7 +809,7 @@ static void compileblockmain(GenState &gs, int wordtype, int prevargs) {
static bool compilearg( static bool compilearg(
GenState &gs, int wordtype, int prevargs, CsString *word GenState &gs, int wordtype, int prevargs, CsString *word
) { ) {
skipcomments(gs.source); gs.skip_comments();
switch (gs.current()) { switch (gs.current()) {
case '\"': case '\"':
switch (wordtype) { switch (wordtype) {
@ -1309,16 +1301,15 @@ static void compile_and_or(
} }
static void compilestatements(GenState &gs, int rettype, int brak, int prevargs) { static void compilestatements(GenState &gs, int rettype, int brak, int prevargs) {
char const *line = gs.source;
CsString idname; CsString idname;
for (;;) { for (;;) {
skipcomments(gs.source); gs.skip_comments();
idname.clear(); idname.clear();
bool more = compilearg(gs, CsValWord, prevargs, &idname); bool more = compilearg(gs, CsValWord, prevargs, &idname);
if (!more) { if (!more) {
goto endstatement; goto endstatement;
} }
skipcomments(gs.source); gs.skip_comments();
if (gs.current() == '=') { if (gs.current() == '=') {
switch (gs.source[1]) { switch (gs.source[1]) {
case '/': case '/':
@ -1525,30 +1516,30 @@ endstatement:
if (more) { if (more) {
while (compilearg(gs, CsValPop)); while (compilearg(gs, CsValPop));
} }
gs.source += strcspn(gs.source, ")];/\n\0"); switch (gs.skip_until(")];/\n")) {
char c = gs.next_char();
switch (c) {
case '\0': case '\0':
if (c != brak) { if (gs.current() != brak) {
cs_error_line( cs_error_line(gs, "missing \"%c\"", char(brak));
gs, line, "missing \"%c\"", char(brak)
);
return; return;
} }
gs.source--;
return; return;
case ')': case ')':
case ']': case ']':
if (c == brak) { if (gs.current() == brak) {
gs.next_char();
return; return;
} }
cs_error_line(gs, line, "unexpected \"%c\"", c); cs_error_line(gs, "unexpected \"%c\"", gs.current());
return; return;
case '/': case '/':
gs.next_char();
if (gs.current() == '/') { if (gs.current() == '/') {
gs.source += strcspn(gs.source, "\n\0"); gs.skip_until('\n');
} }
goto endstatement; goto endstatement;
default:
gs.next_char();
break;
} }
} }
} }

View File

@ -218,9 +218,16 @@ struct GenState {
return *source++; return *source++;
} }
char current() { char current(int ahead = 0) {
return *source; return source[ahead];
} }
ostd::ConstCharRange read_macro_name();
char skip_until(ostd::ConstCharRange chars);
char skip_until(char cf);
void skip_comments();
}; };
CsString intstr(CsInt v); CsString intstr(CsInt v);