update fully functional test/json.nas

This commit is contained in:
ValKmjolnir 2022-03-11 15:11:24 +08:00
parent f26719e1d3
commit 3d86a32b12
1 changed files with 307 additions and 179 deletions

View File

@ -1,196 +1,324 @@
#lib json.nas #lib json.nas
import("lib.nas"); import("lib.nas");
var json={
text:'',
line:1,
size:0,
ptr:0,
get:nil,
check:nil,
next:nil,
match:nil,
hash_gen:nil,
vec_gen:nil,
member:nil,
parse:nil,
token:{content:'',type:''},
content:[],
};
json.get=func(filename) var JSON=func(){
{
me.line=1;
me.ptr=0;
me.content=[];
me.token={content:'',type:''};
me.text=io.fin(filename);
if(!size(me.text))
die("cannot open "~filename);
me.text=split('',me.text);
me.size=size(me.text);
return;
}
json.check=func(ptr) var (
{ j_eof,
var str=me.text[ptr]; j_lbrace,
return (str=='{' or str=='}' or str=='[' or str==']' or str==',' or str==':' or str=='\"' or ('0'<=str and str<='9')); j_rbrace,
} j_lbracket,
j_rbracket,
j_comma,
j_colon,
j_str,
j_num,
j_id
)=(
0,
1,
2,
3,
4,
5,
6,
7,
8,
9
);
var j_content=[
"eof",
"`{`",
"`}`",
"`[`",
"`]`",
"`,`",
"`:`",
"string",
"number",
"identifier"
];
json.next=func() var text='';
{ var line=1;
while(me.ptr<me.size and !json.check(me.ptr)) var text_size=0;
{ var ptr=0;
if(me.text[me.ptr]=='\n') var token={content:'',type:''};
me.line+=1; var content={};
me.ptr+=1; var init=func(){
line=1;
text_size=0;
ptr=0;
content={};
token={content:'',type:''};
text='';
} }
if(me.ptr>=me.size)
var isnum=func(c){
return '0'<=c and c<='9';
}
var isid=func(c){
var tmp=c[0];
return ('a'[0]<=tmp and tmp<='z'[0]) or
('A'[0]<=tmp and tmp<='Z'[0]) or
c=='_';
}
var check=func()
{ {
me.token.content=""; var c=text[ptr];
me.token.type="eof"; return (
c=='{' or c=='}' or
c=='[' or c==']' or
c==',' or c==':' or
c=='\"' or c=='\'' or
isnum(c) or isid(c)
);
}
var get=func(str)
{
init();
if(!size(str))
die("empty string");
text=split('',str);
text_size=size(text);
return;
}
var next=func()
{
while(ptr<text_size and !check())
{
if(text[ptr]=='\n')
line+=1;
ptr+=1;
}
if(ptr>=text_size)
{
token.content="eof";
token.type=j_eof;
return; return;
} }
if(me.text[me.ptr]=='{') var c=text[ptr];
if(c=='{')
{ {
me.token.content='{'; token.content='{';
me.token.type="left brace"; token.type=j_lbrace;
} }
elsif(me.text[me.ptr]=='}') elsif(c=='}')
{ {
me.token.content='}'; token.content='}';
me.token.type="right brace"; token.type=j_rbrace;
} }
elsif(me.text[me.ptr]=='[') elsif(c=='[')
{ {
me.token.content='['; token.content='[';
me.token.type="left bracket"; token.type=j_lbracket;
} }
elsif(me.text[me.ptr]==']') elsif(c==']')
{ {
me.token.content=']'; token.content=']';
me.token.type="right bracket"; token.type=j_rbracket;
} }
elsif(me.text[me.ptr]==',') elsif(c==',')
{ {
me.token.content=','; token.content=',';
me.token.type="comma"; token.type=j_comma;
} }
elsif(me.text[me.ptr]==':') elsif(c==':')
{ {
me.token.content=':'; token.content=':';
me.token.type="colon"; token.type=j_colon;
} }
elsif(me.text[me.ptr]=='\"') elsif(c=='\"' or c=='\'')
{ {
var strbegin=c;
var s=""; var s="";
me.ptr+=1; ptr+=1;
while(me.ptr<me.size and me.text[me.ptr]!='\"') while(ptr<text_size and text[ptr]!=strbegin)
{ {
s~=me.text[me.ptr]; s~=text[ptr];
me.ptr+=1; ptr+=1;
} }
me.token.content=s; token.content=s;
me.token.type="string"; token.type=j_str;
} }
elsif('0'<=me.text[me.ptr] and me.text[me.ptr]<='9') elsif(isnum(c))
{ {
var s=me.text[me.ptr]; var s=c;
me.ptr+=1; ptr+=1;
while(me.ptr<me.size and (('0'<=me.text[me.ptr] and me.text[me.ptr]<='9') or me.text[me.ptr]=='.')) while(ptr<text_size and ((isnum(text[ptr]) or text[ptr]=='.')))
{ {
s~=me.text[me.ptr]; s~=text[ptr];
me.ptr+=1; ptr+=1;
} }
me.ptr-=1; ptr-=1;
me.token.content=num(s); token.content=num(s);
me.token.type="number"; token.type=j_num;
} }
me.ptr+=1; elsif(isid(c))
{
var s=c;
ptr+=1;
while(ptr<text_size and (isid(text[ptr]) or isnum(text[ptr])))
{
s~=text[ptr];
ptr+=1;
}
ptr-=1;
token.content=s;
token.type=j_id;
}
ptr+=1;
return; return;
} }
json.match=func(type) var match=func(type)
{ {
if(me.token.type!=type) if(token.type!=type)
print("line ",me.line,": expect ",type," but get ",me.token.content,"."); print("line ",line,": expect ",j_content[type]," but get `",token.content,"`.\n");
me.next(); next();
return; return;
} }
json.hash_gen=func() var hash_gen=func()
{ {
var hash={}; var hash={};
me.match("left brace"); match(j_lbrace);
me.member(hash); member(hash);
while(me.token.type=="comma") while(token.type==j_comma)
{ {
me.match("comma"); match(j_comma);
me.member(hash); member(hash);
} }
me.match("right brace"); match(j_rbrace);
return hash; return hash;
} }
json.vec_gen=func() var vec_gen=func()
{ {
var vec=[]; var vec=[];
me.match("left bracket"); match(j_lbracket);
if(me.token.type=="left brace") if(token.type==j_lbrace)
append(vec,hash_gen());
elsif(token.type==j_lbracket)
append(vec,vec_gen());
elsif(token.type==j_str or token.type==j_num)
{
append(vec,token.content);
next();
}
while(token.type==j_comma)
{
match(j_comma);
if(token.type==j_lbrace)
append(vec,me.hash_gen()); append(vec,me.hash_gen());
elsif(me.token.type=="left bracket") elsif(token.type==j_lbracket)
append(vec,me.vec_gen()); append(vec,vec_gen());
elsif(me.token.type=="string" or me.token.type=="number") elsif(token.type==j_str or token.type==j_num)
{ {
append(vec,me.token.content); append(vec,token.content);
me.next(); next();
}
while(me.token.type=="comma")
{
me.match("comma");
if(me.token.type=="left brace")
append(vec,me.hash_gen());
elsif(me.token.type=="left bracket")
append(vec,me.vec_gen());
elsif(me.token.type=="string" or me.token.type=="number")
{
append(vec,me.token.content);
me.next();
} }
} }
me.match("right bracket"); match(j_rbracket);
return vec; return vec;
} }
json.member=func(hash) var member=func(hash)
{
var name=me.token.content;
me.match("string");
me.match("colon");
if(me.token.type=="left brace")
hash[name]=me.hash_gen();
elsif(me.token.type=="left bracket")
hash[name]=me.vec_gen();
elsif(me.token.type=="string" or me.token.type=="number")
{ {
hash[name]=me.token.content; var name=token.content;
me.next(); 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;
}
json.parse=func()
{
me.content={};
me.next();
me.match("left brace");
me.member(me.content);
while(me.token.type=="comma")
{
me.match("comma");
me.member(me.content);
} }
me.match("right brace"); return {
return; parse:func(str)
} {
get(str);
next();
match(j_lbrace);
member(content);
while(token.type==j_comma)
{
match(j_comma);
member(content);
}
match(j_rbrace);
var res=content;
init();
return res;
},
stringify:func(hash){
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;
}
};
}();
var ss=JSON.stringify({
vec:[
0,
1,
2
],
hash:{
m1:0,
m2:"str",
m3:[114514],
m4:{
year:1919,
month:8,
date:10
}
}
});
println(ss);
println(JSON.parse(ss));