UNPKG

52.9 kBJavaScriptView Raw
1/**
2 * Copyright 2014 Shape Security, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License")
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17"use strict";
18
19// istanbul ignore next
20
21var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; })();
22
23// istanbul ignore next
24
25var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
26
27// istanbul ignore next
28
29var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
30
31// istanbul ignore next
32
33function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
34
35// istanbul ignore next
36
37function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
38
39var _utils = require("./utils");
40
41var _errors = require("./errors");
42
43var TokenClass = {
44 Eof: { name: "<End>" },
45 Ident: { name: "Identifier", isIdentifierName: true },
46 Keyword: { name: "Keyword", isIdentifierName: true },
47 NumericLiteral: { name: "Numeric" },
48 TemplateElement: { name: "Template" },
49 Punctuator: { name: "Punctuator" },
50 StringLiteral: { name: "String" },
51 RegularExpression: { name: "RegularExpression" },
52 Illegal: { name: "Illegal" }
53};
54
55exports.TokenClass = TokenClass;
56var TokenType = {
57 EOS: { klass: TokenClass.Eof, name: "EOS" },
58 LPAREN: { klass: TokenClass.Punctuator, name: "(" },
59 RPAREN: { klass: TokenClass.Punctuator, name: ")" },
60 LBRACK: { klass: TokenClass.Punctuator, name: "[" },
61 RBRACK: { klass: TokenClass.Punctuator, name: "]" },
62 LBRACE: { klass: TokenClass.Punctuator, name: "{" },
63 RBRACE: { klass: TokenClass.Punctuator, name: "}" },
64 COLON: { klass: TokenClass.Punctuator, name: ":" },
65 SEMICOLON: { klass: TokenClass.Punctuator, name: ";" },
66 PERIOD: { klass: TokenClass.Punctuator, name: "." },
67 ELLIPSIS: { klass: TokenClass.Punctuator, name: "..." },
68 ARROW: { klass: TokenClass.Punctuator, name: "=>" },
69 CONDITIONAL: { klass: TokenClass.Punctuator, name: "?" },
70 INC: { klass: TokenClass.Punctuator, name: "++" },
71 DEC: { klass: TokenClass.Punctuator, name: "--" },
72 ASSIGN: { klass: TokenClass.Punctuator, name: "=" },
73 ASSIGN_BIT_OR: { klass: TokenClass.Punctuator, name: "|=" },
74 ASSIGN_BIT_XOR: { klass: TokenClass.Punctuator, name: "^=" },
75 ASSIGN_BIT_AND: { klass: TokenClass.Punctuator, name: "&=" },
76 ASSIGN_SHL: { klass: TokenClass.Punctuator, name: "<<=" },
77 ASSIGN_SHR: { klass: TokenClass.Punctuator, name: ">>=" },
78 ASSIGN_SHR_UNSIGNED: { klass: TokenClass.Punctuator, name: ">>>=" },
79 ASSIGN_ADD: { klass: TokenClass.Punctuator, name: "+=" },
80 ASSIGN_SUB: { klass: TokenClass.Punctuator, name: "-=" },
81 ASSIGN_MUL: { klass: TokenClass.Punctuator, name: "*=" },
82 ASSIGN_DIV: { klass: TokenClass.Punctuator, name: "/=" },
83 ASSIGN_MOD: { klass: TokenClass.Punctuator, name: "%=" },
84 COMMA: { klass: TokenClass.Punctuator, name: "," },
85 OR: { klass: TokenClass.Punctuator, name: "||" },
86 AND: { klass: TokenClass.Punctuator, name: "&&" },
87 BIT_OR: { klass: TokenClass.Punctuator, name: "|" },
88 BIT_XOR: { klass: TokenClass.Punctuator, name: "^" },
89 BIT_AND: { klass: TokenClass.Punctuator, name: "&" },
90 SHL: { klass: TokenClass.Punctuator, name: "<<" },
91 SHR: { klass: TokenClass.Punctuator, name: ">>" },
92 SHR_UNSIGNED: { klass: TokenClass.Punctuator, name: ">>>" },
93 ADD: { klass: TokenClass.Punctuator, name: "+" },
94 SUB: { klass: TokenClass.Punctuator, name: "-" },
95 MUL: { klass: TokenClass.Punctuator, name: "*" },
96 DIV: { klass: TokenClass.Punctuator, name: "/" },
97 MOD: { klass: TokenClass.Punctuator, name: "%" },
98 EQ: { klass: TokenClass.Punctuator, name: "==" },
99 NE: { klass: TokenClass.Punctuator, name: "!=" },
100 EQ_STRICT: { klass: TokenClass.Punctuator, name: "===" },
101 NE_STRICT: { klass: TokenClass.Punctuator, name: "!==" },
102 LT: { klass: TokenClass.Punctuator, name: "<" },
103 GT: { klass: TokenClass.Punctuator, name: ">" },
104 LTE: { klass: TokenClass.Punctuator, name: "<=" },
105 GTE: { klass: TokenClass.Punctuator, name: ">=" },
106 INSTANCEOF: { klass: TokenClass.Keyword, name: "instanceof" },
107 IN: { klass: TokenClass.Keyword, name: "in" },
108 NOT: { klass: TokenClass.Punctuator, name: "!" },
109 BIT_NOT: { klass: TokenClass.Punctuator, name: "~" },
110 AWAIT: { klass: TokenClass.Keyword, name: "await" },
111 DELETE: { klass: TokenClass.Keyword, name: "delete" },
112 TYPEOF: { klass: TokenClass.Keyword, name: "typeof" },
113 VOID: { klass: TokenClass.Keyword, name: "void" },
114 BREAK: { klass: TokenClass.Keyword, name: "break" },
115 CASE: { klass: TokenClass.Keyword, name: "case" },
116 CATCH: { klass: TokenClass.Keyword, name: "catch" },
117 CLASS: { klass: TokenClass.Keyword, name: "class" },
118 CONTINUE: { klass: TokenClass.Keyword, name: "continue" },
119 DEBUGGER: { klass: TokenClass.Keyword, name: "debugger" },
120 DEFAULT: { klass: TokenClass.Keyword, name: "default" },
121 DO: { klass: TokenClass.Keyword, name: "do" },
122 ELSE: { klass: TokenClass.Keyword, name: "else" },
123 EXPORT: { klass: TokenClass.Keyword, name: "export" },
124 EXTENDS: { klass: TokenClass.Keyword, name: "extends" },
125 FINALLY: { klass: TokenClass.Keyword, name: "finally" },
126 FOR: { klass: TokenClass.Keyword, name: "for" },
127 FUNCTION: { klass: TokenClass.Keyword, name: "function" },
128 IF: { klass: TokenClass.Keyword, name: "if" },
129 IMPORT: { klass: TokenClass.Keyword, name: "import" },
130 LET: { klass: TokenClass.Keyword, name: "let" },
131 NEW: { klass: TokenClass.Keyword, name: "new" },
132 RETURN: { klass: TokenClass.Keyword, name: "return" },
133 SUPER: { klass: TokenClass.Keyword, name: "super" },
134 SWITCH: { klass: TokenClass.Keyword, name: "switch" },
135 THIS: { klass: TokenClass.Keyword, name: "this" },
136 THROW: { klass: TokenClass.Keyword, name: "throw" },
137 TRY: { klass: TokenClass.Keyword, name: "try" },
138 VAR: { klass: TokenClass.Keyword, name: "var" },
139 WHILE: { klass: TokenClass.Keyword, name: "while" },
140 WITH: { klass: TokenClass.Keyword, name: "with" },
141 NULL: { klass: TokenClass.Keyword, name: "null" },
142 TRUE: { klass: TokenClass.Keyword, name: "true" },
143 FALSE: { klass: TokenClass.Keyword, name: "false" },
144 YIELD: { klass: TokenClass.Keyword, name: "yield" },
145 NUMBER: { klass: TokenClass.NumericLiteral, name: "" },
146 STRING: { klass: TokenClass.StringLiteral, name: "" },
147 REGEXP: { klass: TokenClass.RegularExpression, name: "" },
148 IDENTIFIER: { klass: TokenClass.Ident, name: "" },
149 CONST: { klass: TokenClass.Keyword, name: "const" },
150 TEMPLATE: { klass: TokenClass.TemplateElement, name: "" },
151 ILLEGAL: { klass: TokenClass.Illegal, name: "" }
152};
153
154exports.TokenType = TokenType;
155var TT = TokenType;
156var I = TT.ILLEGAL;
157var F = false;
158var T = true;
159
160var ONE_CHAR_PUNCTUATOR = [I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, TT.NOT, I, I, I, TT.MOD, TT.BIT_AND, I, TT.LPAREN, TT.RPAREN, TT.MUL, TT.ADD, TT.COMMA, TT.SUB, TT.PERIOD, TT.DIV, I, I, I, I, I, I, I, I, I, I, TT.COLON, TT.SEMICOLON, TT.LT, TT.ASSIGN, TT.GT, TT.CONDITIONAL, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, TT.LBRACK, I, TT.RBRACK, TT.BIT_XOR, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, TT.LBRACE, TT.BIT_OR, TT.RBRACE, TT.BIT_NOT];
161
162var PUNCTUATOR_START = [F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, T, F, F, F, T, T, F, T, T, T, T, T, T, F, T, F, F, F, F, F, F, F, F, F, F, T, T, T, T, T, T, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, T, F, T, T, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, T, T, T, T, F];
163
164var JsError = (function (_Error) {
165 _inherits(JsError, _Error);
166
167 function JsError(index, line, column, msg) {
168 _classCallCheck(this, JsError);
169
170 _get(Object.getPrototypeOf(JsError.prototype), "constructor", this).call(this, msg);
171 this.index = index;
172 this.line = line;
173 this.column = column;
174 this.description = msg;
175 this.message = "[" + line + ":" + column + "]: " + msg;
176 }
177
178 return JsError;
179})(Error);
180
181exports.JsError = JsError;
182
183function fromCodePoint(cp) {
184 if (cp <= 0xFFFF) return String.fromCharCode(cp);
185 var cu1 = String.fromCharCode(Math.floor((cp - 0x10000) / 0x400) + 0xD800);
186 var cu2 = String.fromCharCode((cp - 0x10000) % 0x400 + 0xDC00);
187 return cu1 + cu2;
188}
189
190function decodeUtf16(lead, trail) {
191 return (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000;
192}
193
194var Tokenizer = (function () {
195 function Tokenizer(source) {
196 _classCallCheck(this, Tokenizer);
197
198 this.source = source;
199 this.index = 0;
200 this.line = 0;
201 this.lineStart = 0;
202 this.startIndex = 0;
203 this.startLine = 0;
204 this.startLineStart = 0;
205 this.lastIndex = 0;
206 this.lastLine = 0;
207 this.lastLineStart = 0;
208 this.hasLineTerminatorBeforeNext = false;
209 this.tokenIndex = 0;
210 }
211
212 _createClass(Tokenizer, [{
213 key: "saveLexerState",
214 value: function saveLexerState() {
215 return {
216 source: this.source,
217 index: this.index,
218 line: this.line,
219 lineStart: this.lineStart,
220 startIndex: this.startIndex,
221 startLine: this.startLine,
222 startLineStart: this.startLineStart,
223 lastIndex: this.lastIndex,
224 lastLine: this.lastLine,
225 lastLineStart: this.lastLineStart,
226 lookahead: this.lookahead,
227 hasLineTerminatorBeforeNext: this.hasLineTerminatorBeforeNext,
228 tokenIndex: this.tokenIndex
229 };
230 }
231 }, {
232 key: "restoreLexerState",
233 value: function restoreLexerState(state) {
234 this.source = state.source;
235 this.index = state.index;
236 this.line = state.line;
237 this.lineStart = state.lineStart;
238 this.startIndex = state.startIndex;
239 this.startLine = state.startLine;
240 this.startLineStart = state.startLineStart;
241 this.lastIndex = state.lastIndex;
242 this.lastLine = state.lastLine;
243 this.lastLineStart = state.lastLineStart;
244 this.lookahead = state.lookahead;
245 this.hasLineTerminatorBeforeNext = state.hasLineTerminatorBeforeNext;
246 this.tokenIndex = state.tokenIndex;
247 }
248 }, {
249 key: "createILLEGAL",
250 value: function createILLEGAL() {
251 this.startIndex = this.index;
252 this.startLine = this.line;
253 this.startLineStart = this.lineStart;
254 return this.index < this.source.length ? this.createError(_errors.ErrorMessages.UNEXPECTED_ILLEGAL_TOKEN, this.source.charAt(this.index)) : this.createError(_errors.ErrorMessages.UNEXPECTED_EOS);
255 }
256 }, {
257 key: "createUnexpected",
258 value: function createUnexpected(token) {
259 switch (token.type.klass) {
260 case TokenClass.Eof:
261 return this.createError(_errors.ErrorMessages.UNEXPECTED_EOS);
262 case TokenClass.Ident:
263 return this.createError(_errors.ErrorMessages.UNEXPECTED_IDENTIFIER);
264 case TokenClass.Keyword:
265 return this.createError(_errors.ErrorMessages.UNEXPECTED_TOKEN, token.slice.text);
266 case TokenClass.NumericLiteral:
267 return this.createError(_errors.ErrorMessages.UNEXPECTED_NUMBER);
268 case TokenClass.TemplateElement:
269 return this.createError(_errors.ErrorMessages.UNEXPECTED_TEMPLATE);
270 case TokenClass.Punctuator:
271 return this.createError(_errors.ErrorMessages.UNEXPECTED_TOKEN, token.type.name);
272 case TokenClass.StringLiteral:
273 return this.createError(_errors.ErrorMessages.UNEXPECTED_STRING);
274 // the other token classes are RegularExpression and Illegal, but they cannot reach here
275 }
276 }
277 }, {
278 key: "createError",
279 value: function createError(message) {
280 // istanbul ignore next
281 var _arguments2 = arguments;
282
283 /* istanbul ignore next */
284 var msg = message.replace(/\{(\d+)\}/g, function (_, n) {
285 return JSON.stringify(_arguments2[+n + 1]);
286 });
287 return new JsError(this.startIndex, this.startLine + 1, this.startIndex - this.startLineStart + 1, msg);
288 }
289 }, {
290 key: "createErrorWithLocation",
291 value: function createErrorWithLocation(location, message) {
292 // istanbul ignore next
293 var _arguments3 = arguments;
294
295 /* istanbul ignore next */
296 var msg = message.replace(/\{(\d+)\}/g, function (_, n) {
297 return JSON.stringify(_arguments3[+n + 2]);
298 });
299 if (location.slice && location.slice.startLocation) {
300 location = location.slice.startLocation;
301 }
302 return new JsError(location.offset, location.line, location.column + 1, msg);
303 }
304 }, {
305 key: "getKeyword",
306 value: function getKeyword(id) {
307 if (id.length === 1 || id.length > 10) {
308 return TokenType.IDENTIFIER;
309 }
310
311 /* istanbul ignore next */
312 switch (id.length) {
313 case 2:
314 switch (id.charAt(0)) {
315 case "i":
316 switch (id.charAt(1)) {
317 case "f":
318 return TokenType.IF;
319 case "n":
320 return TokenType.IN;
321 default:
322 break;
323 }
324 break;
325 case "d":
326 if (id.charAt(1) === "o") {
327 return TokenType.DO;
328 }
329 break;
330 }
331 break;
332 case 3:
333 switch (id.charAt(0)) {
334 case "v":
335 if (Tokenizer.cse2(id, "a", "r")) {
336 return TokenType.VAR;
337 }
338 break;
339 case "f":
340 if (Tokenizer.cse2(id, "o", "r")) {
341 return TokenType.FOR;
342 }
343 break;
344 case "n":
345 if (Tokenizer.cse2(id, "e", "w")) {
346 return TokenType.NEW;
347 }
348 break;
349 case "t":
350 if (Tokenizer.cse2(id, "r", "y")) {
351 return TokenType.TRY;
352 }
353 break;
354 case "l":
355 if (Tokenizer.cse2(id, "e", "t")) {
356 return TokenType.LET;
357 }
358 break;
359 }
360 break;
361 case 4:
362 switch (id.charAt(0)) {
363 case "t":
364 if (Tokenizer.cse3(id, "h", "i", "s")) {
365 return TokenType.THIS;
366 } else if (Tokenizer.cse3(id, "r", "u", "e")) {
367 return TokenType.TRUE;
368 }
369 break;
370 case "n":
371 if (Tokenizer.cse3(id, "u", "l", "l")) {
372 return TokenType.NULL;
373 }
374 break;
375 case "e":
376 if (Tokenizer.cse3(id, "l", "s", "e")) {
377 return TokenType.ELSE;
378 }
379 break;
380 case "c":
381 if (Tokenizer.cse3(id, "a", "s", "e")) {
382 return TokenType.CASE;
383 }
384 break;
385 case "v":
386 if (Tokenizer.cse3(id, "o", "i", "d")) {
387 return TokenType.VOID;
388 }
389 break;
390 case "w":
391 if (Tokenizer.cse3(id, "i", "t", "h")) {
392 return TokenType.WITH;
393 }
394 break;
395 }
396 break;
397 case 5:
398 switch (id.charAt(0)) {
399 case "a":
400 if (this.moduleIsTheGoalSymbol && Tokenizer.cse4(id, "w", "a", "i", "t")) {
401 return TokenType.AWAIT;
402 }
403 break;
404 case "w":
405 if (Tokenizer.cse4(id, "h", "i", "l", "e")) {
406 return TokenType.WHILE;
407 }
408 break;
409 case "b":
410 if (Tokenizer.cse4(id, "r", "e", "a", "k")) {
411 return TokenType.BREAK;
412 }
413 break;
414 case "f":
415 if (Tokenizer.cse4(id, "a", "l", "s", "e")) {
416 return TokenType.FALSE;
417 }
418 break;
419 case "c":
420 if (Tokenizer.cse4(id, "a", "t", "c", "h")) {
421 return TokenType.CATCH;
422 } else if (Tokenizer.cse4(id, "o", "n", "s", "t")) {
423 return TokenType.CONST;
424 } else if (Tokenizer.cse4(id, "l", "a", "s", "s")) {
425 return TokenType.CLASS;
426 }
427 break;
428 case "t":
429 if (Tokenizer.cse4(id, "h", "r", "o", "w")) {
430 return TokenType.THROW;
431 }
432 break;
433 case "y":
434 if (Tokenizer.cse4(id, "i", "e", "l", "d")) {
435 return TokenType.YIELD;
436 }
437 break;
438 case "s":
439 if (Tokenizer.cse4(id, "u", "p", "e", "r")) {
440 return TokenType.SUPER;
441 }
442 break;
443 }
444 break;
445 case 6:
446 switch (id.charAt(0)) {
447 case "r":
448 if (Tokenizer.cse5(id, "e", "t", "u", "r", "n")) {
449 return TokenType.RETURN;
450 }
451 break;
452 case "t":
453 if (Tokenizer.cse5(id, "y", "p", "e", "o", "f")) {
454 return TokenType.TYPEOF;
455 }
456 break;
457 case "d":
458 if (Tokenizer.cse5(id, "e", "l", "e", "t", "e")) {
459 return TokenType.DELETE;
460 }
461 break;
462 case "s":
463 if (Tokenizer.cse5(id, "w", "i", "t", "c", "h")) {
464 return TokenType.SWITCH;
465 }
466 break;
467 case "e":
468 if (Tokenizer.cse5(id, "x", "p", "o", "r", "t")) {
469 return TokenType.EXPORT;
470 }
471 break;
472 case "i":
473 if (Tokenizer.cse5(id, "m", "p", "o", "r", "t")) {
474 return TokenType.IMPORT;
475 }
476 break;
477 }
478 break;
479 case 7:
480 switch (id.charAt(0)) {
481 case "d":
482 if (Tokenizer.cse6(id, "e", "f", "a", "u", "l", "t")) {
483 return TokenType.DEFAULT;
484 }
485 break;
486 case "f":
487 if (Tokenizer.cse6(id, "i", "n", "a", "l", "l", "y")) {
488 return TokenType.FINALLY;
489 }
490 break;
491 case "e":
492 if (Tokenizer.cse6(id, "x", "t", "e", "n", "d", "s")) {
493 return TokenType.EXTENDS;
494 }
495 break;
496 }
497 break;
498 case 8:
499 switch (id.charAt(0)) {
500 case "f":
501 if (Tokenizer.cse7(id, "u", "n", "c", "t", "i", "o", "n")) {
502 return TokenType.FUNCTION;
503 }
504 break;
505 case "c":
506 if (Tokenizer.cse7(id, "o", "n", "t", "i", "n", "u", "e")) {
507 return TokenType.CONTINUE;
508 }
509 break;
510 case "d":
511 if (Tokenizer.cse7(id, "e", "b", "u", "g", "g", "e", "r")) {
512 return TokenType.DEBUGGER;
513 }
514 break;
515 }
516 break;
517 case 10:
518 if (id === "instanceof") {
519 return TokenType.INSTANCEOF;
520 }
521 break;
522 }
523 return TokenType.IDENTIFIER;
524 }
525 }, {
526 key: "skipSingleLineComment",
527 value: function skipSingleLineComment(offset) {
528 this.index += offset;
529 while (this.index < this.source.length) {
530 /**
531 * @type {Number}
532 */
533 var chCode = this.source.charCodeAt(this.index);
534 this.index++;
535 if ((0, _utils.isLineTerminator)(chCode)) {
536 this.hasLineTerminatorBeforeNext = true;
537 if (chCode === 0xD /* "\r" */ && this.source.charCodeAt(this.index) === 0xA /*"\n" */) {
538 this.index++;
539 }
540 this.lineStart = this.index;
541 this.line++;
542 return;
543 }
544 }
545 }
546 }, {
547 key: "skipMultiLineComment",
548 value: function skipMultiLineComment() {
549 this.index += 2;
550 var length = this.source.length;
551 var isLineStart = false;
552 while (this.index < length) {
553 var chCode = this.source.charCodeAt(this.index);
554 if (chCode < 0x80) {
555 switch (chCode) {
556 case 42:
557 // "*"
558 // Block comment ends with "*/".
559 if (this.source.charAt(this.index + 1) === "/") {
560 this.index = this.index + 2;
561 return isLineStart;
562 }
563 this.index++;
564 break;
565 case 10:
566 // "\n"
567 isLineStart = true;
568 this.hasLineTerminatorBeforeNext = true;
569 this.index++;
570 this.lineStart = this.index;
571 this.line++;
572 break;
573 case 13:
574 // "\r":
575 isLineStart = true;
576 this.hasLineTerminatorBeforeNext = true;
577 if (this.source.charAt(this.index + 1) === "\n") {
578 this.index++;
579 }
580 this.index++;
581 this.lineStart = this.index;
582 this.line++;
583 break;
584 default:
585 this.index++;
586 }
587 } else if (chCode === 0x2028 || chCode === 0x2029) {
588 isLineStart = true;
589 this.hasLineTerminatorBeforeNext = true;
590 this.index++;
591 this.lineStart = this.index;
592 this.line++;
593 } else {
594 this.index++;
595 }
596 }
597 throw this.createILLEGAL();
598 }
599 }, {
600 key: "skipComment",
601 value: function skipComment() {
602 this.hasLineTerminatorBeforeNext = false;
603
604 var isLineStart = this.index === 0;
605 var length = this.source.length;
606
607 while (this.index < length) {
608 var chCode = this.source.charCodeAt(this.index);
609 if ((0, _utils.isWhiteSpace)(chCode)) {
610 this.index++;
611 } else if ((0, _utils.isLineTerminator)(chCode)) {
612 this.hasLineTerminatorBeforeNext = true;
613 this.index++;
614 if (chCode === 13 /* "\r" */ && this.source.charAt(this.index) === "\n") {
615 this.index++;
616 }
617 this.lineStart = this.index;
618 this.line++;
619 isLineStart = true;
620 } else if (chCode === 47 /* "/" */) {
621 if (this.index + 1 >= length) {
622 break;
623 }
624 chCode = this.source.charCodeAt(this.index + 1);
625 if (chCode === 47 /* "/" */) {
626 this.skipSingleLineComment(2);
627 isLineStart = true;
628 } else if (chCode === 42 /* "*" */) {
629 isLineStart = this.skipMultiLineComment() || isLineStart;
630 } else {
631 break;
632 }
633 } else if (!this.moduleIsTheGoalSymbol && isLineStart && chCode === 45 /* "-" */) {
634 if (this.index + 2 >= length) {
635 break;
636 }
637 // U+003E is ">"
638 if (this.source.charAt(this.index + 1) === "-" && this.source.charAt(this.index + 2) === ">") {
639 // "-->" is a single-line comment
640 this.skipSingleLineComment(3);
641 } else {
642 break;
643 }
644 } else if (!this.moduleIsTheGoalSymbol && chCode === 60 /* "<" */) {
645 if (this.source.slice(this.index + 1, this.index + 4) === "!--") {
646 this.skipSingleLineComment(4);
647 } else {
648 break;
649 }
650 } else {
651 break;
652 }
653 }
654 }
655 }, {
656 key: "scanHexEscape2",
657 value: function scanHexEscape2() {
658 if (this.index + 2 > this.source.length) {
659 return -1;
660 }
661 var r1 = (0, _utils.getHexValue)(this.source.charAt(this.index));
662 if (r1 === -1) {
663 return -1;
664 }
665 var r2 = (0, _utils.getHexValue)(this.source.charAt(this.index + 1));
666 if (r2 === -1) {
667 return -1;
668 }
669 this.index += 2;
670 return r1 << 4 | r2;
671 }
672 }, {
673 key: "scanUnicode",
674 value: function scanUnicode() {
675 if (this.source.charAt(this.index) === "{") {
676 //\u{HexDigits}
677 var i = this.index + 1;
678 var hexDigits = 0,
679 ch = undefined;
680 while (i < this.source.length) {
681 ch = this.source.charAt(i);
682 var hex = (0, _utils.getHexValue)(ch);
683 if (hex === -1) {
684 break;
685 }
686 hexDigits = hexDigits << 4 | hex;
687 if (hexDigits > 0x10FFFF) {
688 throw this.createILLEGAL();
689 }
690 i++;
691 }
692 if (ch !== "}") {
693 throw this.createILLEGAL();
694 }
695 this.index = i + 1;
696 return hexDigits;
697 } else {
698 //\uHex4Digits
699 if (this.index + 4 > this.source.length) {
700 return -1;
701 }
702 var r1 = (0, _utils.getHexValue)(this.source.charAt(this.index));
703 if (r1 === -1) {
704 return -1;
705 }
706 var r2 = (0, _utils.getHexValue)(this.source.charAt(this.index + 1));
707 if (r2 === -1) {
708 return -1;
709 }
710 var r3 = (0, _utils.getHexValue)(this.source.charAt(this.index + 2));
711 if (r3 === -1) {
712 return -1;
713 }
714 var r4 = (0, _utils.getHexValue)(this.source.charAt(this.index + 3));
715 if (r4 === -1) {
716 return -1;
717 }
718 this.index += 4;
719 return r1 << 12 | r2 << 8 | r3 << 4 | r4;
720 }
721 }
722 }, {
723 key: "getEscapedIdentifier",
724 value: function getEscapedIdentifier() {
725 var id = "";
726 var check = _utils.isIdentifierStart;
727
728 while (this.index < this.source.length) {
729 var ch = this.source.charAt(this.index);
730 var code = ch.charCodeAt(0);
731 var start = this.index;
732 ++this.index;
733 if (ch === "\\") {
734 if (this.index >= this.source.length) {
735 throw this.createILLEGAL();
736 }
737 if (this.source.charAt(this.index) !== "u") {
738 throw this.createILLEGAL();
739 }
740 ++this.index;
741 code = this.scanUnicode();
742 if (code < 0) {
743 throw this.createILLEGAL();
744 }
745 ch = fromCodePoint(code);
746 } else if (0xD800 <= code && code <= 0xDBFF) {
747 if (this.index >= this.source.length) {
748 throw this.createILLEGAL();
749 }
750 var lowSurrogateCode = this.source.charCodeAt(this.index);
751 ++this.index;
752 if (!(0xDC00 <= lowSurrogateCode && lowSurrogateCode <= 0xDFFF)) {
753 throw this.createILLEGAL();
754 }
755 code = decodeUtf16(code, lowSurrogateCode);
756 ch = fromCodePoint(code);
757 }
758 if (!check(code)) {
759 if (id.length < 1) {
760 throw this.createILLEGAL();
761 }
762 this.index = start;
763 return id;
764 }
765 check = _utils.isIdentifierPart;
766 id += ch;
767 }
768 return id;
769 }
770 }, {
771 key: "getIdentifier",
772 value: function getIdentifier() {
773 var start = this.index;
774 var l = this.source.length;
775 var i = this.index;
776 var check = _utils.isIdentifierStart;
777 while (i < l) {
778 var ch = this.source.charAt(i);
779 var code = ch.charCodeAt(0);
780 if (ch === "\\" || 0xD800 <= code && code <= 0xDBFF) {
781 // Go back and try the hard one.
782 this.index = start;
783 return this.getEscapedIdentifier();
784 }
785 if (!check(code)) {
786 this.index = i;
787 return this.source.slice(start, i);
788 }
789 ++i;
790 check = _utils.isIdentifierPart;
791 }
792 this.index = i;
793 return this.source.slice(start, i);
794 }
795 }, {
796 key: "scanIdentifier",
797 value: function scanIdentifier() {
798 var startLocation = this.getLocation();
799 var start = this.index;
800
801 // Backslash (U+005C) starts an escaped character.
802 var id = this.source.charAt(this.index) === "\\" ? this.getEscapedIdentifier() : this.getIdentifier();
803
804 // There is no keyword or literal with only one character.
805 // Thus, it must be an identifier.
806 var slice = this.getSlice(start, startLocation);
807 slice.text = id;
808
809 return { type: this.getKeyword(id), value: id, slice: slice };
810 }
811 }, {
812 key: "getLocation",
813 value: function getLocation() {
814 return {
815 line: this.startLine + 1,
816 column: this.startIndex - this.startLineStart,
817 offset: this.startIndex
818 };
819 }
820 }, {
821 key: "getSlice",
822 value: function getSlice(start, startLocation) {
823 return { text: this.source.slice(start, this.index), start: start, startLocation: startLocation, end: this.index };
824 }
825 }, {
826 key: "scanPunctuatorHelper",
827 value: function scanPunctuatorHelper() {
828 var ch1 = this.source.charAt(this.index);
829
830 switch (ch1) {
831 // Check for most common single-character punctuators.
832 case ".":
833 var ch2 = this.source.charAt(this.index + 1);
834 if (ch2 !== ".") return TokenType.PERIOD;
835 var ch3 = this.source.charAt(this.index + 2);
836 if (ch3 !== ".") return TokenType.PERIOD;
837 return TokenType.ELLIPSIS;
838 case "(":
839 return TokenType.LPAREN;
840 case ")":
841 case ";":
842 case ",":
843 return ONE_CHAR_PUNCTUATOR[ch1.charCodeAt(0)];
844 case "{":
845 return TokenType.LBRACE;
846 case "}":
847 case "[":
848 case "]":
849 case ":":
850 case "?":
851 case "~":
852 return ONE_CHAR_PUNCTUATOR[ch1.charCodeAt(0)];
853 default:
854 // "=" (U+003D) marks an assignment or comparison operator.
855 if (this.index + 1 < this.source.length && this.source.charAt(this.index + 1) === "=") {
856 switch (ch1) {
857 case "=":
858 if (this.index + 2 < this.source.length && this.source.charAt(this.index + 2) === "=") {
859 return TokenType.EQ_STRICT;
860 }
861 return TokenType.EQ;
862 case "!":
863 if (this.index + 2 < this.source.length && this.source.charAt(this.index + 2) === "=") {
864 return TokenType.NE_STRICT;
865 }
866 return TokenType.NE;
867 case "|":
868 return TokenType.ASSIGN_BIT_OR;
869 case "+":
870 return TokenType.ASSIGN_ADD;
871 case "-":
872 return TokenType.ASSIGN_SUB;
873 case "*":
874 return TokenType.ASSIGN_MUL;
875 case "<":
876 return TokenType.LTE;
877 case ">":
878 return TokenType.GTE;
879 case "/":
880 return TokenType.ASSIGN_DIV;
881 case "%":
882 return TokenType.ASSIGN_MOD;
883 case "^":
884 return TokenType.ASSIGN_BIT_XOR;
885 case "&":
886 return TokenType.ASSIGN_BIT_AND;
887 // istanbul ignore next
888 default:
889 break; //failed
890 }
891 }
892 }
893
894 if (this.index + 1 < this.source.length) {
895 var ch2 = this.source.charAt(this.index + 1);
896 if (ch1 === ch2) {
897 if (this.index + 2 < this.source.length) {
898 var ch3 = this.source.charAt(this.index + 2);
899 if (ch1 === ">" && ch3 === ">") {
900 // 4-character punctuator: >>>=
901 if (this.index + 3 < this.source.length && this.source.charAt(this.index + 3) === "=") {
902 return TokenType.ASSIGN_SHR_UNSIGNED;
903 }
904 return TokenType.SHR_UNSIGNED;
905 }
906
907 if (ch1 === "<" && ch3 === "=") {
908 return TokenType.ASSIGN_SHL;
909 }
910
911 if (ch1 === ">" && ch3 === "=") {
912 return TokenType.ASSIGN_SHR;
913 }
914 }
915 // Other 2-character punctuators: ++ -- << >> && ||
916 switch (ch1) {
917 case "+":
918 return TokenType.INC;
919 case "-":
920 return TokenType.DEC;
921 case "<":
922 return TokenType.SHL;
923 case ">":
924 return TokenType.SHR;
925 case "&":
926 return TokenType.AND;
927 case "|":
928 return TokenType.OR;
929 // istanbul ignore next
930 default:
931 break; //failed
932 }
933 } else if (ch1 === "=" && ch2 === ">") {
934 return TokenType.ARROW;
935 }
936 }
937
938 return ONE_CHAR_PUNCTUATOR[ch1.charCodeAt(0)];
939 }
940
941 // 7.7 Punctuators
942 }, {
943 key: "scanPunctuator",
944 value: function scanPunctuator() {
945 var startLocation = this.getLocation();
946 var start = this.index;
947 var subType = this.scanPunctuatorHelper();
948 this.index += subType.name.length;
949 return { type: subType, value: subType.name, slice: this.getSlice(start, startLocation) };
950 }
951 }, {
952 key: "scanHexLiteral",
953 value: function scanHexLiteral(start, startLocation) {
954 var i = this.index;
955 while (i < this.source.length) {
956 var ch = this.source.charAt(i);
957 var hex = (0, _utils.getHexValue)(ch);
958 if (hex === -1) {
959 break;
960 }
961 i++;
962 }
963
964 if (this.index === i) {
965 throw this.createILLEGAL();
966 }
967
968 if (i < this.source.length && (0, _utils.isIdentifierStart)(this.source.charCodeAt(i))) {
969 throw this.createILLEGAL();
970 }
971
972 this.index = i;
973
974 var slice = this.getSlice(start, startLocation);
975 return { type: TokenType.NUMBER, value: parseInt(slice.text.substr(2), 16), slice: slice };
976 }
977 }, {
978 key: "scanBinaryLiteral",
979 value: function scanBinaryLiteral(start, startLocation) {
980 var offset = this.index - start;
981
982 while (this.index < this.source.length) {
983 var ch = this.source.charAt(this.index);
984 if (ch !== "0" && ch !== "1") {
985 break;
986 }
987 this.index++;
988 }
989
990 if (this.index - start <= offset) {
991 throw this.createILLEGAL();
992 }
993
994 if (this.index < this.source.length && ((0, _utils.isIdentifierStart)(this.source.charCodeAt(this.index)) || (0, _utils.isDecimalDigit)(this.source.charCodeAt(this.index)))) {
995 throw this.createILLEGAL();
996 }
997
998 return {
999 type: TokenType.NUMBER,
1000 value: parseInt(this.getSlice(start, startLocation).text.substr(offset), 2),
1001 slice: this.getSlice(start, startLocation),
1002 octal: false,
1003 noctal: false
1004 };
1005 }
1006 }, {
1007 key: "scanOctalLiteral",
1008 value: function scanOctalLiteral(start, startLocation) {
1009 while (this.index < this.source.length) {
1010 var ch = this.source.charAt(this.index);
1011 if ("0" <= ch && ch <= "7") {
1012 this.index++;
1013 } else if ((0, _utils.isIdentifierPart)(ch.charCodeAt(0))) {
1014 throw this.createILLEGAL();
1015 } else {
1016 break;
1017 }
1018 }
1019
1020 if (this.index - start === 2) {
1021 throw this.createILLEGAL();
1022 }
1023
1024 return {
1025 type: TokenType.NUMBER,
1026 value: parseInt(this.getSlice(start, startLocation).text.substr(2), 8),
1027 slice: this.getSlice(start, startLocation),
1028 octal: false,
1029 noctal: false
1030 };
1031 }
1032 }, {
1033 key: "scanLegacyOctalLiteral",
1034 value: function scanLegacyOctalLiteral(start, startLocation) {
1035 var isOctal = true;
1036
1037 while (this.index < this.source.length) {
1038 var ch = this.source.charAt(this.index);
1039 if ("0" <= ch && ch <= "7") {
1040 this.index++;
1041 } else if (ch === "8" || ch === "9") {
1042 isOctal = false;
1043 this.index++;
1044 } else if ((0, _utils.isIdentifierPart)(ch.charCodeAt(0))) {
1045 throw this.createILLEGAL();
1046 } else {
1047 break;
1048 }
1049 }
1050
1051 return {
1052 type: TokenType.NUMBER,
1053 slice: this.getSlice(start, startLocation),
1054 value: parseInt(this.getSlice(start, startLocation).text.substr(1), isOctal ? 8 : 10),
1055 octal: true,
1056 noctal: !isOctal
1057 };
1058 }
1059 }, {
1060 key: "scanNumericLiteral",
1061 value: function scanNumericLiteral() {
1062 var ch = this.source.charAt(this.index);
1063 // assert(ch === "." || "0" <= ch && ch <= "9")
1064 var startLocation = this.getLocation();
1065 var start = this.index;
1066
1067 if (ch === "0") {
1068 this.index++;
1069 if (this.index < this.source.length) {
1070 ch = this.source.charAt(this.index);
1071 if (ch === "x" || ch === "X") {
1072 this.index++;
1073 return this.scanHexLiteral(start, startLocation);
1074 } else if (ch === "b" || ch === "B") {
1075 this.index++;
1076 return this.scanBinaryLiteral(start, startLocation);
1077 } else if (ch === "o" || ch === "O") {
1078 this.index++;
1079 return this.scanOctalLiteral(start, startLocation);
1080 } else if ("0" <= ch && ch <= "9") {
1081 return this.scanLegacyOctalLiteral(start, startLocation);
1082 }
1083 } else {
1084 var _slice = this.getSlice(start, startLocation);
1085 return {
1086 type: TokenType.NUMBER,
1087 value: +_slice.text,
1088 slice: _slice,
1089 octal: false,
1090 noctal: false
1091 };
1092 }
1093 } else if (ch !== ".") {
1094 // Must be "1".."9"
1095 ch = this.source.charAt(this.index);
1096 while ("0" <= ch && ch <= "9") {
1097 this.index++;
1098 if (this.index === this.source.length) {
1099 var _slice2 = this.getSlice(start, startLocation);
1100 return {
1101 type: TokenType.NUMBER,
1102 value: +_slice2.text,
1103 slice: _slice2,
1104 octal: false,
1105 noctal: false
1106 };
1107 }
1108 ch = this.source.charAt(this.index);
1109 }
1110 }
1111
1112 var e = 0;
1113 if (ch === ".") {
1114 this.index++;
1115 if (this.index === this.source.length) {
1116 var _slice3 = this.getSlice(start, startLocation);
1117 return {
1118 type: TokenType.NUMBER,
1119 value: +_slice3.text,
1120 slice: _slice3,
1121 octal: false,
1122 noctal: false
1123 };
1124 }
1125
1126 ch = this.source.charAt(this.index);
1127 while ("0" <= ch && ch <= "9") {
1128 e++;
1129 this.index++;
1130 if (this.index === this.source.length) {
1131 var _slice4 = this.getSlice(start, startLocation);
1132 return {
1133 type: TokenType.NUMBER,
1134 value: +_slice4.text,
1135 slice: _slice4,
1136 octal: false,
1137 noctal: false
1138 };
1139 }
1140 ch = this.source.charAt(this.index);
1141 }
1142 }
1143
1144 // EOF not reached here
1145 if (ch === "e" || ch === "E") {
1146 this.index++;
1147 if (this.index === this.source.length) {
1148 throw this.createILLEGAL();
1149 }
1150
1151 ch = this.source.charAt(this.index);
1152 var neg = false;
1153 if (ch === "+" || ch === "-") {
1154 neg = ch === "-";
1155 this.index++;
1156 if (this.index === this.source.length) {
1157 throw this.createILLEGAL();
1158 }
1159 ch = this.source.charAt(this.index);
1160 }
1161
1162 var f = 0;
1163 if ("0" <= ch && ch <= "9") {
1164 while ("0" <= ch && ch <= "9") {
1165 f *= 10;
1166 f += +ch;
1167 this.index++;
1168 if (this.index === this.source.length) {
1169 break;
1170 }
1171 ch = this.source.charAt(this.index);
1172 }
1173 } else {
1174 throw this.createILLEGAL();
1175 }
1176 e += neg ? f : -f;
1177 }
1178
1179 if ((0, _utils.isIdentifierStart)(ch.charCodeAt(0))) {
1180 throw this.createILLEGAL();
1181 }
1182
1183 var slice = this.getSlice(start, startLocation);
1184 return {
1185 type: TokenType.NUMBER,
1186 value: +slice.text,
1187 slice: slice,
1188 octal: false,
1189 noctal: false
1190 };
1191 }
1192 }, {
1193 key: "scanStringEscape",
1194 value: function scanStringEscape(str, octal) {
1195 this.index++;
1196 if (this.index === this.source.length) {
1197 throw this.createILLEGAL();
1198 }
1199 var ch = this.source.charAt(this.index);
1200 if (!(0, _utils.isLineTerminator)(ch.charCodeAt(0))) {
1201 switch (ch) {
1202 case "n":
1203 str += "\n";
1204 this.index++;
1205 break;
1206 case "r":
1207 str += "\r";
1208 this.index++;
1209 break;
1210 case "t":
1211 str += "\t";
1212 this.index++;
1213 break;
1214 case "u":
1215 case "x":
1216 var unescaped = undefined;
1217 this.index++;
1218 if (this.index >= this.source.length) {
1219 throw this.createILLEGAL();
1220 }
1221 unescaped = ch === "u" ? this.scanUnicode() : this.scanHexEscape2();
1222 if (unescaped < 0) {
1223 throw this.createILLEGAL();
1224 }
1225 str += fromCodePoint(unescaped);
1226 break;
1227 case "b":
1228 str += "\b";
1229 this.index++;
1230 break;
1231 case "f":
1232 str += "\f";
1233 this.index++;
1234 break;
1235 case "v":
1236 str += "\u000b";
1237 this.index++;
1238 break;
1239 default:
1240 if ("0" <= ch && ch <= "7") {
1241 var octalStart = this.index;
1242 var octLen = 1;
1243 // 3 digits are only allowed when string starts
1244 // with 0, 1, 2, 3
1245 if ("0" <= ch && ch <= "3") {
1246 octLen = 0;
1247 }
1248 var code = 0;
1249 while (octLen < 3 && "0" <= ch && ch <= "7") {
1250 this.index++;
1251 if (octLen > 0 || ch !== "0") {
1252 octal = this.source.slice(octalStart, this.index);
1253 }
1254 code *= 8;
1255 code += ch - "0";
1256 octLen++;
1257 if (this.index === this.source.length) {
1258 throw this.createILLEGAL();
1259 }
1260 ch = this.source.charAt(this.index);
1261 }
1262 str += String.fromCharCode(code);
1263 } else if (ch === "8" || ch === "9") {
1264 throw this.createILLEGAL();
1265 } else {
1266 str += ch;
1267 this.index++;
1268 }
1269 }
1270 } else {
1271 this.index++;
1272 if (ch === "\r" && this.source.charAt(this.index) === "\n") {
1273 this.index++;
1274 }
1275 this.lineStart = this.index;
1276 this.line++;
1277 }
1278 return [str, octal];
1279 }
1280
1281 // 7.8.4 String Literals
1282 }, {
1283 key: "scanStringLiteral",
1284 value: function scanStringLiteral() {
1285 var str = "";
1286
1287 var quote = this.source.charAt(this.index);
1288 // assert((quote === "\"" || quote === """), "String literal must starts with a quote")
1289
1290 var startLocation = this.getLocation();
1291 var start = this.index;
1292 this.index++;
1293
1294 var octal = null;
1295 while (this.index < this.source.length) {
1296 var ch = this.source.charAt(this.index);
1297 if (ch === quote) {
1298 this.index++;
1299 return { type: TokenType.STRING, slice: this.getSlice(start, startLocation), str: str, octal: octal };
1300 } else if (ch === "\\") {
1301 var _scanStringEscape = this.scanStringEscape(str, octal);
1302
1303 var _scanStringEscape2 = _slicedToArray(_scanStringEscape, 2);
1304
1305 str = _scanStringEscape2[0];
1306 octal = _scanStringEscape2[1];
1307 } else if ((0, _utils.isLineTerminator)(ch.charCodeAt(0))) {
1308 throw this.createILLEGAL();
1309 } else {
1310 str += ch;
1311 this.index++;
1312 }
1313 }
1314
1315 throw this.createILLEGAL();
1316 }
1317 }, {
1318 key: "scanTemplateElement",
1319 value: function scanTemplateElement() {
1320 var startLocation = this.getLocation();
1321 var start = this.index;
1322 this.index++;
1323 while (this.index < this.source.length) {
1324 var ch = this.source.charCodeAt(this.index);
1325 switch (ch) {
1326 case 0x60:
1327 // `
1328 this.index++;
1329 return { type: TokenType.TEMPLATE, tail: true, slice: this.getSlice(start, startLocation) };
1330 case 0x24:
1331 // $
1332 if (this.source.charCodeAt(this.index + 1) === 0x7B) {
1333 // {
1334 this.index += 2;
1335 return { type: TokenType.TEMPLATE, tail: false, slice: this.getSlice(start, startLocation) };
1336 }
1337 this.index++;
1338 break;
1339 case 0x5C:
1340 // \\
1341 {
1342 var octal = this.scanStringEscape("", null)[1];
1343 if (octal != null) {
1344 throw this.createILLEGAL();
1345 }
1346 break;
1347 }
1348 default:
1349 this.index++;
1350 }
1351 }
1352
1353 throw this.createILLEGAL();
1354 }
1355 }, {
1356 key: "scanRegExp",
1357 value: function scanRegExp(str) {
1358 var startLocation = this.getLocation();
1359 var start = this.index;
1360
1361 var terminated = false;
1362 var classMarker = false;
1363 while (this.index < this.source.length) {
1364 var ch = this.source.charAt(this.index);
1365 if (ch === "\\") {
1366 str += ch;
1367 this.index++;
1368 ch = this.source.charAt(this.index);
1369 // ECMA-262 7.8.5
1370 if ((0, _utils.isLineTerminator)(ch.charCodeAt(0))) {
1371 throw this.createError(_errors.ErrorMessages.UNTERMINATED_REGEXP);
1372 }
1373 str += ch;
1374 this.index++;
1375 } else if ((0, _utils.isLineTerminator)(ch.charCodeAt(0))) {
1376 throw this.createError(_errors.ErrorMessages.UNTERMINATED_REGEXP);
1377 } else {
1378 if (classMarker) {
1379 if (ch === "]") {
1380 classMarker = false;
1381 }
1382 } else {
1383 if (ch === "/") {
1384 terminated = true;
1385 str += ch;
1386 this.index++;
1387 break;
1388 } else if (ch === "[") {
1389 classMarker = true;
1390 }
1391 }
1392 str += ch;
1393 this.index++;
1394 }
1395 }
1396
1397 if (!terminated) {
1398 throw this.createError(_errors.ErrorMessages.UNTERMINATED_REGEXP);
1399 }
1400
1401 while (this.index < this.source.length) {
1402 var ch = this.source.charAt(this.index);
1403 if (ch === "\\") {
1404 throw this.createError(_errors.ErrorMessages.INVALID_REGEXP_FLAGS);
1405 }
1406 if (!(0, _utils.isIdentifierPart)(ch.charCodeAt(0))) {
1407 break;
1408 }
1409 this.index++;
1410 str += ch;
1411 }
1412 return { type: TokenType.REGEXP, value: str, slice: this.getSlice(start, startLocation) };
1413 }
1414 }, {
1415 key: "advance",
1416 value: function advance() {
1417 var startLocation = this.getLocation();
1418
1419 this.lastIndex = this.index;
1420 this.lastLine = this.line;
1421 this.lastLineStart = this.lineStart;
1422
1423 this.skipComment();
1424
1425 this.startIndex = this.index;
1426 this.startLine = this.line;
1427 this.startLineStart = this.lineStart;
1428
1429 if (this.lastIndex === 0) {
1430 this.lastIndex = this.index;
1431 this.lastLine = this.line;
1432 this.lastLineStart = this.lineStart;
1433 }
1434
1435 if (this.index >= this.source.length) {
1436 return { type: TokenType.EOS, slice: this.getSlice(this.index, startLocation) };
1437 }
1438
1439 var charCode = this.source.charCodeAt(this.index);
1440
1441 if (charCode < 0x80) {
1442 if (PUNCTUATOR_START[charCode]) {
1443 return this.scanPunctuator();
1444 }
1445
1446 if ((0, _utils.isIdentifierStart)(charCode) || charCode === 0x5C /* backslash (\) */) {
1447 return this.scanIdentifier();
1448 }
1449
1450 // Dot (.) U+002E can also start a floating-point number, hence the need
1451 // to check the next character.
1452 if (charCode === 0x2E) {
1453 if (this.index + 1 < this.source.length && (0, _utils.isDecimalDigit)(this.source.charCodeAt(this.index + 1))) {
1454 return this.scanNumericLiteral();
1455 }
1456 return this.scanPunctuator();
1457 }
1458
1459 // String literal starts with single quote (U+0027) or double quote (U+0022).
1460 if (charCode === 0x27 || charCode === 0x22) {
1461 return this.scanStringLiteral();
1462 }
1463
1464 // Template literal starts with back quote (U+0060)
1465 if (charCode === 0x60) {
1466 return this.scanTemplateElement();
1467 }
1468
1469 if (0x30 /* "0" */ <= charCode && charCode <= 0x39 /* "9" */) {
1470 return this.scanNumericLiteral();
1471 }
1472
1473 // Slash (/) U+002F can also start a regex.
1474 throw this.createILLEGAL();
1475 } else {
1476 if ((0, _utils.isIdentifierStart)(charCode) || 0xD800 <= charCode && charCode <= 0xDBFF) {
1477 return this.scanIdentifier();
1478 }
1479
1480 throw this.createILLEGAL();
1481 }
1482 }
1483 }, {
1484 key: "eof",
1485 value: function eof() {
1486 return this.lookahead.type === TokenType.EOS;
1487 }
1488 }, {
1489 key: "lex",
1490 value: function lex() {
1491 var prevToken = this.lookahead;
1492 this.lookahead = this.advance();
1493 this.tokenIndex++;
1494 return prevToken;
1495 }
1496 }], [{
1497 key: "cse2",
1498 value: function cse2(id, ch1, ch2) {
1499 return id.charAt(1) === ch1 && id.charAt(2) === ch2;
1500 }
1501 }, {
1502 key: "cse3",
1503 value: function cse3(id, ch1, ch2, ch3) {
1504 return id.charAt(1) === ch1 && id.charAt(2) === ch2 && id.charAt(3) === ch3;
1505 }
1506 }, {
1507 key: "cse4",
1508 value: function cse4(id, ch1, ch2, ch3, ch4) {
1509 return id.charAt(1) === ch1 && id.charAt(2) === ch2 && id.charAt(3) === ch3 && id.charAt(4) === ch4;
1510 }
1511 }, {
1512 key: "cse5",
1513 value: function cse5(id, ch1, ch2, ch3, ch4, ch5) {
1514 return id.charAt(1) === ch1 && id.charAt(2) === ch2 && id.charAt(3) === ch3 && id.charAt(4) === ch4 && id.charAt(5) === ch5;
1515 }
1516 }, {
1517 key: "cse6",
1518 value: function cse6(id, ch1, ch2, ch3, ch4, ch5, ch6) {
1519 return id.charAt(1) === ch1 && id.charAt(2) === ch2 && id.charAt(3) === ch3 && id.charAt(4) === ch4 && id.charAt(5) === ch5 && id.charAt(6) === ch6;
1520 }
1521 }, {
1522 key: "cse7",
1523 value: function cse7(id, ch1, ch2, ch3, ch4, ch5, ch6, ch7) {
1524 return id.charAt(1) === ch1 && id.charAt(2) === ch2 && id.charAt(3) === ch3 && id.charAt(4) === ch4 && id.charAt(5) === ch5 && id.charAt(6) === ch6 && id.charAt(7) === ch7;
1525 }
1526 }]);
1527
1528 return Tokenizer;
1529})();
1530
1531exports["default"] = Tokenizer;
\No newline at end of file