in src/json.ts [16:221]
export function parse(source: string, filename: string | null, withMetadata: boolean): any {
let streamState = new JSONStreamState(source);
let token = new JSONToken();
let state = JSONState.ROOT_STATE;
let cur: any = null;
let stateStack: JSONState[] = [];
let objStack: any[] = [];
function pushState(): void {
stateStack.push(state);
objStack.push(cur);
}
function popState(): void {
state = stateStack.pop()!;
cur = objStack.pop();
}
function fail(msg: string): void {
doFail(streamState, msg);
}
while (nextJSONToken(streamState, token)) {
if (state === JSONState.ROOT_STATE) {
if (cur !== null) {
fail('too many constructs in root');
}
if (token.type === JSONTokenType.LEFT_CURLY_BRACKET) {
cur = {};
if (withMetadata) {
cur.$vscodeTextmateLocation = token.toLocation(filename);
}
pushState();
state = JSONState.DICT_STATE;
continue;
}
if (token.type === JSONTokenType.LEFT_SQUARE_BRACKET) {
cur = [];
pushState();
state = JSONState.ARR_STATE;
continue;
}
fail('unexpected token in root');
}
if (state === JSONState.DICT_STATE_COMMA) {
if (token.type === JSONTokenType.RIGHT_CURLY_BRACKET) {
popState();
continue;
}
if (token.type === JSONTokenType.COMMA) {
state = JSONState.DICT_STATE_NO_CLOSE;
continue;
}
fail('expected , or }');
}
if (state === JSONState.DICT_STATE || state === JSONState.DICT_STATE_NO_CLOSE) {
if (state === JSONState.DICT_STATE && token.type === JSONTokenType.RIGHT_CURLY_BRACKET) {
popState();
continue;
}
if (token.type === JSONTokenType.STRING) {
let keyValue = token.value!;
if (!nextJSONToken(streamState, token) || (/*TS bug*/<any>token.type) !== JSONTokenType.COLON) {
fail('expected colon');
}
if (!nextJSONToken(streamState, token)) {
fail('expected value');
}
state = JSONState.DICT_STATE_COMMA;
if (token.type === JSONTokenType.STRING) {
cur[keyValue] = token.value;
continue;
}
if (token.type === JSONTokenType.NULL) {
cur[keyValue] = null;
continue;
}
if (token.type === JSONTokenType.TRUE) {
cur[keyValue] = true;
continue;
}
if (token.type === JSONTokenType.FALSE) {
cur[keyValue] = false;
continue;
}
if (token.type === JSONTokenType.NUMBER) {
cur[keyValue] = parseFloat(token.value!);
continue;
}
if (token.type === JSONTokenType.LEFT_SQUARE_BRACKET) {
let newArr: any[] = [];
cur[keyValue] = newArr;
pushState();
state = JSONState.ARR_STATE;
cur = newArr;
continue;
}
if (token.type === JSONTokenType.LEFT_CURLY_BRACKET) {
let newDict: any = {};
if (withMetadata) {
newDict.$vscodeTextmateLocation = token.toLocation(filename);
}
cur[keyValue] = newDict;
pushState();
state = JSONState.DICT_STATE;
cur = newDict;
continue;
}
}
fail('unexpected token in dict');
}
if (state === JSONState.ARR_STATE_COMMA) {
if (token.type === JSONTokenType.RIGHT_SQUARE_BRACKET) {
popState();
continue;
}
if (token.type === JSONTokenType.COMMA) {
state = JSONState.ARR_STATE_NO_CLOSE;
continue;
}
fail('expected , or ]');
}
if (state === JSONState.ARR_STATE || state === JSONState.ARR_STATE_NO_CLOSE) {
if (state === JSONState.ARR_STATE && token.type === JSONTokenType.RIGHT_SQUARE_BRACKET) {
popState();
continue;
}
state = JSONState.ARR_STATE_COMMA;
if (token.type === JSONTokenType.STRING) {
cur.push(token.value);
continue;
}
if (token.type === JSONTokenType.NULL) {
cur.push(null);
continue;
}
if (token.type === JSONTokenType.TRUE) {
cur.push(true);
continue;
}
if (token.type === JSONTokenType.FALSE) {
cur.push(false);
continue;
}
if (token.type === JSONTokenType.NUMBER) {
cur.push(parseFloat(token.value!));
continue;
}
if (token.type === JSONTokenType.LEFT_SQUARE_BRACKET) {
let newArr: any[] = [];
cur.push(newArr);
pushState();
state = JSONState.ARR_STATE;
cur = newArr;
continue;
}
if (token.type === JSONTokenType.LEFT_CURLY_BRACKET) {
let newDict: any = {};
if (withMetadata) {
newDict.$vscodeTextmateLocation = token.toLocation(filename);
}
cur.push(newDict);
pushState();
state = JSONState.DICT_STATE;
cur = newDict;
continue;
}
fail('unexpected token in array');
}
fail('unknown state');
}
if (objStack.length !== 0) {
fail('unclosed constructs');
}
return cur;
}