Skip to content

Instantly share code, notes, and snippets.

@kuuote
Created April 11, 2020 15:45
Show Gist options
  • Save kuuote/533a59628ab98f0fa02ad3bdc394e8c2 to your computer and use it in GitHub Desktop.
Save kuuote/533a59628ab98f0fa02ad3bdc394e8c2 to your computer and use it in GitHub Desktop.
" 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