forked from OctaForge/libcubescript
simplify parser error handling (and allow for wider usage of line infos)
parent
cd515a4cff
commit
5d70e2c80f
|
@ -357,6 +357,7 @@ private:
|
||||||
|
|
||||||
struct CsErrorException;
|
struct CsErrorException;
|
||||||
struct CsSharedState;
|
struct CsSharedState;
|
||||||
|
struct GenState;
|
||||||
|
|
||||||
enum class CsLoopState {
|
enum class CsLoopState {
|
||||||
Normal = 0, Break, Continue
|
Normal = 0, Break, Continue
|
||||||
|
@ -364,6 +365,7 @@ enum class CsLoopState {
|
||||||
|
|
||||||
struct OSTD_EXPORT CsState {
|
struct OSTD_EXPORT CsState {
|
||||||
friend struct CsErrorException;
|
friend struct CsErrorException;
|
||||||
|
friend struct GenState;
|
||||||
|
|
||||||
CsSharedState *p_state;
|
CsSharedState *p_state;
|
||||||
CsIdentLink *p_callstack = nullptr;
|
CsIdentLink *p_callstack = nullptr;
|
||||||
|
@ -558,6 +560,7 @@ struct OSTD_EXPORT CsState {
|
||||||
private:
|
private:
|
||||||
CsIdent *add_ident(CsIdent *id);
|
CsIdent *add_ident(CsIdent *id);
|
||||||
|
|
||||||
|
GenState *p_pstate = nullptr;
|
||||||
int p_inloop = 0;
|
int p_inloop = 0;
|
||||||
|
|
||||||
CsAllocCb p_allocf;
|
CsAllocCb p_allocf;
|
||||||
|
|
|
@ -8,30 +8,6 @@
|
||||||
|
|
||||||
namespace cscript {
|
namespace cscript {
|
||||||
|
|
||||||
static ostd::ConstCharRange cs_get_debug_fmt(
|
|
||||||
GenState &gs, ostd::ConstCharRange fmt, ostd::CharRange buf
|
|
||||||
) {
|
|
||||||
ostd::CharRange r = buf;
|
|
||||||
if (!gs.src_name.empty()) {
|
|
||||||
ostd::format(r, "%s:%d: %s", gs.src_name, gs.current_line, fmt);
|
|
||||||
} else {
|
|
||||||
ostd::format(r, "%d: %s", gs.current_line, fmt);
|
|
||||||
}
|
|
||||||
r.put('\0');
|
|
||||||
return buf.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ...A>
|
|
||||||
static void cs_error_line(
|
|
||||||
GenState &gs, ostd::ConstCharRange fmt, A &&...args
|
|
||||||
) {
|
|
||||||
ostd::Array<char, 256> buf;
|
|
||||||
auto rfmt = cs_get_debug_fmt(
|
|
||||||
gs, 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) {
|
||||||
while (!str.empty()) {
|
while (!str.empty()) {
|
||||||
switch (*str) {
|
switch (*str) {
|
||||||
|
@ -93,7 +69,7 @@ ostd::ConstCharRange GenState::get_str() {
|
||||||
done:
|
done:
|
||||||
auto ret = ostd::slice_until(beg, source);
|
auto ret = ostd::slice_until(beg, source);
|
||||||
if (current() != '\"') {
|
if (current() != '\"') {
|
||||||
cs_error_line(*this, "unfinished string '%s'", ln);
|
throw CsErrorException(cs, "unfinished string '%s'", ln);
|
||||||
}
|
}
|
||||||
next_char();
|
next_char();
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -152,7 +128,7 @@ void GenState::skip_comments() {
|
||||||
if (current() == '\\') {
|
if (current() == '\\') {
|
||||||
char c = current(1);
|
char c = current(1);
|
||||||
if ((c != '\r') && (c != '\n')) {
|
if ((c != '\r') && (c != '\n')) {
|
||||||
cs_error_line(*this, "invalid line break");
|
throw CsErrorException(cs, "invalid line break");
|
||||||
}
|
}
|
||||||
/* skip backslash */
|
/* skip backslash */
|
||||||
next_char();
|
next_char();
|
||||||
|
@ -675,7 +651,7 @@ static void compileblockmain(GenState &gs, int wordtype, int prevargs) {
|
||||||
for (int brak = 1; brak;) {
|
for (int brak = 1; brak;) {
|
||||||
switch (gs.skip_until("@\"/[]")) {
|
switch (gs.skip_until("@\"/[]")) {
|
||||||
case '\0':
|
case '\0':
|
||||||
cs_error_line(gs, "missing \"]\"");
|
throw CsErrorException(gs.cs, "missing \"]\"");
|
||||||
return;
|
return;
|
||||||
case '\"':
|
case '\"':
|
||||||
gs.get_str();
|
gs.get_str();
|
||||||
|
@ -704,7 +680,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, "too many @s");
|
throw CsErrorException(gs.cs, "too many @s");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!concs && prevargs >= MaxResults) {
|
if (!concs && prevargs >= MaxResults) {
|
||||||
|
@ -1554,7 +1530,7 @@ endstatement:
|
||||||
switch (gs.skip_until(")];/\n")) {
|
switch (gs.skip_until(")];/\n")) {
|
||||||
case '\0':
|
case '\0':
|
||||||
if (gs.current() != brak) {
|
if (gs.current() != brak) {
|
||||||
cs_error_line(gs, "missing \"%c\"", char(brak));
|
throw CsErrorException(gs.cs, "missing \"%c\"", char(brak));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -1564,7 +1540,7 @@ endstatement:
|
||||||
gs.next_char();
|
gs.next_char();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cs_error_line(gs, "unexpected \"%c\"", gs.current());
|
throw CsErrorException(gs.cs, "unexpected \"%c\"", gs.current());
|
||||||
return;
|
return;
|
||||||
case '/':
|
case '/':
|
||||||
gs.next_char();
|
gs.next_char();
|
||||||
|
|
21
src/cs_vm.cc
21
src/cs_vm.cc
|
@ -112,6 +112,20 @@ ostd::ConstCharRange CsErrorException::save_msg(
|
||||||
if (msg.size() > sizeof(cs.p_errbuf)) {
|
if (msg.size() > sizeof(cs.p_errbuf)) {
|
||||||
msg = msg.slice(0, sizeof(cs.p_errbuf));
|
msg = msg.slice(0, sizeof(cs.p_errbuf));
|
||||||
}
|
}
|
||||||
|
GenState *gs = cs.p_pstate;
|
||||||
|
if (gs) {
|
||||||
|
/* we can attach line number */
|
||||||
|
ostd::CharRange r(cs.p_errbuf, sizeof(cs.p_errbuf));
|
||||||
|
ostd::Ptrdiff sz = -1;
|
||||||
|
if (!gs->src_name.empty()) {
|
||||||
|
sz = ostd::format(r, "%s:%d: %s", gs->src_name, gs->current_line, msg);
|
||||||
|
} else {
|
||||||
|
sz = ostd::format(r, "%d: %s", gs->current_line, msg);
|
||||||
|
}
|
||||||
|
if (sz > 0) {
|
||||||
|
return ostd::ConstCharRange(cs.p_errbuf, sz);
|
||||||
|
}
|
||||||
|
}
|
||||||
memcpy(cs.p_errbuf, msg.data(), msg.size());
|
memcpy(cs.p_errbuf, msg.data(), msg.size());
|
||||||
return ostd::ConstCharRange(cs.p_errbuf, msg.size());
|
return ostd::ConstCharRange(cs.p_errbuf, msg.size());
|
||||||
}
|
}
|
||||||
|
@ -185,6 +199,7 @@ static inline ostd::Uint32 *forcecode(CsState &cs, CsValue &v) {
|
||||||
GenState gs(cs);
|
GenState gs(cs);
|
||||||
gs.code.reserve(64);
|
gs.code.reserve(64);
|
||||||
gs.gen_main(v.get_str());
|
gs.gen_main(v.get_str());
|
||||||
|
gs.done();
|
||||||
v.set_code(reinterpret_cast<CsBytecode *>(gs.code.release() + 1));
|
v.set_code(reinterpret_cast<CsBytecode *>(gs.code.release() + 1));
|
||||||
code = reinterpret_cast<ostd::Uint32 *>(v.get_code());
|
code = reinterpret_cast<ostd::Uint32 *>(v.get_code());
|
||||||
}
|
}
|
||||||
|
@ -895,6 +910,7 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) {
|
||||||
gs.code.push(CsCodeExit);
|
gs.code.push(CsCodeExit);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
gs.done();
|
||||||
arg.set_code(
|
arg.set_code(
|
||||||
reinterpret_cast<CsBytecode *>(gs.code.release() + 1)
|
reinterpret_cast<CsBytecode *>(gs.code.release() + 1)
|
||||||
);
|
);
|
||||||
|
@ -911,6 +927,7 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) {
|
||||||
GenState gs(cs);
|
GenState gs(cs);
|
||||||
gs.code.reserve(64);
|
gs.code.reserve(64);
|
||||||
gs.gen_main(s);
|
gs.gen_main(s);
|
||||||
|
gs.done();
|
||||||
arg.set_code(reinterpret_cast<CsBytecode *>(
|
arg.set_code(reinterpret_cast<CsBytecode *>(
|
||||||
gs.code.release() + 1
|
gs.code.release() + 1
|
||||||
));
|
));
|
||||||
|
@ -1587,8 +1604,8 @@ static void cs_run(
|
||||||
GenState gs(cs);
|
GenState gs(cs);
|
||||||
gs.src_name = file;
|
gs.src_name = file;
|
||||||
gs.code.reserve(64);
|
gs.code.reserve(64);
|
||||||
/* FIXME range */
|
gs.gen_main(code, CsValAny);
|
||||||
gs.gen_main(code.data(), CsValAny);
|
gs.done();
|
||||||
runcode(cs, gs.code.data() + 1, ret);
|
runcode(cs, gs.code.data() + 1, ret);
|
||||||
if (int(gs.code[0]) >= 0x100) {
|
if (int(gs.code[0]) >= 0x100) {
|
||||||
gs.code.release();
|
gs.code.release();
|
||||||
|
|
21
src/cs_vm.hh
21
src/cs_vm.hh
|
@ -111,6 +111,8 @@ constexpr ostd::Size CsTypeStorageSize =
|
||||||
|
|
||||||
struct GenState {
|
struct GenState {
|
||||||
CsState &cs;
|
CsState &cs;
|
||||||
|
GenState *prevps;
|
||||||
|
bool parsing = true;
|
||||||
CsVector<ostd::Uint32> code;
|
CsVector<ostd::Uint32> code;
|
||||||
ostd::ConstCharRange source;
|
ostd::ConstCharRange source;
|
||||||
int current_line;
|
int current_line;
|
||||||
|
@ -118,8 +120,23 @@ struct GenState {
|
||||||
|
|
||||||
GenState() = delete;
|
GenState() = delete;
|
||||||
GenState(CsState &csr):
|
GenState(CsState &csr):
|
||||||
cs(csr), code(), source(nullptr), current_line(1), src_name()
|
cs(csr), prevps(csr.p_pstate), code(),
|
||||||
{}
|
source(nullptr), current_line(1), src_name()
|
||||||
|
{
|
||||||
|
csr.p_pstate = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~GenState() {
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
|
||||||
|
void done() {
|
||||||
|
if (!parsing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cs.p_pstate = prevps;
|
||||||
|
parsing = false;
|
||||||
|
}
|
||||||
|
|
||||||
ostd::ConstCharRange get_str();
|
ostd::ConstCharRange get_str();
|
||||||
CsString get_str_dup(bool unescape = true);
|
CsString get_str_dup(bool unescape = true);
|
||||||
|
|
Loading…
Reference in New Issue