Created
April 11, 2020 15:45
-
-
Save kuuote/533a59628ab98f0fa02ad3bdc394e8c2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
" ws以外の全ての関数は[result, newpos]を返す | |
function! s:object(in, pos) abort | |
let p = s:ws(a:in, a:pos + 1) | |
if a:in[p] == 125 " } | |
return [{}, p + 1] | |
endif | |
let acc = {} | |
while v:true | |
let [r, p] = s:member(a:in, p) | |
let acc[r[0]] = r[1] | |
if a:in[p] == 125 " } | |
break | |
elseif a:in[p] != 44 " , | |
throw printf("object:missing comma at %d", p) | |
endif | |
let p = s:ws(a:in, p + 1) | |
endwhile | |
return [acc, p + 1] | |
endfunction | |
function! s:member(in, pos) abort | |
let [k, p] = s:element(a:in, a:pos) | |
if type(k) != v:t_string | |
throw printf("member:key must be string, actual:%s", string(k)) | |
endif | |
if a:in[p] != 58 " : | |
throw printf("member:missing colon at %d", p) | |
endif | |
let [v, p] = s:element(a:in, p + 1) | |
return [[k, v], p] | |
endfunction | |
function! s:array(in, pos) abort | |
let p = s:ws(a:in, a:pos + 1) | |
if a:in[p] == 93 " ] | |
return [[], p + 1] | |
endif | |
let acc = [] | |
while v:true | |
let [r, p] = s:element(a:in, p) | |
call add(acc, r) | |
if a:in[p] == 93 " ] | |
break | |
elseif a:in[p] != 44 " , | |
throw printf("array:missing comma at %d", p) | |
endif | |
let p = s:ws(a:in, p + 1) | |
endwhile | |
return [acc, p + 1] | |
endfunction | |
function! s:element(in, pos) abort | |
let p = s:ws(a:in, a:pos) | |
let c = a:in[p] | |
if c == 123 " { | |
let r = s:object(a:in, p) | |
elseif c == 91 " [ | |
let r = s:array(a:in, p) | |
elseif c == 34 | |
let r = s:string(a:in, p) | |
endif | |
return [r[0], s:ws(a:in, r[1])] | |
endfunction | |
function! s:string(in, pos) abort | |
let end = index(a:in, 34, a:pos + 1) " dquote | |
return [list2str(a:in[a:pos + 1 : end - 1]), end + 1] | |
endfunction | |
let s:ws = [0x20, 0xa, 0xd, 0x9] | |
function! s:ws(in, pos) abort | |
let p = a:pos | |
while p < len(a:in) && index(s:ws, a:in[p]) != -1 | |
let p += 1 | |
endwhile | |
return p | |
endfunction | |
echo s:element(str2list('{"foo" : "string", "bar": [{"nested":"object"}, "is", [["a","l", "l" ,"o" , "wed"] ]]}'), 0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment