🐛 fix bugs in stl/json, now it runs correctly

This commit is contained in:
ValKmjolnir 2023-01-31 19:39:22 +08:00
parent fdd7794a83
commit acb2e3664c
2 changed files with 188 additions and 125 deletions

View File

@ -1,13 +1,13 @@
# lib json.nas # lib json.nas
# 2021 ValKmjolnir # 2021 ValKmjolnir
var JSON=func(){ var JSON=func() {
var ( var (
j_eof, j_eof,
j_lbrace, j_lbrace,
j_rbrace, j_rbrace,
j_lbracket, j_lbrkt,
j_rbracket, j_rbrkt,
j_comma, j_comma,
j_colon, j_colon,
j_str, j_str,
@ -32,27 +32,28 @@ var JSON=func(){
var text_size=0; var text_size=0;
var ptr=0; var ptr=0;
var token={content:'',type:''}; var token={content:'',type:''};
var content={};
var init=func(){ var init=func() {
text=''; text='';
line=1; line=1;
text_size=0; text_size=0;
ptr=0; ptr=0;
content={};
token={content:'',type:''}; token={content:'',type:''};
} }
var isnum=func(c){ var isnum=func(c) {
return '0'<=c and c<='9'; return '0'<=c and c<='9';
} }
var isid=func(c){
var isid=func(c) {
var tmp=c[0]; var tmp=c[0];
return ('a'[0]<=tmp and tmp<='z'[0]) or return ('a'[0]<=tmp and tmp<='z'[0]) or
('A'[0]<=tmp and tmp<='Z'[0]) or ('A'[0]<=tmp and tmp<='Z'[0]) or
c=='_'; c=='_';
} }
var check=func(){
var c=text[ptr]; var check=func() {
var c=char(text[ptr]);
return ( return (
c=='{' or c=='}' or c=='{' or c=='}' or
c=='[' or c==']' or c=='[' or c==']' or
@ -62,70 +63,76 @@ var JSON=func(){
); );
} }
var get=func(str){ var get=func(str) {
init(); init();
if(!size(str)) if(!size(str)) {
die("empty string"); die("empty string");
text=split('',str); }
text=str;
text_size=size(text); text_size=size(text);
return; return;
} }
var next=func(){
while(ptr<text_size and !check()){ var next=func() {
if(text[ptr]=='\n') while(ptr<text_size and !check()) {
if(char(text[ptr])=='\n')
line+=1; line+=1;
ptr+=1; ptr+=1;
} }
if(ptr>=text_size){ if(ptr>=text_size) {
token.content="eof"; token.content="eof";
token.type=j_eof; token.type=j_eof;
return; return;
} }
var c=text[ptr]; var c=char(text[ptr]);
if(c=='{'){ if(c=='{') {
token.content='{'; token.content='{';
token.type=j_lbrace; token.type=j_lbrace;
}elsif(c=='}'){ } elsif(c=='}') {
token.content='}'; token.content='}';
token.type=j_rbrace; token.type=j_rbrace;
}elsif(c=='['){ } elsif(c=='[') {
token.content='['; token.content='[';
token.type=j_lbracket; token.type=j_lbrkt;
}elsif(c==']'){ } elsif(c==']') {
token.content=']'; token.content=']';
token.type=j_rbracket; token.type=j_rbrkt;
}elsif(c==','){ } elsif(c==',') {
token.content=','; token.content=',';
token.type=j_comma; token.type=j_comma;
}elsif(c==':'){ } elsif(c==':') {
token.content=':'; token.content=':';
token.type=j_colon; token.type=j_colon;
}elsif(c=='\"' or c=='\''){ } elsif(c=='\"' or c=='\'') {
var strbegin=c; var strbegin=c;
var s=""; var s="";
ptr+=1; ptr+=1;
while(ptr<text_size and text[ptr]!=strbegin){ while(ptr<text_size and char(text[ptr])!=strbegin) {
s~=text[ptr]; s~=char(text[ptr]);
ptr+=1; ptr+=1;
if(char(text[ptr-1])=="\\" and ptr<text_size) {
s~=char(text[ptr]);
ptr+=1;
}
} }
token.content=s; token.content=s;
token.type=j_str; token.type=j_str;
}elsif(isnum(c)){ } elsif(isnum(c)) {
var s=c; var s=c;
ptr+=1; ptr+=1;
while(ptr<text_size and ((isnum(text[ptr]) or text[ptr]=='.'))){ while(ptr<text_size and ((isnum(char(text[ptr])) or char(text[ptr])=='.'))) {
s~=text[ptr]; s~=char(text[ptr]);
ptr+=1; ptr+=1;
} }
ptr-=1; ptr-=1;
token.content=num(s); token.content=num(s);
token.type=j_num; token.type=j_num;
}elsif(isid(c)){ } elsif(isid(c)) {
var s=c; var s=c;
ptr+=1; ptr+=1;
while(ptr<text_size and (isid(text[ptr]) or isnum(text[ptr]))){ while(ptr<text_size and (isid(char(text[ptr])) or isnum(char(text[ptr])))) {
s~=text[ptr]; s~=char(text[ptr]);
ptr+=1; ptr+=1;
} }
ptr-=1; ptr-=1;
@ -136,18 +143,40 @@ var JSON=func(){
return; return;
} }
var match=func(type){ var match=func(type) {
if(token.type!=type) if(token.type!=type)
print("line ",line,": expect ",j_content[type]," but get `",token.content,"`.\n"); print("line ",line,": expect ",j_content[type]," but get `",token.content,"`.\n");
next(); next();
return; return;
} }
var hash_gen=func(){ var member=func(hash) {
var name=token.content;
if(token.type==j_rbrace) {
return;
}
if(token.type==j_str) {
match(j_str);
} else {
match(j_id);
}
match(j_colon);
if(token.type==j_lbrace) {
hash[name]=hash_gen();
} elsif(token.type==j_lbrkt) {
hash[name]=vec_gen();
} elsif(token.type==j_str or token.type==j_num) {
hash[name]=token.content;
next();
}
return;
}
var hash_gen=func() {
var hash={}; var hash={};
match(j_lbrace); match(j_lbrace);
member(hash); member(hash);
while(token.type==j_comma){ while(token.type==j_comma) {
match(j_comma); match(j_comma);
member(hash); member(hash);
} }
@ -155,114 +184,103 @@ var JSON=func(){
return hash; return hash;
} }
var vec_gen=func(){ var vec_gen=func() {
var vec=[]; var vec=[];
match(j_lbracket); match(j_lbrkt);
if(token.type==j_lbrace){ if(token.type==j_lbrace) {
append(vec,hash_gen()); append(vec,hash_gen());
}elsif(token.type==j_lbracket){ } elsif(token.type==j_lbrkt) {
append(vec,vec_gen()); append(vec,vec_gen());
}elsif(token.type==j_str or token.type==j_num){ } elsif(token.type==j_str or token.type==j_num) {
append(vec,token.content); append(vec,token.content);
next(); next();
} }
while(token.type==j_comma){ while(token.type==j_comma) {
match(j_comma); match(j_comma);
if(token.type==j_lbrace){ if(token.type==j_lbrace) {
append(vec,me.hash_gen()); append(vec,hash_gen());
}elsif(token.type==j_lbracket){ } elsif(token.type==j_lbrkt) {
append(vec,vec_gen()); append(vec,vec_gen());
}elsif(token.type==j_str or token.type==j_num){ } elsif(token.type==j_str or token.type==j_num) {
append(vec,token.content); append(vec,token.content);
next(); next();
} }
} }
match(j_rbracket); match(j_rbrkt);
return vec; return vec;
} }
var member=func(hash){
var name=token.content;
if(token.type==j_rbrace){
return;
}
if(token.type==j_str){
match(j_str);
}else{
match(j_id);
}
match(j_colon);
if(token.type==j_lbrace){
hash[name]=hash_gen();
}elsif(token.type==j_lbracket){
hash[name]=vec_gen();
}elsif(token.type==j_str or token.type==j_num){
hash[name]=token.content;
next();
}
return;
}
return { return {
parse:func(str){ parse:func(str) {
if(typeof(str)!="str") if(typeof(str)!="str") {
die("JSON.parse: must use string"); die("JSON.parse: must use string");
}
get(str); get(str);
next(); next();
match(j_lbrace); if(token.type==j_lbrkt) {
member(content); var res=vec_gen();
while(token.type==j_comma){ } else {
match(j_comma); var res=hash_gen();
member(content);
} }
match(j_rbrace);
var res=content;
init(); init();
return res; return res;
},
stringify:func(hash){
if(typeof(hash)!="hash")
die("JSON.stringify: must use hashmap");
var s="";
var gen=func(elem){
var t=typeof(elem);
if(t=="num"){
s~=elem;
}elsif(t=="str"){
s~='"'~elem~'"';
}elsif(t=="vec"){
vgen(elem);
}elsif(t=="hash"){
hgen(elem);
}else{
s~='"undefined"';
}
}
var vgen=func(v){
s~="[";
var vsize=size(v);
for(var i=0;i<vsize;i+=1){
gen(v[i]);
if(i!=vsize-1)
s~=",";
}
s~="]";
}
var hgen=func(h){
s~="{";
var k=keys(h);
var vsize=size(k);
for(var i=0;i<vsize;i+=1){
s~=k[i]~":";
gen(h[k[i]]);
if(i!=vsize-1)
s~=",";
}
s~="}";
}
hgen(hash);
return s;
} }
}; };
}(); }();
JSON.stringify=func(object) {
if(typeof(object)!="hash" and typeof(object)!="vec") {
die("JSON.stringify: must use hashmap or vector");
}
var s="";
var gen=func(elem) {
var t=typeof(elem);
if(t=="num") {
s~=str(elem);
} elsif(t=="str") {
s~='"'~elem~'"';
} elsif(t=="vec") {
vgen(elem);
} elsif(t=="hash") {
hgen(elem);
} else {
s~='"undefined"';
}
}
var vgen=func(v) {
s~="[";
var vsize=size(v);
for(var i=0;i<vsize;i+=1) {
gen(v[i]);
if(i!=vsize-1) {
s~=",";
}
}
s~="]";
}
var hgen=func(h) {
s~="{";
var k=keys(h);
var vsize=size(k);
for(var i=0;i<vsize;i+=1) {
s~=k[i]~":";
gen(h[k[i]]);
if(i!=vsize-1) {
s~=",";
}
}
s~="}";
}
if(typeof(object)=="vec") {
vgen(object);
} else {
hgen(object);
}
return s;
}

View File

@ -1,10 +1,11 @@
import.stl.json; import.stl.json;
import.stl.process_bar;
var ss=JSON.stringify({ var ss=JSON.stringify({
vec:[0,1,2], vec:[0,1,2],
hash:{ hash:{
m1:0, m1:0,
m2:"str", m2:"str\\\"test\\\"",
m3:[114514], m3:[114514],
m4:{year:1919,month:8,date:10} m4:{year:1919,month:8,date:10}
}, },
@ -14,5 +15,49 @@ var ss=JSON.stringify({
empty_an:[[[[[[{}]]]]]], empty_an:[[[[[[{}]]]]]],
function:func(){} function:func(){}
}); });
println(ss); println(ss,"\n");
println(JSON.parse(ss)); println(JSON.parse(ss),"\n");
var ss=JSON.stringify([{
vec:[0,1,2,3],
hash:{
m1:0,
m2:"str\\\"test\\\"",
m3:[114514,1919810],
m4:{year:1919,month:8,date:10}
},
emptyhash:{},
emptyvec:[],
empty_an:[[[[[{}]]]]],
function:func(){}
}]);
println(ss,"\n");
println(JSON.parse(ss),"\n");
func {
var bar=process_bar.high_resolution_bar(30);
var tmp=[
{t1:nil},
{t2:nil},
{t3:nil},
{t4:nil},
{t5:nil},
{t6:nil}
];
srand();
foreach(var h;tmp) {
var name=keys(h)[0];
h[name]=[];
print("\e[1000D",bar.bar(0));
for(var i=0;i<1e3;i+=1) {
append(h[name],{id:i,content:int(rand()*1e7)});
print("\e[1000D",bar.bar((i+1)/1e3));
}
print("\e[1000D",bar.bar(1)," executing...\n");
}
print("\e[1000D","\e["~str(size(tmp))~"A");
foreach(var h;JSON.parse(JSON.stringify(tmp))) {
println("\e[1000D",bar.bar(1)," done ",keys(h)[0]," ",size(h[keys(h)[0]])," ");
}
}();