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