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