summaryrefslogtreecommitdiff
path: root/node_modules/sucrase/dist/esm/parser/traverser/lval.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/sucrase/dist/esm/parser/traverser/lval.js')
-rw-r--r--node_modules/sucrase/dist/esm/parser/traverser/lval.js159
1 files changed, 159 insertions, 0 deletions
diff --git a/node_modules/sucrase/dist/esm/parser/traverser/lval.js b/node_modules/sucrase/dist/esm/parser/traverser/lval.js
new file mode 100644
index 0000000..f5c4855
--- /dev/null
+++ b/node_modules/sucrase/dist/esm/parser/traverser/lval.js
@@ -0,0 +1,159 @@
+import {flowParseAssignableListItemTypes} from "../plugins/flow";
+import {tsParseAssignableListItemTypes, tsParseModifiers} from "../plugins/typescript";
+import {
+ eat,
+ IdentifierRole,
+ match,
+ next,
+ popTypeContext,
+ pushTypeContext,
+} from "../tokenizer/index";
+import {ContextualKeyword} from "../tokenizer/keywords";
+import {TokenType, TokenType as tt} from "../tokenizer/types";
+import {isFlowEnabled, isTypeScriptEnabled, state} from "./base";
+import {parseIdentifier, parseMaybeAssign, parseObj} from "./expression";
+import {expect, unexpected} from "./util";
+
+export function parseSpread() {
+ next();
+ parseMaybeAssign(false);
+}
+
+export function parseRest(isBlockScope) {
+ next();
+ parseBindingAtom(isBlockScope);
+}
+
+export function parseBindingIdentifier(isBlockScope) {
+ parseIdentifier();
+ markPriorBindingIdentifier(isBlockScope);
+}
+
+export function parseImportedIdentifier() {
+ parseIdentifier();
+ state.tokens[state.tokens.length - 1].identifierRole = IdentifierRole.ImportDeclaration;
+}
+
+export function markPriorBindingIdentifier(isBlockScope) {
+ let identifierRole;
+ if (state.scopeDepth === 0) {
+ identifierRole = IdentifierRole.TopLevelDeclaration;
+ } else if (isBlockScope) {
+ identifierRole = IdentifierRole.BlockScopedDeclaration;
+ } else {
+ identifierRole = IdentifierRole.FunctionScopedDeclaration;
+ }
+ state.tokens[state.tokens.length - 1].identifierRole = identifierRole;
+}
+
+// Parses lvalue (assignable) atom.
+export function parseBindingAtom(isBlockScope) {
+ switch (state.type) {
+ case tt._this: {
+ // In TypeScript, "this" may be the name of a parameter, so allow it.
+ const oldIsType = pushTypeContext(0);
+ next();
+ popTypeContext(oldIsType);
+ return;
+ }
+
+ case tt._yield:
+ case tt.name: {
+ state.type = tt.name;
+ parseBindingIdentifier(isBlockScope);
+ return;
+ }
+
+ case tt.bracketL: {
+ next();
+ parseBindingList(tt.bracketR, isBlockScope, true /* allowEmpty */);
+ return;
+ }
+
+ case tt.braceL:
+ parseObj(true, isBlockScope);
+ return;
+
+ default:
+ unexpected();
+ }
+}
+
+export function parseBindingList(
+ close,
+ isBlockScope,
+ allowEmpty = false,
+ allowModifiers = false,
+ contextId = 0,
+) {
+ let first = true;
+
+ let hasRemovedComma = false;
+ const firstItemTokenIndex = state.tokens.length;
+
+ while (!eat(close) && !state.error) {
+ if (first) {
+ first = false;
+ } else {
+ expect(tt.comma);
+ state.tokens[state.tokens.length - 1].contextId = contextId;
+ // After a "this" type in TypeScript, we need to set the following comma (if any) to also be
+ // a type token so that it will be removed.
+ if (!hasRemovedComma && state.tokens[firstItemTokenIndex].isType) {
+ state.tokens[state.tokens.length - 1].isType = true;
+ hasRemovedComma = true;
+ }
+ }
+ if (allowEmpty && match(tt.comma)) {
+ // Empty item; nothing further to parse for this item.
+ } else if (eat(close)) {
+ break;
+ } else if (match(tt.ellipsis)) {
+ parseRest(isBlockScope);
+ parseAssignableListItemTypes();
+ // Support rest element trailing commas allowed by TypeScript <2.9.
+ eat(TokenType.comma);
+ expect(close);
+ break;
+ } else {
+ parseAssignableListItem(allowModifiers, isBlockScope);
+ }
+ }
+}
+
+function parseAssignableListItem(allowModifiers, isBlockScope) {
+ if (allowModifiers) {
+ tsParseModifiers([
+ ContextualKeyword._public,
+ ContextualKeyword._protected,
+ ContextualKeyword._private,
+ ContextualKeyword._readonly,
+ ContextualKeyword._override,
+ ]);
+ }
+
+ parseMaybeDefault(isBlockScope);
+ parseAssignableListItemTypes();
+ parseMaybeDefault(isBlockScope, true /* leftAlreadyParsed */);
+}
+
+function parseAssignableListItemTypes() {
+ if (isFlowEnabled) {
+ flowParseAssignableListItemTypes();
+ } else if (isTypeScriptEnabled) {
+ tsParseAssignableListItemTypes();
+ }
+}
+
+// Parses assignment pattern around given atom if possible.
+export function parseMaybeDefault(isBlockScope, leftAlreadyParsed = false) {
+ if (!leftAlreadyParsed) {
+ parseBindingAtom(isBlockScope);
+ }
+ if (!eat(tt.eq)) {
+ return;
+ }
+ const eqIndex = state.tokens.length - 1;
+ parseMaybeAssign();
+ state.tokens[eqIndex].rhsEndIndex = state.tokens.length;
+}