Skip to content

Commit

Permalink
Implement parsing for flow enums (alangpierce#708)
Browse files Browse the repository at this point in the history
Progress toward alangpierce#701

This is based largely off of the Babel implementation, and handles various cases
with ellipses, `of` declarations, assignments, and enums as part of named and
default exports.

I also changed the token test to make it easier to copy and paste the error
output to get a starting point for the tokens.
  • Loading branch information
alangpierce authored and 1Lighty committed Aug 14, 2022
1 parent 4db12b5 commit c97b661
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 41 deletions.
1 change: 1 addition & 0 deletions generator/generateReadWordTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ const CONTEXTUAL_KEYWORDS = [
"require",
"set",
"static",
"symbol",
"type",
"unique",
];
Expand Down
56 changes: 52 additions & 4 deletions src/parser/plugins/flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -769,9 +769,19 @@ export function flowTryParseStatement(): boolean {
flowParseInterface();
popTypeContext(oldIsType);
return true;
} else {
return false;
} else if (isContextual(ContextualKeyword._enum)) {
flowParseEnumDeclaration();
return true;
}
return false;
}

export function flowTryParseExportDefaultExpression(): boolean {
if (isContextual(ContextualKeyword._enum)) {
flowParseEnumDeclaration();
return true;
}
return false;
}

// declares, interfaces and type aliases
Expand Down Expand Up @@ -811,7 +821,8 @@ export function flowShouldParseExportDeclaration(): boolean {
return (
isContextual(ContextualKeyword._type) ||
isContextual(ContextualKeyword._interface) ||
isContextual(ContextualKeyword._opaque)
isContextual(ContextualKeyword._opaque) ||
isContextual(ContextualKeyword._enum)
);
}

Expand All @@ -820,7 +831,8 @@ export function flowShouldDisallowExportDefaultSpecifier(): boolean {
match(tt.name) &&
(state.contextualKeyword === ContextualKeyword._type ||
state.contextualKeyword === ContextualKeyword._interface ||
state.contextualKeyword === ContextualKeyword._opaque)
state.contextualKeyword === ContextualKeyword._opaque ||
state.contextualKeyword === ContextualKeyword._enum)
);
}

Expand Down Expand Up @@ -1055,3 +1067,39 @@ function parseAsyncArrowWithTypeParameters(): boolean {
parseArrowExpression(startTokenIndex);
return true;
}

function flowParseEnumDeclaration(): void {
expectContextual(ContextualKeyword._enum);
state.tokens[state.tokens.length - 1].type = tt._enum;
parseIdentifier();
flowParseEnumBody();
}

function flowParseEnumBody(): void {
if (eatContextual(ContextualKeyword._of)) {
next();
}
expect(tt.braceL);
flowParseEnumMembers();
expect(tt.braceR);
}

function flowParseEnumMembers(): void {
while (!match(tt.braceR) && !state.error) {
if (eat(tt.ellipsis)) {
break;
}
flowParseEnumMember();
if (!match(tt.braceR)) {
expect(tt.comma);
}
}
}

function flowParseEnumMember(): void {
parseIdentifier();
if (eat(tt.eq)) {
// Flow enum values are always just one token (a string, number, or boolean literal).
next();
}
}
1 change: 1 addition & 0 deletions src/parser/tokenizer/keywords.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export enum ContextualKeyword {
_require,
_set,
_static,
_symbol,
_type,
_unique,
}
74 changes: 42 additions & 32 deletions src/parser/tokenizer/readWordTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {TokenType as tt} from "./types";
// prettier-ignore
export const READ_WORD_TREE = new Int32Array([
// ""
-1, 27, 594, 729, 1566, 2187, 2673, 3294, -1, 3510, -1, 4428, 4563, 4644, 4941, 5319, 5697, -1, 6237, 6696, 7155, 7587, 7749, 7911, -1, 8127, -1,
-1, 27, 594, 729, 1566, 2187, 2673, 3294, -1, 3510, -1, 4428, 4563, 4644, 4941, 5319, 5697, -1, 6237, 6696, 7290, 7722, 7884, 8046, -1, 8262, -1,
// "a"
-1, -1, 54, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 243, -1, -1, -1, 486, -1, -1, -1,
// "ab"
Expand Down Expand Up @@ -501,7 +501,7 @@ export const READ_WORD_TREE = new Int32Array([
// "return"
(tt._return << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "s"
-1, -1, -1, -1, -1, 6723, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6777, 6912, -1, 7020, -1, -1, -1,
-1, -1, -1, -1, -1, 6723, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6777, 6912, -1, 7020, -1, 7155, -1,
// "se"
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6750, -1, -1, -1, -1, -1, -1,
// "set"
Expand Down Expand Up @@ -534,86 +534,96 @@ export const READ_WORD_TREE = new Int32Array([
-1, -1, -1, -1, -1, -1, -1, -1, 7128, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "switch"
(tt._switch << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "sy"
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7182, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "sym"
-1, -1, 7209, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "symb"
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7236, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "symbo"
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7263, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "symbol"
ContextualKeyword._symbol << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "t"
-1, -1, -1, -1, -1, -1, -1, -1, 7182, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7344, -1, -1, -1, -1, -1, -1, 7452, -1,
-1, -1, -1, -1, -1, -1, -1, -1, 7317, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7479, -1, -1, -1, -1, -1, -1, 7587, -1,
// "th"
-1, -1, -1, -1, -1, -1, -1, -1, -1, 7209, -1, -1, -1, -1, -1, -1, -1, -1, 7263, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, 7344, -1, -1, -1, -1, -1, -1, -1, -1, 7398, -1, -1, -1, -1, -1, -1, -1, -1,
// "thi"
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7236, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7371, -1, -1, -1, -1, -1, -1, -1,
// "this"
(tt._this << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "thr"
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7425, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "thro"
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7317, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7452, -1, -1, -1,
// "throw"
(tt._throw << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "tr"
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7371, -1, -1, -1, 7425, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7506, -1, -1, -1, 7560, -1,
// "tru"
-1, -1, -1, -1, -1, 7398, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 7533, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "true"
(tt._true << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "try"
(tt._try << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "ty"
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7479, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7614, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "typ"
-1, -1, -1, -1, -1, 7506, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 7641, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "type"
ContextualKeyword._type << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7533, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
ContextualKeyword._type << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7668, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "typeo"
-1, -1, -1, -1, -1, -1, 7560, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, 7695, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "typeof"
(tt._typeof << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "u"
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7614, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7749, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "un"
-1, -1, -1, -1, -1, -1, -1, -1, -1, 7641, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, 7776, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "uni"
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7668, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7803, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "uniq"
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7695, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7830, -1, -1, -1, -1, -1,
// "uniqu"
-1, -1, -1, -1, -1, 7722, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 7857, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "unique"
ContextualKeyword._unique << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "v"
-1, 7776, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7830, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 7911, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7965, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "va"
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7803, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7938, -1, -1, -1, -1, -1, -1, -1, -1,
// "var"
(tt._var << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "vo"
-1, -1, -1, -1, -1, -1, -1, -1, -1, 7857, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, 7992, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "voi"
-1, -1, -1, -1, 7884, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, 8019, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "void"
(tt._void << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "w"
-1, -1, -1, -1, -1, -1, -1, -1, 7938, 8046, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, 8073, 8181, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "wh"
-1, -1, -1, -1, -1, -1, -1, -1, -1, 7965, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, 8100, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "whi"
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7992, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8127, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "whil"
-1, -1, -1, -1, -1, 8019, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 8154, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "while"
(tt._while << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "wi"
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8073, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8208, -1, -1, -1, -1, -1, -1,
// "wit"
-1, -1, -1, -1, -1, -1, -1, -1, 8100, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, 8235, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "with"
(tt._with << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "y"
-1, -1, -1, -1, -1, -1, -1, -1, -1, 8154, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, 8289, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "yi"
-1, -1, -1, -1, -1, 8181, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 8316, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "yie"
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8343, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "yiel"
-1, -1, -1, -1, 8235, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, 8370, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
// "yield"
(tt._yield << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
]);
6 changes: 6 additions & 0 deletions src/parser/traverser/statement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
flowShouldParseExportStar,
flowStartParseFunctionParams,
flowStartParseImportSpecifiers,
flowTryParseExportDefaultExpression,
flowTryParseStatement,
} from "../plugins/flow";
import {
Expand Down Expand Up @@ -918,6 +919,11 @@ function parseExportDefaultExpression(): void {
return;
}
}
if (isFlowEnabled) {
if (flowTryParseExportDefaultExpression()) {
return;
}
}
const functionStart = state.start;
if (eat(tt._function)) {
parseFunction(functionStart, true, true);
Expand Down
13 changes: 12 additions & 1 deletion test/flow-test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {throws} from "assert";

import {transform, Options} from "../src";
import {IMPORT_DEFAULT_PREFIX} from "./prefixes";
import {ESMODULE_PREFIX, IMPORT_DEFAULT_PREFIX} from "./prefixes";
import {assertResult} from "./util";

function assertFlowResult(
Expand Down Expand Up @@ -154,6 +154,17 @@ describe("transform flow", () => {
);
});

it("handles plain default exports when parsing flow", () => {
assertFlowResult(
`
export default 3;
`,
`"use strict";${ESMODULE_PREFIX}
exports. default = 3;
`,
);
});

it("properly parses import aliases with the flow parser", () => {
assertFlowResult(
`
Expand Down
Loading

0 comments on commit c97b661

Please sign in to comment.