1 | import {flowParseAssignableListItemTypes} from "../plugins/flow";
|
2 | import {
|
3 | tsParseAccessModifier,
|
4 | tsParseAssignableListItemTypes,
|
5 | tsParseModifier,
|
6 | } from "../plugins/typescript";
|
7 | import {
|
8 | eat,
|
9 | IdentifierRole,
|
10 | match,
|
11 | next,
|
12 | popTypeContext,
|
13 | pushTypeContext,
|
14 | } from "../tokenizer/index";
|
15 | import {ContextualKeyword} from "../tokenizer/keywords";
|
16 | import {TokenType, TokenType as tt} from "../tokenizer/types";
|
17 | import {isFlowEnabled, isTypeScriptEnabled, state} from "./base";
|
18 | import {parseIdentifier, parseMaybeAssign, parseObj} from "./expression";
|
19 | import {expect, unexpected} from "./util";
|
20 |
|
21 | export function parseSpread() {
|
22 | next();
|
23 | parseMaybeAssign(false);
|
24 | }
|
25 |
|
26 | export function parseRest(isBlockScope) {
|
27 | next();
|
28 | parseBindingAtom(isBlockScope);
|
29 | }
|
30 |
|
31 | export function parseBindingIdentifier(isBlockScope) {
|
32 | parseIdentifier();
|
33 | markPriorBindingIdentifier(isBlockScope);
|
34 | }
|
35 |
|
36 | export function markPriorBindingIdentifier(isBlockScope) {
|
37 | if (state.isType) {
|
38 | return;
|
39 | }
|
40 | if (state.scopeDepth === 0) {
|
41 | state.tokens[state.tokens.length - 1].identifierRole = IdentifierRole.TopLevelDeclaration;
|
42 | } else {
|
43 | state.tokens[state.tokens.length - 1].identifierRole = isBlockScope
|
44 | ? IdentifierRole.BlockScopedDeclaration
|
45 | : IdentifierRole.FunctionScopedDeclaration;
|
46 | }
|
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 | ) {
|
88 | let first = true;
|
89 |
|
90 | let hasRemovedComma = false;
|
91 | const firstItemTokenIndex = state.tokens.length;
|
92 |
|
93 | while (!eat(close) && !state.error) {
|
94 | if (first) {
|
95 | first = false;
|
96 | } else {
|
97 | expect(tt.comma);
|
98 |
|
99 |
|
100 | if (!hasRemovedComma && state.tokens[firstItemTokenIndex].isType) {
|
101 | state.tokens[state.tokens.length - 1].isType = true;
|
102 | hasRemovedComma = true;
|
103 | }
|
104 | }
|
105 | if (allowEmpty && match(tt.comma)) {
|
106 |
|
107 | } else if (eat(close)) {
|
108 | break;
|
109 | } else if (match(tt.ellipsis)) {
|
110 | parseRest(isBlockScope);
|
111 | parseAssignableListItemTypes();
|
112 |
|
113 | eat(TokenType.comma);
|
114 | expect(close);
|
115 | break;
|
116 | } else {
|
117 | parseAssignableListItem(allowModifiers, isBlockScope);
|
118 | }
|
119 | }
|
120 | }
|
121 |
|
122 | function parseAssignableListItem(allowModifiers, isBlockScope) {
|
123 | if (allowModifiers) {
|
124 | tsParseAccessModifier();
|
125 | tsParseModifier([ContextualKeyword._readonly]);
|
126 | }
|
127 |
|
128 | parseMaybeDefault(isBlockScope);
|
129 | parseAssignableListItemTypes();
|
130 | parseMaybeDefault(isBlockScope, true );
|
131 | }
|
132 |
|
133 | function parseAssignableListItemTypes() {
|
134 | if (isFlowEnabled) {
|
135 | flowParseAssignableListItemTypes();
|
136 | } else if (isTypeScriptEnabled) {
|
137 | tsParseAssignableListItemTypes();
|
138 | }
|
139 | }
|
140 |
|
141 |
|
142 | export function parseMaybeDefault(isBlockScope, leftAlreadyParsed = false) {
|
143 | if (!leftAlreadyParsed) {
|
144 | parseBindingAtom(isBlockScope);
|
145 | }
|
146 | if (!eat(tt.eq)) {
|
147 | return;
|
148 | }
|
149 | const eqIndex = state.tokens.length - 1;
|
150 | parseMaybeAssign();
|
151 | state.tokens[eqIndex].rhsEndIndex = state.tokens.length;
|
152 | }
|