From 5d70e2c80f60c5a1339472889f26031d0691f4ac Mon Sep 17 00:00:00 2001 From: q66 Date: Thu, 29 Sep 2016 21:21:21 +0200 Subject: [PATCH] simplify parser error handling (and allow for wider usage of line infos) --- include/cubescript/cubescript.hh | 3 +++ src/cs_gen.cc | 36 ++++++-------------------------- src/cs_vm.cc | 21 +++++++++++++++++-- src/cs_vm.hh | 21 +++++++++++++++++-- 4 files changed, 47 insertions(+), 34 deletions(-) diff --git a/include/cubescript/cubescript.hh b/include/cubescript/cubescript.hh index 97b170b0..3dd12b9b 100644 --- a/include/cubescript/cubescript.hh +++ b/include/cubescript/cubescript.hh @@ -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; diff --git a/src/cs_gen.cc b/src/cs_gen.cc index 698d27b7..4223436b 100644 --- a/src/cs_gen.cc +++ b/src/cs_gen.cc @@ -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 -static void cs_error_line( - GenState &gs, ostd::ConstCharRange fmt, A &&...args -) { - ostd::Array buf; - auto rfmt = cs_get_debug_fmt( - gs, fmt, ostd::CharRange(buf.data(), buf.size()) - ); - throw CsErrorException(gs.cs, rfmt, ostd::forward(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(); diff --git a/src/cs_vm.cc b/src/cs_vm.cc index 394fe830..003ecd9a 100644 --- a/src/cs_vm.cc +++ b/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(gs.code.release() + 1)); code = reinterpret_cast(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(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( 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(); diff --git a/src/cs_vm.hh b/src/cs_vm.hh index 8f533291..b53ca106 100644 --- a/src/cs_vm.hh +++ b/src/cs_vm.hh @@ -111,6 +111,8 @@ constexpr ostd::Size CsTypeStorageSize = struct GenState { CsState &cs; + GenState *prevps; + bool parsing = true; CsVector 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);