⚡ optimize error handling in json module
This commit is contained in:
parent
135665a5df
commit
bd3ae8c440
|
@ -37,6 +37,8 @@ std::string get_content(token_type type) {
|
||||||
case token_type::tok_id: return "identifier";
|
case token_type::tok_id: return "identifier";
|
||||||
case token_type::tok_bool: return "boolean";
|
case token_type::tok_bool: return "boolean";
|
||||||
}
|
}
|
||||||
|
// unreachable
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
struct token {
|
struct token {
|
||||||
|
@ -46,7 +48,6 @@ struct token {
|
||||||
|
|
||||||
class json {
|
class json {
|
||||||
private:
|
private:
|
||||||
usize parse_error = 0;
|
|
||||||
std::string text = "";
|
std::string text = "";
|
||||||
usize line = 1;
|
usize line = 1;
|
||||||
usize ptr = 0;
|
usize ptr = 0;
|
||||||
|
@ -77,11 +78,16 @@ private:
|
||||||
var vector_object_generate(gc*);
|
var vector_object_generate(gc*);
|
||||||
void hash_member(nas_hash&, gc*);
|
void hash_member(nas_hash&, gc*);
|
||||||
var hash_object_generate(gc*);
|
var hash_object_generate(gc*);
|
||||||
|
void check_eof();
|
||||||
|
static std::string& error_info() {
|
||||||
|
static std::string info = "";
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::string stringify(var&);
|
std::string stringify(var&);
|
||||||
var parse(const std::string&, gc*);
|
var parse(const std::string&, gc*);
|
||||||
bool has_error() const { return parse_error; }
|
static const std::string& get_error() { return error_info(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string json::var_generate(var& value) {
|
std::string json::var_generate(var& value) {
|
||||||
|
@ -152,6 +158,11 @@ void json::next() {
|
||||||
while(ptr<text.length() && !check(text[ptr])) {
|
while(ptr<text.length() && !check(text[ptr])) {
|
||||||
if (text[ptr]=='\n') {
|
if (text[ptr]=='\n') {
|
||||||
++line;
|
++line;
|
||||||
|
} else if (text[ptr]!=' ' && text[ptr]!='\t') {
|
||||||
|
error_info() += "json::parse: line " + std::to_string(line);
|
||||||
|
error_info() += ": invalid character `";
|
||||||
|
error_info() += text[ptr];
|
||||||
|
error_info() += "`\n";
|
||||||
}
|
}
|
||||||
++ptr;
|
++ptr;
|
||||||
}
|
}
|
||||||
|
@ -216,10 +227,9 @@ void json::next() {
|
||||||
|
|
||||||
void json::match(token_type type) {
|
void json::match(token_type type) {
|
||||||
if (this_token.type!=type) {
|
if (this_token.type!=type) {
|
||||||
std::cerr << "json::parse: line " << line << ": expect ";
|
error_info() += "json::parse: line " + std::to_string(line);
|
||||||
std::cerr << get_content(type) << " but get `";
|
error_info() += ": expect " + get_content(type) + " but get `";
|
||||||
std::cerr << this_token.content << "`.\n";
|
error_info() += this_token.content + "`.\n";
|
||||||
++parse_error;
|
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
return;
|
return;
|
||||||
|
@ -292,14 +302,28 @@ var json::hash_object_generate(gc* ngc) {
|
||||||
return hash_object;
|
return hash_object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void json::check_eof() {
|
||||||
|
next();
|
||||||
|
if (this_token.type==token_type::tok_eof) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (this_token.type!=token_type::tok_eof) {
|
||||||
|
error_info() += "json::parse: line " + std::to_string(line);
|
||||||
|
error_info() += ": expect " + get_content(token_type::tok_eof);
|
||||||
|
error_info() += " but get `" + this_token.content + "`.\n";
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var json::parse(const std::string& input, gc* ngc) {
|
var json::parse(const std::string& input, gc* ngc) {
|
||||||
usize parse_error = 0;
|
usize parse_error = 0;
|
||||||
usize line = 1;
|
usize line = 1;
|
||||||
usize ptr = 0;
|
usize ptr = 0;
|
||||||
this_token = {token_type::tok_eof, ""};
|
this_token = {token_type::tok_eof, ""};
|
||||||
|
error_info() = "";
|
||||||
|
|
||||||
if (input.empty()) {
|
if (input.empty()) {
|
||||||
std::cerr << "json::parse: empty string.\n";
|
error_info() += "json::parse: empty string.\n";
|
||||||
++parse_error;
|
++parse_error;
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
@ -308,12 +332,14 @@ var json::parse(const std::string& input, gc* ngc) {
|
||||||
if (this_token.type==token_type::tok_lbrkt) {
|
if (this_token.type==token_type::tok_lbrkt) {
|
||||||
ngc->temp = temp_stack = ngc->alloc(vm_type::vm_vec);
|
ngc->temp = temp_stack = ngc->alloc(vm_type::vm_vec);
|
||||||
auto result = vector_object_generate(ngc);
|
auto result = vector_object_generate(ngc);
|
||||||
|
check_eof();
|
||||||
ngc->temp = nil;
|
ngc->temp = nil;
|
||||||
temp_stack = nil;
|
temp_stack = nil;
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
ngc->temp = temp_stack = ngc->alloc(vm_type::vm_vec);
|
ngc->temp = temp_stack = ngc->alloc(vm_type::vm_vec);
|
||||||
auto result = hash_object_generate(ngc);
|
auto result = hash_object_generate(ngc);
|
||||||
|
check_eof();
|
||||||
ngc->temp = nil;
|
ngc->temp = nil;
|
||||||
temp_stack = nil;
|
temp_stack = nil;
|
||||||
return result;
|
return result;
|
||||||
|
@ -334,17 +360,17 @@ var parse(var* args, usize size, gc* ngc) {
|
||||||
if (!input.is_str()) {
|
if (!input.is_str()) {
|
||||||
return nas_err("json::parse", "must use string");
|
return nas_err("json::parse", "must use string");
|
||||||
}
|
}
|
||||||
json instance;
|
return json().parse(input.str(), ngc);
|
||||||
auto result = instance.parse(input.str(), ngc);
|
}
|
||||||
if (instance.has_error()) {
|
|
||||||
return nas_err("json::parse", "parse error");
|
var get_error(var* args, usize size, gc* ngc) {
|
||||||
}
|
return ngc->newstr(json::get_error());
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module_func_info func_tbl[] = {
|
module_func_info func_tbl[] = {
|
||||||
{"stringify", stringify},
|
{"stringify", stringify},
|
||||||
{"parse", parse},
|
{"parse", parse},
|
||||||
|
{"get_error", get_error},
|
||||||
{nullptr, nullptr}
|
{nullptr, nullptr}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@ use std.dylib;
|
||||||
var _dynamic_lib = dylib.dlopen("libjson."~(os.platform()=="windows"?"dll":"so"));
|
var _dynamic_lib = dylib.dlopen("libjson."~(os.platform()=="windows"?"dll":"so"));
|
||||||
var _stringify = _dynamic_lib.stringify;
|
var _stringify = _dynamic_lib.stringify;
|
||||||
var _parse = _dynamic_lib.parse;
|
var _parse = _dynamic_lib.parse;
|
||||||
|
var _get_error = _dynamic_lib.get_error;
|
||||||
|
var _no_param_call = dylib.limitcall(0);
|
||||||
var _call = dylib.limitcall(1);
|
var _call = dylib.limitcall(1);
|
||||||
|
|
||||||
var stringify = func(object) {
|
var stringify = func(object) {
|
||||||
|
@ -15,3 +17,7 @@ var stringify = func(object) {
|
||||||
var parse = func(input_string) {
|
var parse = func(input_string) {
|
||||||
return _call(_parse, input_string);
|
return _call(_parse, input_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var get_error = func() {
|
||||||
|
return _no_param_call(_get_error);
|
||||||
|
}
|
|
@ -39,6 +39,36 @@ println(ss, "\n");
|
||||||
println(json.parse(ss), "\n");
|
println(json.parse(ss), "\n");
|
||||||
println(libjson.parse(ss), "\n");
|
println(libjson.parse(ss), "\n");
|
||||||
|
|
||||||
|
var test_func = func(input_string) {
|
||||||
|
var result = libjson.parse(input_string);
|
||||||
|
var errno = libjson.get_error();
|
||||||
|
if (!size(errno)) {
|
||||||
|
println("\e[92;1msuccess\e[0m:");
|
||||||
|
println(" ", result);
|
||||||
|
} else {
|
||||||
|
println("\e[91;1merror\e[0m:");
|
||||||
|
foreach(var err; split("\n", errno)) {
|
||||||
|
println(" |-> ", err);
|
||||||
|
}
|
||||||
|
println(" +-> generated with error:");
|
||||||
|
println(" +-> ", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_func("[[]]");
|
||||||
|
test_func("{\"1\":1}");
|
||||||
|
test_func("[[[}]]]");
|
||||||
|
test_func("=-==_+_+_+");
|
||||||
|
test_func("123");
|
||||||
|
test_func(libjson.stringify({
|
||||||
|
a: 0,
|
||||||
|
b: nil,
|
||||||
|
c: "this is a string",
|
||||||
|
d: [{}, [[1, 2, 4, 8, 16]]]
|
||||||
|
}));
|
||||||
|
test_func("");
|
||||||
|
println();
|
||||||
|
|
||||||
var test_json = func(json) {
|
var test_json = func(json) {
|
||||||
var bar = process_bar.high_resolution_bar(30);
|
var bar = process_bar.high_resolution_bar(30);
|
||||||
var tmp = [
|
var tmp = [
|
||||||
|
|
Loading…
Reference in New Issue