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 CsSharedState;
|
||||
struct GenState;
|
||||
|
||||
enum class CsLoopState {
|
||||
Normal = 0, Break, Continue
|
||||
|
@ -364,6 +365,7 @@ enum class CsLoopState {
|
|||
|
||||
struct OSTD_EXPORT CsState {
|
||||
friend struct CsErrorException;
|
||||
friend struct GenState;
|
||||
|
||||
CsSharedState *p_state;
|
||||
CsIdentLink *p_callstack = nullptr;
|
||||
|
@ -558,6 +560,7 @@ struct OSTD_EXPORT CsState {
|
|||
private:
|
||||
CsIdent *add_ident(CsIdent *id);
|
||||
|
||||
GenState *p_pstate = nullptr;
|
||||
int p_inloop = 0;
|
||||
|
||||
CsAllocCb p_allocf;
|
||||
|
|
|
@ -8,30 +8,6 @@
|
|||
|
||||
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) {
|
||||
while (!str.empty()) {
|
||||
switch (*str) {
|
||||
|
@ -93,7 +69,7 @@ ostd::ConstCharRange GenState::get_str() {
|
|||
done:
|
||||
auto ret = ostd::slice_until(beg, source);
|
||||
if (current() != '\"') {
|
||||
cs_error_line(*this, "unfinished string '%s'", ln);
|
||||
throw CsErrorException(cs, "unfinished string '%s'", ln);
|
||||
}
|
||||
next_char();
|
||||
return ret;
|
||||
|
@ -152,7 +128,7 @@ void GenState::skip_comments() {
|
|||
if (current() == '\\') {
|
||||
char c = current(1);
|
||||
if ((c != '\r') && (c != '\n')) {
|
||||
cs_error_line(*this, "invalid line break");
|
||||
throw CsErrorException(cs, "invalid line break");
|
||||
}
|
||||
/* skip backslash */
|
||||
next_char();
|
||||
|
@ -675,7 +651,7 @@ static void compileblockmain(GenState &gs, int wordtype, int prevargs) {
|
|||
for (int brak = 1; brak;) {
|
||||
switch (gs.skip_until("@\"/[]")) {
|
||||
case '\0':
|
||||
cs_error_line(gs, "missing \"]\"");
|
||||
throw CsErrorException(gs.cs, "missing \"]\"");
|
||||
return;
|
||||
case '\"':
|
||||
gs.get_str();
|
||||
|
@ -704,7 +680,7 @@ static void compileblockmain(GenState &gs, int wordtype, int prevargs) {
|
|||
if (brak > level) {
|
||||
continue;
|
||||
} else if (brak < level) {
|
||||
cs_error_line(gs, "too many @s");
|
||||
throw CsErrorException(gs.cs, "too many @s");
|
||||
return;
|
||||
}
|
||||
if (!concs && prevargs >= MaxResults) {
|
||||
|
@ -1554,7 +1530,7 @@ endstatement:
|
|||
switch (gs.skip_until(")];/\n")) {
|
||||
case '\0':
|
||||
if (gs.current() != brak) {
|
||||
cs_error_line(gs, "missing \"%c\"", char(brak));
|
||||
throw CsErrorException(gs.cs, "missing \"%c\"", char(brak));
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
@ -1564,7 +1540,7 @@ endstatement:
|
|||
gs.next_char();
|
||||
return;
|
||||
}
|
||||
cs_error_line(gs, "unexpected \"%c\"", gs.current());
|
||||
throw CsErrorException(gs.cs, "unexpected \"%c\"", gs.current());
|
||||
return;
|
||||
case '/':
|
||||
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)) {
|
||||
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());
|
||||
return ostd::ConstCharRange(cs.p_errbuf, msg.size());
|
||||
}
|
||||
|
@ -185,6 +199,7 @@ static inline ostd::Uint32 *forcecode(CsState &cs, CsValue &v) {
|
|||
GenState gs(cs);
|
||||
gs.code.reserve(64);
|
||||
gs.gen_main(v.get_str());
|
||||
gs.done();
|
||||
v.set_code(reinterpret_cast<CsBytecode *>(gs.code.release() + 1));
|
||||
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);
|
||||
break;
|
||||
}
|
||||
gs.done();
|
||||
arg.set_code(
|
||||
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);
|
||||
gs.code.reserve(64);
|
||||
gs.gen_main(s);
|
||||
gs.done();
|
||||
arg.set_code(reinterpret_cast<CsBytecode *>(
|
||||
gs.code.release() + 1
|
||||
));
|
||||
|
@ -1587,8 +1604,8 @@ static void cs_run(
|
|||
GenState gs(cs);
|
||||
gs.src_name = file;
|
||||
gs.code.reserve(64);
|
||||
/* FIXME range */
|
||||
gs.gen_main(code.data(), CsValAny);
|
||||
gs.gen_main(code, CsValAny);
|
||||
gs.done();
|
||||
runcode(cs, gs.code.data() + 1, ret);
|
||||
if (int(gs.code[0]) >= 0x100) {
|
||||
gs.code.release();
|
||||
|
|
21
src/cs_vm.hh
21
src/cs_vm.hh
|
@ -111,6 +111,8 @@ constexpr ostd::Size CsTypeStorageSize =
|
|||
|
||||
struct GenState {
|
||||
CsState &cs;
|
||||
GenState *prevps;
|
||||
bool parsing = true;
|
||||
CsVector<ostd::Uint32> code;
|
||||
ostd::ConstCharRange source;
|
||||
int current_line;
|
||||
|
@ -118,8 +120,23 @@ struct GenState {
|
|||
|
||||
GenState() = delete;
|
||||
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();
|
||||
CsString get_str_dup(bool unescape = true);
|
||||
|
|
Loading…
Reference in New Issue