function nextJSONToken()

in src/json.ts [332:521]


function nextJSONToken(_state: JSONStreamState, _out: JSONToken): boolean {
	_out.value = null;
	_out.type = JSONTokenType.UNKNOWN;
	_out.offset = -1;
	_out.len = -1;
	_out.line = -1;
	_out.char = -1;

	let source = _state.source;
	let pos = _state.pos;
	let len = _state.len;
	let line = _state.line;
	let char = _state.char;

	//------------------------ skip whitespace
	let chCode: number;
	do {
		if (pos >= len) {
			return false; /*EOS*/
		}

		chCode = source.charCodeAt(pos);
		if (chCode === ChCode.SPACE || chCode === ChCode.HORIZONTAL_TAB || chCode === ChCode.CARRIAGE_RETURN) {
			// regular whitespace
			pos++; char++;
			continue;
		}

		if (chCode === ChCode.LINE_FEED) {
			// newline
			pos++; line++; char = 0;
			continue;
		}

		// not whitespace
		break;
	} while (true);

	_out.offset = pos;
	_out.line = line;
	_out.char = char;

	if (chCode === ChCode.QUOTATION_MARK) {
		//------------------------ strings
		_out.type = JSONTokenType.STRING;

		pos++; char++;

		do {
			if (pos >= len) {
				return false; /*EOS*/
			}

			chCode = source.charCodeAt(pos);
			pos++; char++;

			if (chCode === ChCode.BACKSLASH) {
				// skip next char
				pos++; char++;
				continue;
			}

			if (chCode === ChCode.QUOTATION_MARK) {
				// end of the string
				break;
			}
		} while (true);

		_out.value = source.substring(_out.offset + 1, pos - 1).replace(/\\u([0-9A-Fa-f]{4})/g, (_, m0) => {
			return (<any>String).fromCodePoint(parseInt(m0, 16));
		}).replace(/\\(.)/g, (_, m0) => {
			switch (m0) {
				case '"': return '"';
				case '\\': return '\\';
				case '/': return '/';
				case 'b': return '\b';
				case 'f': return '\f';
				case 'n': return '\n';
				case 'r': return '\r';
				case 't': return '\t';
				default: doFail(_state, 'invalid escape sequence');
			}
			throw new Error('unreachable');
		});

	} else if (chCode === ChCode.LEFT_SQUARE_BRACKET) {

		_out.type = JSONTokenType.LEFT_SQUARE_BRACKET;
		pos++; char++;

	} else if (chCode === ChCode.LEFT_CURLY_BRACKET) {

		_out.type = JSONTokenType.LEFT_CURLY_BRACKET;
		pos++; char++;

	} else if (chCode === ChCode.RIGHT_SQUARE_BRACKET) {

		_out.type = JSONTokenType.RIGHT_SQUARE_BRACKET;
		pos++; char++;

	} else if (chCode === ChCode.RIGHT_CURLY_BRACKET) {

		_out.type = JSONTokenType.RIGHT_CURLY_BRACKET;
		pos++; char++;

	} else if (chCode === ChCode.COLON) {

		_out.type = JSONTokenType.COLON;
		pos++; char++;

	} else if (chCode === ChCode.COMMA) {

		_out.type = JSONTokenType.COMMA;
		pos++; char++;

	} else if (chCode === ChCode.n) {
		//------------------------ null

		_out.type = JSONTokenType.NULL;
		pos++; char++; chCode = source.charCodeAt(pos);
		if (chCode !== ChCode.u) { return false; /* INVALID */ }
		pos++; char++; chCode = source.charCodeAt(pos);
		if (chCode !== ChCode.l) { return false; /* INVALID */ }
		pos++; char++; chCode = source.charCodeAt(pos);
		if (chCode !== ChCode.l) { return false; /* INVALID */ }
		pos++; char++;

	} else if (chCode === ChCode.t) {
		//------------------------ true

		_out.type = JSONTokenType.TRUE;
		pos++; char++; chCode = source.charCodeAt(pos);
		if (chCode !== ChCode.r) { return false; /* INVALID */ }
		pos++; char++; chCode = source.charCodeAt(pos);
		if (chCode !== ChCode.u) { return false; /* INVALID */ }
		pos++; char++; chCode = source.charCodeAt(pos);
		if (chCode !== ChCode.e) { return false; /* INVALID */ }
		pos++; char++;

	} else if (chCode === ChCode.f) {
		//------------------------ false

		_out.type = JSONTokenType.FALSE;
		pos++; char++; chCode = source.charCodeAt(pos);
		if (chCode !== ChCode.a) { return false; /* INVALID */ }
		pos++; char++; chCode = source.charCodeAt(pos);
		if (chCode !== ChCode.l) { return false; /* INVALID */ }
		pos++; char++; chCode = source.charCodeAt(pos);
		if (chCode !== ChCode.s) { return false; /* INVALID */ }
		pos++; char++; chCode = source.charCodeAt(pos);
		if (chCode !== ChCode.e) { return false; /* INVALID */ }
		pos++; char++;

	} else {
		//------------------------ numbers

		_out.type = JSONTokenType.NUMBER;
		do {
			if (pos >= len) { return false; /*EOS*/ }

			chCode = source.charCodeAt(pos);
			if (
				chCode === ChCode.DOT
				|| (chCode >= ChCode.D0 && chCode <= ChCode.D9)
				|| (chCode === ChCode.e || chCode === ChCode.E)
				|| (chCode === ChCode.MINUS || chCode === ChCode.PLUS)
			) {
				// looks like a piece of a number
				pos++; char++;
				continue;
			}

			// pos--; char--;
			break;
		} while (true);
	}

	_out.len = pos - _out.offset;
	if (_out.value === null) {
		_out.value = source.substr(_out.offset, _out.len);
	}

	_state.pos = pos;
	_state.line = line;
	_state.char = char;

	// console.log('PRODUCING TOKEN: ', _out.value, JSONTokenType[_out.type]);

	return true;
}