clean up parser a bit
parent
33c6479539
commit
73f770552c
141
src/cs_gen.cc
141
src/cs_gen.cc
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
11
src/cs_vm.hh
11
src/cs_vm.hh
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue