node_modules.graphql.language.lexer.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of apollo-client-maven-plugin Show documentation
Show all versions of apollo-client-maven-plugin Show documentation
Maven plugin for generating graphql clients
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.TokenKind = undefined;
exports.createLexer = createLexer;
exports.getTokenDesc = getTokenDesc;
var _error = require('../error');
var _blockStringValue = require('./blockStringValue');
var _blockStringValue2 = _interopRequireDefault(_blockStringValue);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Given a Source object, this returns a Lexer for that source.
* A Lexer is a stateful stream generator in that every time
* it is advanced, it returns the next token in the Source. Assuming the
* source lexes, the final Token emitted by the lexer will be of kind
* EOF, after which the lexer will repeatedly return the same EOF token
* whenever called.
*/
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* strict
*/
function createLexer(source, options) {
var startOfFileToken = new Tok(TokenKind.SOF, 0, 0, 0, 0, null);
var lexer = {
source: source,
options: options,
lastToken: startOfFileToken,
token: startOfFileToken,
line: 1,
lineStart: 0,
advance: advanceLexer,
lookahead: lookahead
};
return lexer;
}
function advanceLexer() {
this.lastToken = this.token;
var token = this.token = this.lookahead();
return token;
}
function lookahead() {
var token = this.token;
if (token.kind !== TokenKind.EOF) {
do {
// Note: next is only mutable during parsing, so we cast to allow this.
token = token.next || (token.next = readToken(this, token));
} while (token.kind === TokenKind.COMMENT);
}
return token;
}
/**
* The return type of createLexer.
*/
/**
* An exported enum describing the different kinds of tokens that the
* lexer emits.
*/
var TokenKind = exports.TokenKind = Object.freeze({
SOF: '',
EOF: '',
BANG: '!',
DOLLAR: '$',
AMP: '&',
PAREN_L: '(',
PAREN_R: ')',
SPREAD: '...',
COLON: ':',
EQUALS: '=',
AT: '@',
BRACKET_L: '[',
BRACKET_R: ']',
BRACE_L: '{',
PIPE: '|',
BRACE_R: '}',
NAME: 'Name',
INT: 'Int',
FLOAT: 'Float',
STRING: 'String',
BLOCK_STRING: 'BlockString',
COMMENT: 'Comment'
});
/**
* The enum type representing the token kinds values.
*/
/**
* A helper function to describe a token as a string for debugging
*/
function getTokenDesc(token) {
var value = token.value;
return value ? token.kind + ' "' + value + '"' : token.kind;
}
var charCodeAt = String.prototype.charCodeAt;
var slice = String.prototype.slice;
/**
* Helper function for constructing the Token object.
*/
function Tok(kind, start, end, line, column, prev, value) {
this.kind = kind;
this.start = start;
this.end = end;
this.line = line;
this.column = column;
this.value = value;
this.prev = prev;
this.next = null;
}
// Print a simplified form when appearing in JSON/util.inspect.
Tok.prototype.toJSON = Tok.prototype.inspect = function toJSON() {
return {
kind: this.kind,
value: this.value,
line: this.line,
column: this.column
};
};
function printCharCode(code) {
return (
// NaN/undefined represents access beyond the end of the file.
isNaN(code) ? TokenKind.EOF : // Trust JSON for ASCII.
code < 0x007f ? JSON.stringify(String.fromCharCode(code)) : // Otherwise print the escaped form.
'"\\u' + ('00' + code.toString(16).toUpperCase()).slice(-4) + '"'
);
}
/**
* Gets the next token from the source starting at the given position.
*
* This skips over whitespace and comments until it finds the next lexable
* token, then lexes punctuators immediately or calls the appropriate helper
* function for more complicated tokens.
*/
function readToken(lexer, prev) {
var source = lexer.source;
var body = source.body;
var bodyLength = body.length;
var pos = positionAfterWhitespace(body, prev.end, lexer);
var line = lexer.line;
var col = 1 + pos - lexer.lineStart;
if (pos >= bodyLength) {
return new Tok(TokenKind.EOF, bodyLength, bodyLength, line, col, prev);
}
var code = charCodeAt.call(body, pos);
// SourceCharacter
if (code < 0x0020 && code !== 0x0009 && code !== 0x000a && code !== 0x000d) {
throw (0, _error.syntaxError)(source, pos, 'Cannot contain the invalid character ' + printCharCode(code) + '.');
}
switch (code) {
// !
case 33:
return new Tok(TokenKind.BANG, pos, pos + 1, line, col, prev);
// #
case 35:
return readComment(source, pos, line, col, prev);
// $
case 36:
return new Tok(TokenKind.DOLLAR, pos, pos + 1, line, col, prev);
// &
case 38:
return new Tok(TokenKind.AMP, pos, pos + 1, line, col, prev);
// (
case 40:
return new Tok(TokenKind.PAREN_L, pos, pos + 1, line, col, prev);
// )
case 41:
return new Tok(TokenKind.PAREN_R, pos, pos + 1, line, col, prev);
// .
case 46:
if (charCodeAt.call(body, pos + 1) === 46 && charCodeAt.call(body, pos + 2) === 46) {
return new Tok(TokenKind.SPREAD, pos, pos + 3, line, col, prev);
}
break;
// :
case 58:
return new Tok(TokenKind.COLON, pos, pos + 1, line, col, prev);
// =
case 61:
return new Tok(TokenKind.EQUALS, pos, pos + 1, line, col, prev);
// @
case 64:
return new Tok(TokenKind.AT, pos, pos + 1, line, col, prev);
// [
case 91:
return new Tok(TokenKind.BRACKET_L, pos, pos + 1, line, col, prev);
// ]
case 93:
return new Tok(TokenKind.BRACKET_R, pos, pos + 1, line, col, prev);
// {
case 123:
return new Tok(TokenKind.BRACE_L, pos, pos + 1, line, col, prev);
// |
case 124:
return new Tok(TokenKind.PIPE, pos, pos + 1, line, col, prev);
// }
case 125:
return new Tok(TokenKind.BRACE_R, pos, pos + 1, line, col, prev);
// A-Z _ a-z
case 65:
case 66:
case 67:
case 68:
case 69:
case 70:
case 71:
case 72:
case 73:
case 74:
case 75:
case 76:
case 77:
case 78:
case 79:
case 80:
case 81:
case 82:
case 83:
case 84:
case 85:
case 86:
case 87:
case 88:
case 89:
case 90:
case 95:
case 97:
case 98:
case 99:
case 100:
case 101:
case 102:
case 103:
case 104:
case 105:
case 106:
case 107:
case 108:
case 109:
case 110:
case 111:
case 112:
case 113:
case 114:
case 115:
case 116:
case 117:
case 118:
case 119:
case 120:
case 121:
case 122:
return readName(source, pos, line, col, prev);
// - 0-9
case 45:
case 48:
case 49:
case 50:
case 51:
case 52:
case 53:
case 54:
case 55:
case 56:
case 57:
return readNumber(source, pos, code, line, col, prev);
// "
case 34:
if (charCodeAt.call(body, pos + 1) === 34 && charCodeAt.call(body, pos + 2) === 34) {
return readBlockString(source, pos, line, col, prev);
}
return readString(source, pos, line, col, prev);
}
throw (0, _error.syntaxError)(source, pos, unexpectedCharacterMessage(code));
}
/**
* Report a message that an unexpected character was encountered.
*/
function unexpectedCharacterMessage(code) {
if (code === 39) {
// '
return "Unexpected single quote character ('), did you mean to use " + 'a double quote (")?';
}
return 'Cannot parse the unexpected character ' + printCharCode(code) + '.';
}
/**
* Reads from body starting at startPosition until it finds a non-whitespace
* or commented character, then returns the position of that character for
* lexing.
*/
function positionAfterWhitespace(body, startPosition, lexer) {
var bodyLength = body.length;
var position = startPosition;
while (position < bodyLength) {
var code = charCodeAt.call(body, position);
// tab | space | comma | BOM
if (code === 9 || code === 32 || code === 44 || code === 0xfeff) {
++position;
} else if (code === 10) {
// new line
++position;
++lexer.line;
lexer.lineStart = position;
} else if (code === 13) {
// carriage return
if (charCodeAt.call(body, position + 1) === 10) {
position += 2;
} else {
++position;
}
++lexer.line;
lexer.lineStart = position;
} else {
break;
}
}
return position;
}
/**
* Reads a comment token from the source file.
*
* #[\u0009\u0020-\uFFFF]*
*/
function readComment(source, start, line, col, prev) {
var body = source.body;
var code = void 0;
var position = start;
do {
code = charCodeAt.call(body, ++position);
} while (code !== null && (
// SourceCharacter but not LineTerminator
code > 0x001f || code === 0x0009));
return new Tok(TokenKind.COMMENT, start, position, line, col, prev, slice.call(body, start + 1, position));
}
/**
* Reads a number token from the source file, either a float
* or an int depending on whether a decimal point appears.
*
* Int: -?(0|[1-9][0-9]*)
* Float: -?(0|[1-9][0-9]*)(\.[0-9]+)?((E|e)(+|-)?[0-9]+)?
*/
function readNumber(source, start, firstCode, line, col, prev) {
var body = source.body;
var code = firstCode;
var position = start;
var isFloat = false;
if (code === 45) {
// -
code = charCodeAt.call(body, ++position);
}
if (code === 48) {
// 0
code = charCodeAt.call(body, ++position);
if (code >= 48 && code <= 57) {
throw (0, _error.syntaxError)(source, position, 'Invalid number, unexpected digit after 0: ' + printCharCode(code) + '.');
}
} else {
position = readDigits(source, position, code);
code = charCodeAt.call(body, position);
}
if (code === 46) {
// .
isFloat = true;
code = charCodeAt.call(body, ++position);
position = readDigits(source, position, code);
code = charCodeAt.call(body, position);
}
if (code === 69 || code === 101) {
// E e
isFloat = true;
code = charCodeAt.call(body, ++position);
if (code === 43 || code === 45) {
// + -
code = charCodeAt.call(body, ++position);
}
position = readDigits(source, position, code);
}
return new Tok(isFloat ? TokenKind.FLOAT : TokenKind.INT, start, position, line, col, prev, slice.call(body, start, position));
}
/**
* Returns the new position in the source after reading digits.
*/
function readDigits(source, start, firstCode) {
var body = source.body;
var position = start;
var code = firstCode;
if (code >= 48 && code <= 57) {
// 0 - 9
do {
code = charCodeAt.call(body, ++position);
} while (code >= 48 && code <= 57); // 0 - 9
return position;
}
throw (0, _error.syntaxError)(source, position, 'Invalid number, expected digit but got: ' + printCharCode(code) + '.');
}
/**
* Reads a string token from the source file.
*
* "([^"\\\u000A\u000D]|(\\(u[0-9a-fA-F]{4}|["\\/bfnrt])))*"
*/
function readString(source, start, line, col, prev) {
var body = source.body;
var position = start + 1;
var chunkStart = position;
var code = 0;
var value = '';
while (position < body.length && (code = charCodeAt.call(body, position)) !== null &&
// not LineTerminator
code !== 0x000a && code !== 0x000d) {
// Closing Quote (")
if (code === 34) {
value += slice.call(body, chunkStart, position);
return new Tok(TokenKind.STRING, start, position + 1, line, col, prev, value);
}
// SourceCharacter
if (code < 0x0020 && code !== 0x0009) {
throw (0, _error.syntaxError)(source, position, 'Invalid character within String: ' + printCharCode(code) + '.');
}
++position;
if (code === 92) {
// \
value += slice.call(body, chunkStart, position - 1);
code = charCodeAt.call(body, position);
switch (code) {
case 34:
value += '"';
break;
case 47:
value += '/';
break;
case 92:
value += '\\';
break;
case 98:
value += '\b';
break;
case 102:
value += '\f';
break;
case 110:
value += '\n';
break;
case 114:
value += '\r';
break;
case 116:
value += '\t';
break;
case 117:
// u
var charCode = uniCharCode(charCodeAt.call(body, position + 1), charCodeAt.call(body, position + 2), charCodeAt.call(body, position + 3), charCodeAt.call(body, position + 4));
if (charCode < 0) {
throw (0, _error.syntaxError)(source, position, 'Invalid character escape sequence: ' + ('\\u' + body.slice(position + 1, position + 5) + '.'));
}
value += String.fromCharCode(charCode);
position += 4;
break;
default:
throw (0, _error.syntaxError)(source, position, 'Invalid character escape sequence: \\' + String.fromCharCode(code) + '.');
}
++position;
chunkStart = position;
}
}
throw (0, _error.syntaxError)(source, position, 'Unterminated string.');
}
/**
* Reads a block string token from the source file.
*
* """("?"?(\\"""|\\(?!=""")|[^"\\]))*"""
*/
function readBlockString(source, start, line, col, prev) {
var body = source.body;
var position = start + 3;
var chunkStart = position;
var code = 0;
var rawValue = '';
while (position < body.length && (code = charCodeAt.call(body, position)) !== null) {
// Closing Triple-Quote (""")
if (code === 34 && charCodeAt.call(body, position + 1) === 34 && charCodeAt.call(body, position + 2) === 34) {
rawValue += slice.call(body, chunkStart, position);
return new Tok(TokenKind.BLOCK_STRING, start, position + 3, line, col, prev, (0, _blockStringValue2.default)(rawValue));
}
// SourceCharacter
if (code < 0x0020 && code !== 0x0009 && code !== 0x000a && code !== 0x000d) {
throw (0, _error.syntaxError)(source, position, 'Invalid character within String: ' + printCharCode(code) + '.');
}
// Escape Triple-Quote (\""")
if (code === 92 && charCodeAt.call(body, position + 1) === 34 && charCodeAt.call(body, position + 2) === 34 && charCodeAt.call(body, position + 3) === 34) {
rawValue += slice.call(body, chunkStart, position) + '"""';
position += 4;
chunkStart = position;
} else {
++position;
}
}
throw (0, _error.syntaxError)(source, position, 'Unterminated string.');
}
/**
* Converts four hexidecimal chars to the integer that the
* string represents. For example, uniCharCode('0','0','0','f')
* will return 15, and uniCharCode('0','0','f','f') returns 255.
*
* Returns a negative number on error, if a char was invalid.
*
* This is implemented by noting that char2hex() returns -1 on error,
* which means the result of ORing the char2hex() will also be negative.
*/
function uniCharCode(a, b, c, d) {
return char2hex(a) << 12 | char2hex(b) << 8 | char2hex(c) << 4 | char2hex(d);
}
/**
* Converts a hex character to its integer value.
* '0' becomes 0, '9' becomes 9
* 'A' becomes 10, 'F' becomes 15
* 'a' becomes 10, 'f' becomes 15
*
* Returns -1 on error.
*/
function char2hex(a) {
return a >= 48 && a <= 57 ? a - 48 // 0-9
: a >= 65 && a <= 70 ? a - 55 // A-F
: a >= 97 && a <= 102 ? a - 87 // a-f
: -1;
}
/**
* Reads an alphanumeric + underscore name from the source.
*
* [_A-Za-z][_0-9A-Za-z]*
*/
function readName(source, start, line, col, prev) {
var body = source.body;
var bodyLength = body.length;
var position = start + 1;
var code = 0;
while (position !== bodyLength && (code = charCodeAt.call(body, position)) !== null && (code === 95 || // _
code >= 48 && code <= 57 || // 0-9
code >= 65 && code <= 90 || // A-Z
code >= 97 && code <= 122) // a-z
) {
++position;
}
return new Tok(TokenKind.NAME, start, position, line, col, prev, slice.call(body, start, position));
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy