export function parse()

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;
}