Created
December 18, 2023 10:58
-
-
Save kuuote/d7427f53919a7697b95a1e526c43cd7a to your computer and use it in GitHub Desktop.
parses subset of ECMA-404
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