UNPKG

1.94 kBJavaScriptView Raw
1import {input, state} from "../traverser/base";
2import {charCodes} from "../util/charcodes";
3import {IS_IDENTIFIER_CHAR} from "../util/identifier";
4import {finishToken} from "./index";
5import {READ_WORD_TREE} from "./readWordTree";
6import {TokenType as tt} from "./types";
7
8/**
9 * Read an identifier, producing either a name token or matching on one of the existing keywords.
10 * For performance, we pre-generate big decision tree that we traverse. Each node represents a
11 * prefix and has 27 values, where the first value is the token or contextual token, if any (-1 if
12 * not), and the other 26 values are the transitions to other nodes, or -1 to stop.
13 */
14export default function readWord() {
15 let treePos = 0;
16 let code = 0;
17 let pos = state.pos;
18 while (pos < input.length) {
19 code = input.charCodeAt(pos);
20 if (code < charCodes.lowercaseA || code > charCodes.lowercaseZ) {
21 break;
22 }
23 const next = READ_WORD_TREE[treePos + (code - charCodes.lowercaseA) + 1];
24 if (next === -1) {
25 break;
26 } else {
27 treePos = next;
28 pos++;
29 }
30 }
31
32 const keywordValue = READ_WORD_TREE[treePos];
33 if (keywordValue > -1 && !IS_IDENTIFIER_CHAR[code]) {
34 state.pos = pos;
35 if (keywordValue & 1) {
36 finishToken(keywordValue >>> 1);
37 } else {
38 finishToken(tt.name, keywordValue >>> 1);
39 }
40 return;
41 }
42
43 while (pos < input.length) {
44 const ch = input.charCodeAt(pos);
45 if (IS_IDENTIFIER_CHAR[ch]) {
46 pos++;
47 } else if (ch === charCodes.backslash) {
48 // \u
49 pos += 2;
50 if (input.charCodeAt(pos) === charCodes.leftCurlyBrace) {
51 while (pos < input.length && input.charCodeAt(pos) !== charCodes.rightCurlyBrace) {
52 pos++;
53 }
54 pos++;
55 }
56 } else if (ch === charCodes.atSign && input.charCodeAt(pos + 1) === charCodes.atSign) {
57 pos += 2;
58 } else {
59 break;
60 }
61 }
62 state.pos = pos;
63 finishToken(tt.name);
64}