1 | import {flowParseAssignableListItemTypes} from "../plugins/flow";
|
2 | import {tsParseAssignableListItemTypes, tsParseModifiers} from "../plugins/typescript";
|
3 | import {
|
4 | eat,
|
5 | IdentifierRole,
|
6 | match,
|
7 | next,
|
8 | popTypeContext,
|
9 | pushTypeContext,
|
10 | } from "../tokenizer/index";
|
11 | import {ContextualKeyword} from "../tokenizer/keywords";
|
12 | import {TokenType, TokenType as tt} from "../tokenizer/types";
|
13 | import {isFlowEnabled, isTypeScriptEnabled, state} from "./base";
|
14 | import {parseIdentifier, parseMaybeAssign, parseObj} from "./expression";
|
15 | import {expect, unexpected} from "./util";
|
16 |
|
17 | export function parseSpread() {
|
18 | next();
|
19 | parseMaybeAssign(false);
|
20 | }
|
21 |
|
22 | export function parseRest(isBlockScope) {
|
23 | next();
|
24 | parseBindingAtom(isBlockScope);
|
25 | }
|
26 |
|
27 | export function parseBindingIdentifier(isBlockScope) {
|
28 | parseIdentifier();
|
29 | markPriorBindingIdentifier(isBlockScope);
|
30 | }
|
31 |
|
32 | export function parseImportedIdentifier() {
|
33 | parseIdentifier();
|
34 | state.tokens[state.tokens.length - 1].identifierRole = IdentifierRole.ImportDeclaration;
|
35 | }
|
36 |
|
37 | export function markPriorBindingIdentifier(isBlockScope) {
|
38 | let identifierRole;
|
39 | if (state.scopeDepth === 0) {
|
40 | identifierRole = IdentifierRole.TopLevelDeclaration;
|
41 | } else if (isBlockScope) {
|
42 | identifierRole = IdentifierRole.BlockScopedDeclaration;
|
43 | } else {
|
44 | identifierRole = IdentifierRole.FunctionScopedDeclaration;
|
45 | }
|
46 | state.tokens[state.tokens.length - 1].identifierRole = identifierRole;
|
47 | }
|
48 |
|
49 |
|
50 | export function parseBindingAtom(isBlockScope) {
|
51 | switch (state.type) {
|
52 | case tt._this: {
|
53 |
|
54 | const oldIsType = pushTypeContext(0);
|
55 | next();
|
56 | popTypeContext(oldIsType);
|
57 | return;
|
58 | }
|
59 |
|
60 | case tt._yield:
|
61 | case tt.name: {
|
62 | state.type = tt.name;
|
63 | parseBindingIdentifier(isBlockScope);
|
64 | return;
|
65 | }
|
66 |
|
67 | case tt.bracketL: {
|
68 | next();
|
69 | parseBindingList(tt.bracketR, isBlockScope, true );
|
70 | return;
|
71 | }
|
72 |
|
73 | case tt.braceL:
|
74 | parseObj(true, isBlockScope);
|
75 | return;
|
76 |
|
77 | default:
|
78 | unexpected();
|
79 | }
|
80 | }
|
81 |
|
82 | export function parseBindingList(
|
83 | close,
|
84 | isBlockScope,
|
85 | allowEmpty = false,
|
86 | allowModifiers = false,
|
87 | contextId = 0,
|
88 | ) {
|
89 | let first = true;
|
90 |
|
91 | let hasRemovedComma = false;
|
92 | const firstItemTokenIndex = state.tokens.length;
|
93 |
|
94 | while (!eat(close) && !state.error) {
|
95 | if (first) {
|
96 | first = false;
|
97 | } else {
|
98 | expect(tt.comma);
|
99 | state.tokens[state.tokens.length - 1].contextId = contextId;
|
100 |
|
101 |
|
102 | if (!hasRemovedComma && state.tokens[firstItemTokenIndex].isType) {
|
103 | state.tokens[state.tokens.length - 1].isType = true;
|
104 | hasRemovedComma = true;
|
105 | }
|
106 | }
|
107 | if (allowEmpty && match(tt.comma)) {
|
108 |
|
109 | } else if (eat(close)) {
|
110 | break;
|
111 | } else if (match(tt.ellipsis)) {
|
112 | parseRest(isBlockScope);
|
113 | parseAssignableListItemTypes();
|
114 |
|
115 | eat(TokenType.comma);
|
116 | expect(close);
|
117 | break;
|
118 | } else {
|
119 | parseAssignableListItem(allowModifiers, isBlockScope);
|
120 | }
|
121 | }
|
122 | }
|
123 |
|
124 | function parseAssignableListItem(allowModifiers, isBlockScope) {
|
125 | if (allowModifiers) {
|
126 | tsParseModifiers([
|
127 | ContextualKeyword._public,
|
128 | ContextualKeyword._protected,
|
129 | ContextualKeyword._private,
|
130 | ContextualKeyword._readonly,
|
131 | ContextualKeyword._override,
|
132 | ]);
|
133 | }
|
134 |
|
135 | parseMaybeDefault(isBlockScope);
|
136 | parseAssignableListItemTypes();
|
137 | parseMaybeDefault(isBlockScope, true );
|
138 | }
|
139 |
|
140 | function parseAssignableListItemTypes() {
|
141 | if (isFlowEnabled) {
|
142 | flowParseAssignableListItemTypes();
|
143 | } else if (isTypeScriptEnabled) {
|
144 | tsParseAssignableListItemTypes();
|
145 | }
|
146 | }
|
147 |
|
148 |
|
149 | export function parseMaybeDefault(isBlockScope, leftAlreadyParsed = false) {
|
150 | if (!leftAlreadyParsed) {
|
151 | parseBindingAtom(isBlockScope);
|
152 | }
|
153 | if (!eat(tt.eq)) {
|
154 | return;
|
155 | }
|
156 | const eqIndex = state.tokens.length - 1;
|
157 | parseMaybeAssign();
|
158 | state.tokens[eqIndex].rhsEndIndex = state.tokens.length;
|
159 | }
|