1 |
|
2 |
|
3 | import {input, isFlowEnabled, state} from "../traverser/base";
|
4 | import {unexpected} from "../traverser/util";
|
5 | import {charCodes} from "../util/charcodes";
|
6 | import {IS_IDENTIFIER_CHAR, IS_IDENTIFIER_START} from "../util/identifier";
|
7 | import {IS_WHITESPACE} from "../util/whitespace";
|
8 | import {ContextualKeyword} from "./keywords";
|
9 | import readWord from "./readWord";
|
10 | import { TokenType as tt} from "./types";
|
11 |
|
12 | export var IdentifierRole; (function (IdentifierRole) {
|
13 | const Access = 0; IdentifierRole[IdentifierRole["Access"] = Access] = "Access";
|
14 | const ExportAccess = Access + 1; IdentifierRole[IdentifierRole["ExportAccess"] = ExportAccess] = "ExportAccess";
|
15 | const TopLevelDeclaration = ExportAccess + 1; IdentifierRole[IdentifierRole["TopLevelDeclaration"] = TopLevelDeclaration] = "TopLevelDeclaration";
|
16 | const FunctionScopedDeclaration = TopLevelDeclaration + 1; IdentifierRole[IdentifierRole["FunctionScopedDeclaration"] = FunctionScopedDeclaration] = "FunctionScopedDeclaration";
|
17 | const BlockScopedDeclaration = FunctionScopedDeclaration + 1; IdentifierRole[IdentifierRole["BlockScopedDeclaration"] = BlockScopedDeclaration] = "BlockScopedDeclaration";
|
18 | const ObjectShorthandTopLevelDeclaration = BlockScopedDeclaration + 1; IdentifierRole[IdentifierRole["ObjectShorthandTopLevelDeclaration"] = ObjectShorthandTopLevelDeclaration] = "ObjectShorthandTopLevelDeclaration";
|
19 | const ObjectShorthandFunctionScopedDeclaration = ObjectShorthandTopLevelDeclaration + 1; IdentifierRole[IdentifierRole["ObjectShorthandFunctionScopedDeclaration"] = ObjectShorthandFunctionScopedDeclaration] = "ObjectShorthandFunctionScopedDeclaration";
|
20 | const ObjectShorthandBlockScopedDeclaration = ObjectShorthandFunctionScopedDeclaration + 1; IdentifierRole[IdentifierRole["ObjectShorthandBlockScopedDeclaration"] = ObjectShorthandBlockScopedDeclaration] = "ObjectShorthandBlockScopedDeclaration";
|
21 | const ObjectShorthand = ObjectShorthandBlockScopedDeclaration + 1; IdentifierRole[IdentifierRole["ObjectShorthand"] = ObjectShorthand] = "ObjectShorthand";
|
22 | const ObjectKey = ObjectShorthand + 1; IdentifierRole[IdentifierRole["ObjectKey"] = ObjectKey] = "ObjectKey";
|
23 | })(IdentifierRole || (IdentifierRole = {}));
|
24 |
|
25 | export function isDeclaration(token) {
|
26 | const role = token.identifierRole;
|
27 | return (
|
28 | role === IdentifierRole.TopLevelDeclaration ||
|
29 | role === IdentifierRole.FunctionScopedDeclaration ||
|
30 | role === IdentifierRole.BlockScopedDeclaration ||
|
31 | role === IdentifierRole.ObjectShorthandTopLevelDeclaration ||
|
32 | role === IdentifierRole.ObjectShorthandFunctionScopedDeclaration ||
|
33 | role === IdentifierRole.ObjectShorthandBlockScopedDeclaration
|
34 | );
|
35 | }
|
36 |
|
37 | export function isNonTopLevelDeclaration(token) {
|
38 | const role = token.identifierRole;
|
39 | return (
|
40 | role === IdentifierRole.FunctionScopedDeclaration ||
|
41 | role === IdentifierRole.BlockScopedDeclaration ||
|
42 | role === IdentifierRole.ObjectShorthandFunctionScopedDeclaration ||
|
43 | role === IdentifierRole.ObjectShorthandBlockScopedDeclaration
|
44 | );
|
45 | }
|
46 |
|
47 | export function isBlockScopedDeclaration(token) {
|
48 | const role = token.identifierRole;
|
49 |
|
50 | return (
|
51 | role === IdentifierRole.TopLevelDeclaration ||
|
52 | role === IdentifierRole.BlockScopedDeclaration ||
|
53 | role === IdentifierRole.ObjectShorthandTopLevelDeclaration ||
|
54 | role === IdentifierRole.ObjectShorthandBlockScopedDeclaration
|
55 | );
|
56 | }
|
57 |
|
58 | export function isFunctionScopedDeclaration(token) {
|
59 | const role = token.identifierRole;
|
60 | return (
|
61 | role === IdentifierRole.FunctionScopedDeclaration ||
|
62 | role === IdentifierRole.ObjectShorthandFunctionScopedDeclaration
|
63 | );
|
64 | }
|
65 |
|
66 | export function isObjectShorthandDeclaration(token) {
|
67 | return (
|
68 | token.identifierRole === IdentifierRole.ObjectShorthandTopLevelDeclaration ||
|
69 | token.identifierRole === IdentifierRole.ObjectShorthandBlockScopedDeclaration ||
|
70 | token.identifierRole === IdentifierRole.ObjectShorthandFunctionScopedDeclaration
|
71 | );
|
72 | }
|
73 |
|
74 |
|
75 |
|
76 |
|
77 | export class Token {
|
78 | constructor() {
|
79 | this.type = state.type;
|
80 | this.contextualKeyword = state.contextualKeyword;
|
81 | this.start = state.start;
|
82 | this.end = state.end;
|
83 | this.isType = state.isType;
|
84 | this.identifierRole = null;
|
85 | this.shadowsGlobal = false;
|
86 | this.contextId = null;
|
87 | this.rhsEndIndex = null;
|
88 | this.isExpression = false;
|
89 | }
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 |
|
104 | }
|
105 |
|
106 |
|
107 |
|
108 |
|
109 | export function next() {
|
110 | state.tokens.push(new Token());
|
111 | nextToken();
|
112 | }
|
113 |
|
114 |
|
115 | export function nextTemplateToken() {
|
116 | state.tokens.push(new Token());
|
117 | state.start = state.pos;
|
118 | readTmplToken();
|
119 | }
|
120 |
|
121 |
|
122 |
|
123 | export function retokenizeSlashAsRegex() {
|
124 | if (state.type === tt.assign) {
|
125 | --state.pos;
|
126 | }
|
127 | readRegexp();
|
128 | }
|
129 |
|
130 | export function pushTypeContext(existingTokensInType) {
|
131 | for (let i = state.tokens.length - existingTokensInType; i < state.tokens.length; i++) {
|
132 | state.tokens[i].isType = true;
|
133 | }
|
134 | const oldIsType = state.isType;
|
135 | state.isType = true;
|
136 | return oldIsType;
|
137 | }
|
138 |
|
139 | export function popTypeContext(oldIsType) {
|
140 | state.isType = oldIsType;
|
141 | }
|
142 |
|
143 | export function eat(type) {
|
144 | if (match(type)) {
|
145 | next();
|
146 | return true;
|
147 | } else {
|
148 | return false;
|
149 | }
|
150 | }
|
151 |
|
152 | export function match(type) {
|
153 | return state.type === type;
|
154 | }
|
155 |
|
156 | export function lookaheadType() {
|
157 | const snapshot = state.snapshot();
|
158 | next();
|
159 | const type = state.type;
|
160 | state.restoreFromSnapshot(snapshot);
|
161 | return type;
|
162 | }
|
163 |
|
164 | export class TypeAndKeyword {
|
165 |
|
166 |
|
167 | constructor(type, contextualKeyword) {
|
168 | this.type = type;
|
169 | this.contextualKeyword = contextualKeyword;
|
170 | }
|
171 | }
|
172 |
|
173 | export function lookaheadTypeAndKeyword() {
|
174 | const snapshot = state.snapshot();
|
175 | next();
|
176 | const type = state.type;
|
177 | const contextualKeyword = state.contextualKeyword;
|
178 | state.restoreFromSnapshot(snapshot);
|
179 | return new TypeAndKeyword(type, contextualKeyword);
|
180 | }
|
181 |
|
182 |
|
183 |
|
184 | export function nextToken() {
|
185 | skipSpace();
|
186 | state.start = state.pos;
|
187 | if (state.pos >= input.length) {
|
188 | const tokens = state.tokens;
|
189 |
|
190 |
|
191 |
|
192 | if (
|
193 | tokens.length >= 2 &&
|
194 | tokens[tokens.length - 1].start >= input.length &&
|
195 | tokens[tokens.length - 2].start >= input.length
|
196 | ) {
|
197 | unexpected("Unexpectedly reached the end of input.");
|
198 | }
|
199 | finishToken(tt.eof);
|
200 | return;
|
201 | }
|
202 | readToken(input.charCodeAt(state.pos));
|
203 | }
|
204 |
|
205 | function readToken(code) {
|
206 |
|
207 |
|
208 | if (
|
209 | IS_IDENTIFIER_START[code] ||
|
210 | code === charCodes.backslash ||
|
211 | (code === charCodes.atSign && input.charCodeAt(state.pos + 1) === charCodes.atSign)
|
212 | ) {
|
213 | readWord();
|
214 | } else {
|
215 | getTokenFromCode(code);
|
216 | }
|
217 | }
|
218 |
|
219 | function skipBlockComment() {
|
220 | while (
|
221 | input.charCodeAt(state.pos) !== charCodes.asterisk ||
|
222 | input.charCodeAt(state.pos + 1) !== charCodes.slash
|
223 | ) {
|
224 | state.pos++;
|
225 | if (state.pos > input.length) {
|
226 | unexpected("Unterminated comment", state.pos - 2);
|
227 | return;
|
228 | }
|
229 | }
|
230 | state.pos += 2;
|
231 | }
|
232 |
|
233 | export function skipLineComment(startSkip) {
|
234 | let ch = input.charCodeAt((state.pos += startSkip));
|
235 | if (state.pos < input.length) {
|
236 | while (
|
237 | ch !== charCodes.lineFeed &&
|
238 | ch !== charCodes.carriageReturn &&
|
239 | ch !== charCodes.lineSeparator &&
|
240 | ch !== charCodes.paragraphSeparator &&
|
241 | ++state.pos < input.length
|
242 | ) {
|
243 | ch = input.charCodeAt(state.pos);
|
244 | }
|
245 | }
|
246 | }
|
247 |
|
248 |
|
249 |
|
250 | export function skipSpace() {
|
251 | while (state.pos < input.length) {
|
252 | const ch = input.charCodeAt(state.pos);
|
253 | switch (ch) {
|
254 | case charCodes.carriageReturn:
|
255 | if (input.charCodeAt(state.pos + 1) === charCodes.lineFeed) {
|
256 | ++state.pos;
|
257 | }
|
258 |
|
259 | case charCodes.lineFeed:
|
260 | case charCodes.lineSeparator:
|
261 | case charCodes.paragraphSeparator:
|
262 | ++state.pos;
|
263 | break;
|
264 |
|
265 | case charCodes.slash:
|
266 | switch (input.charCodeAt(state.pos + 1)) {
|
267 | case charCodes.asterisk:
|
268 | skipBlockComment();
|
269 | break;
|
270 |
|
271 | case charCodes.slash:
|
272 | skipLineComment(2);
|
273 | break;
|
274 |
|
275 | default:
|
276 | return;
|
277 | }
|
278 | break;
|
279 |
|
280 | default:
|
281 | if (IS_WHITESPACE[ch]) {
|
282 | ++state.pos;
|
283 | } else {
|
284 | return;
|
285 | }
|
286 | }
|
287 | }
|
288 | }
|
289 |
|
290 |
|
291 |
|
292 | export function finishToken(
|
293 | type,
|
294 | contextualKeyword = ContextualKeyword.NONE,
|
295 | ) {
|
296 | state.end = state.pos;
|
297 | state.type = type;
|
298 | state.contextualKeyword = contextualKeyword;
|
299 | }
|
300 |
|
301 |
|
302 |
|
303 |
|
304 |
|
305 |
|
306 |
|
307 |
|
308 |
|
309 | function readToken_dot() {
|
310 | const nextChar = input.charCodeAt(state.pos + 1);
|
311 | if (nextChar >= charCodes.digit0 && nextChar <= charCodes.digit9) {
|
312 | readNumber(true);
|
313 | return;
|
314 | }
|
315 |
|
316 | const next2 = input.charCodeAt(state.pos + 2);
|
317 | if (nextChar === charCodes.dot && next2 === charCodes.dot) {
|
318 | state.pos += 3;
|
319 | finishToken(tt.ellipsis);
|
320 | } else {
|
321 | ++state.pos;
|
322 | finishToken(tt.dot);
|
323 | }
|
324 | }
|
325 |
|
326 | function readToken_slash() {
|
327 | const nextChar = input.charCodeAt(state.pos + 1);
|
328 | if (nextChar === charCodes.equalsTo) {
|
329 | finishOp(tt.assign, 2);
|
330 | } else {
|
331 | finishOp(tt.slash, 1);
|
332 | }
|
333 | }
|
334 |
|
335 | function readToken_mult_modulo(code) {
|
336 |
|
337 | let tokenType = code === charCodes.asterisk ? tt.star : tt.modulo;
|
338 | let width = 1;
|
339 | let nextChar = input.charCodeAt(state.pos + 1);
|
340 |
|
341 |
|
342 | if (code === charCodes.asterisk && nextChar === charCodes.asterisk) {
|
343 | width++;
|
344 | nextChar = input.charCodeAt(state.pos + 2);
|
345 | tokenType = tt.exponent;
|
346 | }
|
347 |
|
348 |
|
349 | if (
|
350 | nextChar === charCodes.equalsTo &&
|
351 | input.charCodeAt(state.pos + 2) !== charCodes.greaterThan
|
352 | ) {
|
353 | width++;
|
354 | tokenType = tt.assign;
|
355 | }
|
356 |
|
357 | finishOp(tokenType, width);
|
358 | }
|
359 |
|
360 | function readToken_pipe_amp(code) {
|
361 |
|
362 | const nextChar = input.charCodeAt(state.pos + 1);
|
363 |
|
364 | if (nextChar === code) {
|
365 | if (input.charCodeAt(state.pos + 2) === charCodes.equalsTo) {
|
366 |
|
367 | finishOp(tt.assign, 3);
|
368 | } else {
|
369 |
|
370 | finishOp(code === charCodes.verticalBar ? tt.logicalOR : tt.logicalAND, 2);
|
371 | }
|
372 | return;
|
373 | }
|
374 |
|
375 | if (code === charCodes.verticalBar) {
|
376 |
|
377 | if (nextChar === charCodes.greaterThan) {
|
378 | finishOp(tt.pipeline, 2);
|
379 | return;
|
380 | } else if (nextChar === charCodes.rightCurlyBrace && isFlowEnabled) {
|
381 |
|
382 | finishOp(tt.braceBarR, 2);
|
383 | return;
|
384 | }
|
385 | }
|
386 |
|
387 | if (nextChar === charCodes.equalsTo) {
|
388 | finishOp(tt.assign, 2);
|
389 | return;
|
390 | }
|
391 |
|
392 | finishOp(code === charCodes.verticalBar ? tt.bitwiseOR : tt.bitwiseAND, 1);
|
393 | }
|
394 |
|
395 | function readToken_caret() {
|
396 |
|
397 | const nextChar = input.charCodeAt(state.pos + 1);
|
398 | if (nextChar === charCodes.equalsTo) {
|
399 | finishOp(tt.assign, 2);
|
400 | } else {
|
401 | finishOp(tt.bitwiseXOR, 1);
|
402 | }
|
403 | }
|
404 |
|
405 | function readToken_plus_min(code) {
|
406 |
|
407 | const nextChar = input.charCodeAt(state.pos + 1);
|
408 |
|
409 | if (nextChar === code) {
|
410 |
|
411 | finishOp(tt.preIncDec, 2);
|
412 | return;
|
413 | }
|
414 |
|
415 | if (nextChar === charCodes.equalsTo) {
|
416 | finishOp(tt.assign, 2);
|
417 | } else if (code === charCodes.plusSign) {
|
418 | finishOp(tt.plus, 1);
|
419 | } else {
|
420 | finishOp(tt.minus, 1);
|
421 | }
|
422 | }
|
423 |
|
424 |
|
425 | function readToken_lt_gt(code) {
|
426 |
|
427 | if (code === charCodes.greaterThan && state.isType) {
|
428 | finishOp(tt.greaterThan, 1);
|
429 | return;
|
430 | }
|
431 | const nextChar = input.charCodeAt(state.pos + 1);
|
432 |
|
433 | if (nextChar === code) {
|
434 | const size =
|
435 | code === charCodes.greaterThan && input.charCodeAt(state.pos + 2) === charCodes.greaterThan
|
436 | ? 3
|
437 | : 2;
|
438 | if (input.charCodeAt(state.pos + size) === charCodes.equalsTo) {
|
439 | finishOp(tt.assign, size + 1);
|
440 | return;
|
441 | }
|
442 | finishOp(tt.bitShift, size);
|
443 | return;
|
444 | }
|
445 |
|
446 | if (nextChar === charCodes.equalsTo) {
|
447 |
|
448 | finishOp(tt.relationalOrEqual, 2);
|
449 | } else if (code === charCodes.lessThan) {
|
450 | finishOp(tt.lessThan, 1);
|
451 | } else {
|
452 | finishOp(tt.greaterThan, 1);
|
453 | }
|
454 | }
|
455 |
|
456 | function readToken_eq_excl(code) {
|
457 |
|
458 | const nextChar = input.charCodeAt(state.pos + 1);
|
459 | if (nextChar === charCodes.equalsTo) {
|
460 | finishOp(tt.equality, input.charCodeAt(state.pos + 2) === charCodes.equalsTo ? 3 : 2);
|
461 | return;
|
462 | }
|
463 | if (code === charCodes.equalsTo && nextChar === charCodes.greaterThan) {
|
464 |
|
465 | state.pos += 2;
|
466 | finishToken(tt.arrow);
|
467 | return;
|
468 | }
|
469 | finishOp(code === charCodes.equalsTo ? tt.eq : tt.bang, 1);
|
470 | }
|
471 |
|
472 | function readToken_question() {
|
473 |
|
474 | const nextChar = input.charCodeAt(state.pos + 1);
|
475 | const nextChar2 = input.charCodeAt(state.pos + 2);
|
476 | if (nextChar === charCodes.questionMark && !state.isType) {
|
477 | if (nextChar2 === charCodes.equalsTo) {
|
478 |
|
479 | finishOp(tt.assign, 3);
|
480 | } else {
|
481 |
|
482 | finishOp(tt.nullishCoalescing, 2);
|
483 | }
|
484 | } else if (
|
485 | nextChar === charCodes.dot &&
|
486 | !(nextChar2 >= charCodes.digit0 && nextChar2 <= charCodes.digit9)
|
487 | ) {
|
488 |
|
489 | state.pos += 2;
|
490 | finishToken(tt.questionDot);
|
491 | } else {
|
492 | ++state.pos;
|
493 | finishToken(tt.question);
|
494 | }
|
495 | }
|
496 |
|
497 | export function getTokenFromCode(code) {
|
498 | switch (code) {
|
499 | case charCodes.numberSign:
|
500 | ++state.pos;
|
501 | finishToken(tt.hash);
|
502 | return;
|
503 |
|
504 |
|
505 |
|
506 |
|
507 | case charCodes.dot:
|
508 | readToken_dot();
|
509 | return;
|
510 |
|
511 |
|
512 | case charCodes.leftParenthesis:
|
513 | ++state.pos;
|
514 | finishToken(tt.parenL);
|
515 | return;
|
516 | case charCodes.rightParenthesis:
|
517 | ++state.pos;
|
518 | finishToken(tt.parenR);
|
519 | return;
|
520 | case charCodes.semicolon:
|
521 | ++state.pos;
|
522 | finishToken(tt.semi);
|
523 | return;
|
524 | case charCodes.comma:
|
525 | ++state.pos;
|
526 | finishToken(tt.comma);
|
527 | return;
|
528 | case charCodes.leftSquareBracket:
|
529 | ++state.pos;
|
530 | finishToken(tt.bracketL);
|
531 | return;
|
532 | case charCodes.rightSquareBracket:
|
533 | ++state.pos;
|
534 | finishToken(tt.bracketR);
|
535 | return;
|
536 |
|
537 | case charCodes.leftCurlyBrace:
|
538 | if (isFlowEnabled && input.charCodeAt(state.pos + 1) === charCodes.verticalBar) {
|
539 | finishOp(tt.braceBarL, 2);
|
540 | } else {
|
541 | ++state.pos;
|
542 | finishToken(tt.braceL);
|
543 | }
|
544 | return;
|
545 |
|
546 | case charCodes.rightCurlyBrace:
|
547 | ++state.pos;
|
548 | finishToken(tt.braceR);
|
549 | return;
|
550 |
|
551 | case charCodes.colon:
|
552 | if (input.charCodeAt(state.pos + 1) === charCodes.colon) {
|
553 | finishOp(tt.doubleColon, 2);
|
554 | } else {
|
555 | ++state.pos;
|
556 | finishToken(tt.colon);
|
557 | }
|
558 | return;
|
559 |
|
560 | case charCodes.questionMark:
|
561 | readToken_question();
|
562 | return;
|
563 | case charCodes.atSign:
|
564 | ++state.pos;
|
565 | finishToken(tt.at);
|
566 | return;
|
567 |
|
568 | case charCodes.graveAccent:
|
569 | ++state.pos;
|
570 | finishToken(tt.backQuote);
|
571 | return;
|
572 |
|
573 | case charCodes.digit0: {
|
574 | const nextChar = input.charCodeAt(state.pos + 1);
|
575 |
|
576 | if (
|
577 | nextChar === charCodes.lowercaseX ||
|
578 | nextChar === charCodes.uppercaseX ||
|
579 | nextChar === charCodes.lowercaseO ||
|
580 | nextChar === charCodes.uppercaseO ||
|
581 | nextChar === charCodes.lowercaseB ||
|
582 | nextChar === charCodes.uppercaseB
|
583 | ) {
|
584 | readRadixNumber();
|
585 | return;
|
586 | }
|
587 | }
|
588 |
|
589 |
|
590 | case charCodes.digit1:
|
591 | case charCodes.digit2:
|
592 | case charCodes.digit3:
|
593 | case charCodes.digit4:
|
594 | case charCodes.digit5:
|
595 | case charCodes.digit6:
|
596 | case charCodes.digit7:
|
597 | case charCodes.digit8:
|
598 | case charCodes.digit9:
|
599 | readNumber(false);
|
600 | return;
|
601 |
|
602 |
|
603 | case charCodes.quotationMark:
|
604 | case charCodes.apostrophe:
|
605 | readString(code);
|
606 | return;
|
607 |
|
608 |
|
609 |
|
610 |
|
611 |
|
612 |
|
613 | case charCodes.slash:
|
614 | readToken_slash();
|
615 | return;
|
616 |
|
617 | case charCodes.percentSign:
|
618 | case charCodes.asterisk:
|
619 | readToken_mult_modulo(code);
|
620 | return;
|
621 |
|
622 | case charCodes.verticalBar:
|
623 | case charCodes.ampersand:
|
624 | readToken_pipe_amp(code);
|
625 | return;
|
626 |
|
627 | case charCodes.caret:
|
628 | readToken_caret();
|
629 | return;
|
630 |
|
631 | case charCodes.plusSign:
|
632 | case charCodes.dash:
|
633 | readToken_plus_min(code);
|
634 | return;
|
635 |
|
636 | case charCodes.lessThan:
|
637 | case charCodes.greaterThan:
|
638 | readToken_lt_gt(code);
|
639 | return;
|
640 |
|
641 | case charCodes.equalsTo:
|
642 | case charCodes.exclamationMark:
|
643 | readToken_eq_excl(code);
|
644 | return;
|
645 |
|
646 | case charCodes.tilde:
|
647 | finishOp(tt.tilde, 1);
|
648 | return;
|
649 |
|
650 | default:
|
651 | break;
|
652 | }
|
653 |
|
654 | unexpected(`Unexpected character '${String.fromCharCode(code)}'`, state.pos);
|
655 | }
|
656 |
|
657 | function finishOp(type, size) {
|
658 | state.pos += size;
|
659 | finishToken(type);
|
660 | }
|
661 |
|
662 | function readRegexp() {
|
663 | const start = state.pos;
|
664 | let escaped = false;
|
665 | let inClass = false;
|
666 | for (;;) {
|
667 | if (state.pos >= input.length) {
|
668 | unexpected("Unterminated regular expression", start);
|
669 | return;
|
670 | }
|
671 | const code = input.charCodeAt(state.pos);
|
672 | if (escaped) {
|
673 | escaped = false;
|
674 | } else {
|
675 | if (code === charCodes.leftSquareBracket) {
|
676 | inClass = true;
|
677 | } else if (code === charCodes.rightSquareBracket && inClass) {
|
678 | inClass = false;
|
679 | } else if (code === charCodes.slash && !inClass) {
|
680 | break;
|
681 | }
|
682 | escaped = code === charCodes.backslash;
|
683 | }
|
684 | ++state.pos;
|
685 | }
|
686 | ++state.pos;
|
687 |
|
688 | skipWord();
|
689 |
|
690 | finishToken(tt.regexp);
|
691 | }
|
692 |
|
693 |
|
694 |
|
695 | function readInt() {
|
696 | while (true) {
|
697 | const code = input.charCodeAt(state.pos);
|
698 | if (
|
699 | (code >= charCodes.digit0 && code <= charCodes.digit9) ||
|
700 | (code >= charCodes.lowercaseA && code <= charCodes.lowercaseF) ||
|
701 | (code >= charCodes.uppercaseA && code <= charCodes.uppercaseF) ||
|
702 | code === charCodes.underscore
|
703 | ) {
|
704 | state.pos++;
|
705 | } else {
|
706 | break;
|
707 | }
|
708 | }
|
709 | }
|
710 |
|
711 | function readRadixNumber() {
|
712 | let isBigInt = false;
|
713 |
|
714 | state.pos += 2;
|
715 | readInt();
|
716 |
|
717 | if (input.charCodeAt(state.pos) === charCodes.lowercaseN) {
|
718 | ++state.pos;
|
719 | isBigInt = true;
|
720 | }
|
721 |
|
722 | if (isBigInt) {
|
723 | finishToken(tt.bigint);
|
724 | return;
|
725 | }
|
726 |
|
727 | finishToken(tt.num);
|
728 | }
|
729 |
|
730 |
|
731 | function readNumber(startsWithDot) {
|
732 | let isBigInt = false;
|
733 |
|
734 | if (!startsWithDot) {
|
735 | readInt();
|
736 | }
|
737 |
|
738 | let nextChar = input.charCodeAt(state.pos);
|
739 | if (nextChar === charCodes.dot) {
|
740 | ++state.pos;
|
741 | readInt();
|
742 | nextChar = input.charCodeAt(state.pos);
|
743 | }
|
744 |
|
745 | if (nextChar === charCodes.uppercaseE || nextChar === charCodes.lowercaseE) {
|
746 | nextChar = input.charCodeAt(++state.pos);
|
747 | if (nextChar === charCodes.plusSign || nextChar === charCodes.dash) {
|
748 | ++state.pos;
|
749 | }
|
750 | readInt();
|
751 | nextChar = input.charCodeAt(state.pos);
|
752 | }
|
753 |
|
754 | if (nextChar === charCodes.lowercaseN) {
|
755 | ++state.pos;
|
756 | isBigInt = true;
|
757 | }
|
758 |
|
759 | if (isBigInt) {
|
760 | finishToken(tt.bigint);
|
761 | return;
|
762 | }
|
763 | finishToken(tt.num);
|
764 | }
|
765 |
|
766 | function readString(quote) {
|
767 | state.pos++;
|
768 | for (;;) {
|
769 | if (state.pos >= input.length) {
|
770 | unexpected("Unterminated string constant");
|
771 | return;
|
772 | }
|
773 | const ch = input.charCodeAt(state.pos);
|
774 | if (ch === charCodes.backslash) {
|
775 | state.pos++;
|
776 | } else if (ch === quote) {
|
777 | break;
|
778 | }
|
779 | state.pos++;
|
780 | }
|
781 | state.pos++;
|
782 | finishToken(tt.string);
|
783 | }
|
784 |
|
785 |
|
786 | function readTmplToken() {
|
787 | for (;;) {
|
788 | if (state.pos >= input.length) {
|
789 | unexpected("Unterminated template");
|
790 | return;
|
791 | }
|
792 | const ch = input.charCodeAt(state.pos);
|
793 | if (
|
794 | ch === charCodes.graveAccent ||
|
795 | (ch === charCodes.dollarSign && input.charCodeAt(state.pos + 1) === charCodes.leftCurlyBrace)
|
796 | ) {
|
797 | if (state.pos === state.start && match(tt.template)) {
|
798 | if (ch === charCodes.dollarSign) {
|
799 | state.pos += 2;
|
800 | finishToken(tt.dollarBraceL);
|
801 | return;
|
802 | } else {
|
803 | ++state.pos;
|
804 | finishToken(tt.backQuote);
|
805 | return;
|
806 | }
|
807 | }
|
808 | finishToken(tt.template);
|
809 | return;
|
810 | }
|
811 | if (ch === charCodes.backslash) {
|
812 | state.pos++;
|
813 | }
|
814 | state.pos++;
|
815 | }
|
816 | }
|
817 |
|
818 |
|
819 |
|
820 |
|
821 | export function skipWord() {
|
822 | while (state.pos < input.length) {
|
823 | const ch = input.charCodeAt(state.pos);
|
824 | if (IS_IDENTIFIER_CHAR[ch]) {
|
825 | state.pos++;
|
826 | } else if (ch === charCodes.backslash) {
|
827 |
|
828 | state.pos += 2;
|
829 | if (input.charCodeAt(state.pos) === charCodes.leftCurlyBrace) {
|
830 | while (
|
831 | state.pos < input.length &&
|
832 | input.charCodeAt(state.pos) !== charCodes.rightCurlyBrace
|
833 | ) {
|
834 | state.pos++;
|
835 | }
|
836 | state.pos++;
|
837 | }
|
838 | } else {
|
839 | break;
|
840 | }
|
841 | }
|
842 | }
|