Skip to content

Commit 5ab81a0

Browse files
alangpiercedcodeIO
authored andcommitted
Allow keywords in named import/export syntax (#107)
1 parent e415377 commit 5ab81a0

8 files changed

+119
-35
lines changed

src/parser.ts

+28-27
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import {
1414
Tokenizer,
1515
Token,
1616
Range,
17-
CommentHandler
17+
CommentHandler,
18+
IdentifierHandling
1819
} from "./tokenizer";
1920

2021
import {
@@ -579,7 +580,7 @@ export class Parser extends DiagnosticEmitter {
579580
this.tryParseSignatureIsSignature = false;
580581
return null;
581582
}
582-
} else if (tn.skip(Token.IDENTIFIER)) {
583+
} else if (tn.skipIdentifier()) {
583584
let name = Node.createIdentifierExpression(tn.readIdentifier(), tn.range(tn.tokenPos, tn.pos));
584585
if (tn.skip(Token.QUESTION)) {
585586
isSignature = true;
@@ -678,11 +679,11 @@ export class Parser extends DiagnosticEmitter {
678679
// at '@': Identifier ('.' Identifier)* '(' Arguments
679680

680681
var startPos = tn.tokenPos;
681-
if (tn.skip(Token.IDENTIFIER)) {
682+
if (tn.skipIdentifier()) {
682683
let name = tn.readIdentifier();
683684
let expression: Expression = Node.createIdentifierExpression(name, tn.range(startPos, tn.pos));
684685
while (tn.skip(Token.DOT)) {
685-
if (tn.skip(Token.IDENTIFIER)) {
686+
if (tn.skipIdentifier()) {
686687
name = tn.readIdentifier();
687688
expression = Node.createPropertyAccessExpression(
688689
expression,
@@ -744,7 +745,7 @@ export class Parser extends DiagnosticEmitter {
744745

745746
// before: Identifier (':' Type)? ('=' Expression)?
746747

747-
if (!tn.skip(Token.IDENTIFIER)) {
748+
if (!tn.skipIdentifier()) {
748749
this.error(
749750
DiagnosticCode.Identifier_expected,
750751
tn.range()
@@ -853,7 +854,7 @@ export class Parser extends DiagnosticEmitter {
853854

854855
// before: Identifier ('=' Expression)?
855856

856-
if (!tn.skip(Token.IDENTIFIER)) {
857+
if (!tn.skipIdentifier()) {
857858
this.error(
858859
DiagnosticCode.Identifier_expected,
859860
tn.range()
@@ -1081,7 +1082,7 @@ export class Parser extends DiagnosticEmitter {
10811082
}
10821083
isRest = true;
10831084
}
1084-
if (tn.skip(Token.IDENTIFIER)) {
1085+
if (tn.skipIdentifier()) {
10851086
if (!isRest) startRange = tn.range();
10861087
let identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
10871088
let type: CommonTypeNode | null = null;
@@ -1154,7 +1155,7 @@ export class Parser extends DiagnosticEmitter {
11541155
// '{' Statement* '}'
11551156
// ';'?
11561157

1157-
if (!tn.skip(Token.IDENTIFIER)) {
1158+
if (!tn.skipIdentifier()) {
11581159
this.error(
11591160
DiagnosticCode.Identifier_expected,
11601161
tn.range(tn.pos)
@@ -1281,7 +1282,7 @@ export class Parser extends DiagnosticEmitter {
12811282
// Statement
12821283

12831284
if (tn.token == Token.FUNCTION) {
1284-
if (tn.skip(Token.IDENTIFIER)) {
1285+
if (tn.skipIdentifier()) {
12851286
name = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
12861287
} else { // empty name
12871288
name = Node.createEmptyIdentifierExpression(tn.range(tn.pos));
@@ -1397,7 +1398,7 @@ export class Parser extends DiagnosticEmitter {
13971398

13981399
var isInterface = tn.token == Token.INTERFACE;
13991400

1400-
if (!tn.skip(Token.IDENTIFIER)) {
1401+
if (!tn.skipIdentifier()) {
14011402
this.error(
14021403
DiagnosticCode.Identifier_expected,
14031404
tn.range()
@@ -1565,7 +1566,7 @@ export class Parser extends DiagnosticEmitter {
15651566
var setStart: i32 = 0;
15661567
var setEnd: i32 = 0;
15671568
if (tn.skip(Token.GET)) {
1568-
if (tn.peek(true, true) == Token.IDENTIFIER && !tn.nextTokenOnNewLine) {
1569+
if (tn.peek(true, IdentifierHandling.PREFER) == Token.IDENTIFIER && !tn.nextTokenOnNewLine) {
15691570
flags |= CommonFlags.GET;
15701571
isGetter = true;
15711572
setStart = tn.tokenPos;
@@ -1580,7 +1581,7 @@ export class Parser extends DiagnosticEmitter {
15801581
tn.reset(state);
15811582
}
15821583
} else if (tn.skip(Token.SET)) {
1583-
if (tn.peek(true, true) == Token.IDENTIFIER && !tn.nextTokenOnNewLine) {
1584+
if (tn.peek(true, IdentifierHandling.PREFER) == Token.IDENTIFIER && !tn.nextTokenOnNewLine) {
15841585
flags |= CommonFlags.SET | CommonFlags.SET;
15851586
isSetter = true;
15861587
setStart = tn.tokenPos;
@@ -1617,7 +1618,7 @@ export class Parser extends DiagnosticEmitter {
16171618
}
16181619
}
16191620

1620-
if (!isConstructor && !tn.skip(Token.IDENTIFIER)) {
1621+
if (!isConstructor && !tn.skipIdentifier()) {
16211622
this.error(
16221623
DiagnosticCode.Identifier_expected,
16231624
tn.range()
@@ -1833,7 +1834,7 @@ export class Parser extends DiagnosticEmitter {
18331834

18341835
// at 'namespace': Identifier '{' (Variable | Function)* '}'
18351836

1836-
if (tn.skip(Token.IDENTIFIER)) {
1837+
if (tn.skipIdentifier()) {
18371838
let identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
18381839
if (tn.skip(Token.OPENBRACE)) {
18391840
let members = new Array<Statement>();
@@ -1926,11 +1927,11 @@ export class Parser extends DiagnosticEmitter {
19261927

19271928
// before: Identifier ('as' Identifier)?
19281929

1929-
if (tn.skip(Token.IDENTIFIER)) {
1930+
if (tn.skipIdentifier()) {
19301931
let identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
19311932
let asIdentifier: IdentifierExpression | null = null;
19321933
if (tn.skip(Token.AS)) {
1933-
if (tn.skip(Token.IDENTIFIER)) {
1934+
if (tn.skipIdentifierName()) {
19341935
asIdentifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
19351936
} else {
19361937
this.error(
@@ -1986,7 +1987,7 @@ export class Parser extends DiagnosticEmitter {
19861987
}
19871988
} else if (tn.skip(Token.ASTERISK)) {
19881989
if (tn.skip(Token.AS)) {
1989-
if (tn.skip(Token.IDENTIFIER)) {
1990+
if (tn.skipIdentifier()) {
19901991
namespaceName = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
19911992
} else {
19921993
this.error(
@@ -2044,11 +2045,11 @@ export class Parser extends DiagnosticEmitter {
20442045

20452046
// before: Identifier ('as' Identifier)?
20462047

2047-
if (tn.skip(Token.IDENTIFIER)) {
2048+
if (tn.skipIdentifierName()) {
20482049
let identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
20492050
let asIdentifier: IdentifierExpression | null = null;
20502051
if (tn.skip(Token.AS)) {
2051-
if (tn.skip(Token.IDENTIFIER)) {
2052+
if (tn.skipIdentifier()) {
20522053
asIdentifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
20532054
} else {
20542055
this.error(
@@ -2081,10 +2082,10 @@ export class Parser extends DiagnosticEmitter {
20812082

20822083
// at 'export' 'import': Identifier ('=' Identifier)? ';'?
20832084

2084-
if (tn.skip(Token.IDENTIFIER)) {
2085+
if (tn.skipIdentifier()) {
20852086
let asIdentifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
20862087
if (tn.skip(Token.EQUALS)) {
2087-
if (tn.skip(Token.IDENTIFIER)) {
2088+
if (tn.skipIdentifier()) {
20882089
let identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
20892090
let ret = Node.createExportImportStatement(identifier, asIdentifier, tn.range(startPos, tn.pos));
20902091
tn.skip(Token.SEMICOLON);
@@ -2242,7 +2243,7 @@ export class Parser extends DiagnosticEmitter {
22422243

22432244
var identifier: IdentifierExpression | null = null;
22442245
if (tn.peek(true) == Token.IDENTIFIER && !tn.nextTokenOnNewLine) {
2245-
tn.next(true);
2246+
tn.next(IdentifierHandling.PREFER);
22462247
identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
22472248
}
22482249
var ret = Node.createBreakStatement(identifier, tn.range());
@@ -2258,7 +2259,7 @@ export class Parser extends DiagnosticEmitter {
22582259

22592260
var identifier: IdentifierExpression | null = null;
22602261
if (tn.peek(true) == Token.IDENTIFIER && !tn.nextTokenOnNewLine) {
2261-
tn.next(true);
2262+
tn.next(IdentifierHandling.PREFER);
22622263
identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
22632264
}
22642265
var ret = Node.createContinueStatement(identifier, tn.range());
@@ -2578,7 +2579,7 @@ export class Parser extends DiagnosticEmitter {
25782579
);
25792580
return null;
25802581
}
2581-
if (!tn.skip(Token.IDENTIFIER)) {
2582+
if (!tn.skipIdentifier()) {
25822583
this.error(
25832584
DiagnosticCode.Identifier_expected,
25842585
tn.range()
@@ -2656,7 +2657,7 @@ export class Parser extends DiagnosticEmitter {
26562657

26572658
// at 'type': Identifier ('<' TypeParameters '>')? '=' Type ';'?
26582659

2659-
if (tn.skip(Token.IDENTIFIER)) {
2660+
if (tn.skipIdentifier()) {
26602661
let name = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
26612662
let typeParameters: TypeParameterNode[] | null = null;
26622663
if (tn.skip(Token.LESSTHAN)) {
@@ -2744,7 +2745,7 @@ export class Parser extends DiagnosticEmitter {
27442745
tn: Tokenizer
27452746
): Expression | null {
27462747

2747-
var token = tn.next(true);
2748+
var token = tn.next(IdentifierHandling.PREFER);
27482749
var startPos = tn.tokenPos;
27492750
var expr: Expression | null = null;
27502751

@@ -2821,7 +2822,7 @@ export class Parser extends DiagnosticEmitter {
28212822
let state = tn.mark();
28222823
let again = true;
28232824
do {
2824-
switch (tn.next(true)) {
2825+
switch (tn.next(IdentifierHandling.PREFER)) {
28252826

28262827
// function expression
28272828
case Token.DOT_DOT_DOT: {

src/tokenizer.ts

+29-8
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,12 @@ export enum Token {
166166
ENDOFFILE
167167
}
168168

169+
export enum IdentifierHandling {
170+
DEFAULT,
171+
PREFER,
172+
ALWAYS
173+
}
174+
169175
export function tokenFromKeyword(text: string): Token {
170176
switch (text.length && text.charCodeAt(0)) {
171177
case CharCode.a: {
@@ -523,12 +529,15 @@ export class Tokenizer extends DiagnosticEmitter {
523529
}
524530
}
525531

526-
next(preferIdentifier: bool = false): Token {
532+
next(identifierHandling: IdentifierHandling = IdentifierHandling.DEFAULT): Token {
527533
this.nextToken = -1;
528-
return this.token = this.unsafeNext(preferIdentifier);
534+
return this.token = this.unsafeNext(identifierHandling);
529535
}
530536

531-
private unsafeNext(preferIdentifier: bool = false, maxTokenLength: i32 = i32.MAX_VALUE): Token {
537+
private unsafeNext(
538+
identifierHandling: IdentifierHandling = IdentifierHandling.DEFAULT,
539+
maxTokenLength: i32 = i32.MAX_VALUE
540+
): Token {
532541
var text = this.source.text;
533542
while (this.pos < this.end) {
534543
this.tokenPos = this.pos;
@@ -908,7 +917,11 @@ export class Tokenizer extends DiagnosticEmitter {
908917
let keywordToken = tokenFromKeyword(keywordText);
909918
if (
910919
keywordToken != Token.INVALID &&
911-
!(preferIdentifier && tokenIsAlsoIdentifier(keywordToken))
920+
identifierHandling !== IdentifierHandling.ALWAYS &&
921+
!(
922+
identifierHandling === IdentifierHandling.PREFER &&
923+
tokenIsAlsoIdentifier(keywordToken)
924+
)
912925
) {
913926
return keywordToken;
914927
}
@@ -933,15 +946,15 @@ export class Tokenizer extends DiagnosticEmitter {
933946

934947
peek(
935948
checkOnNewLine: bool = false,
936-
preferIdentifier: bool = false,
949+
identifierHandling: IdentifierHandling = IdentifierHandling.DEFAULT,
937950
maxCompoundLength: i32 = i32.MAX_VALUE
938951
): Token {
939952
var text = this.source.text;
940953
if (this.nextToken < 0) {
941954
let posBefore = this.pos;
942955
let tokenBefore = this.token;
943956
let tokenPosBefore = this.tokenPos;
944-
this.nextToken = this.unsafeNext(preferIdentifier, maxCompoundLength);
957+
this.nextToken = this.unsafeNext(identifierHandling, maxCompoundLength);
945958
this.nextTokenPos = this.tokenPos;
946959
if (checkOnNewLine) {
947960
this.nextTokenOnNewLine = false;
@@ -959,7 +972,15 @@ export class Tokenizer extends DiagnosticEmitter {
959972
return this.nextToken;
960973
}
961974

962-
skip(token: Token): bool {
975+
skipIdentifier(): bool {
976+
return this.skip(Token.IDENTIFIER, IdentifierHandling.PREFER);
977+
}
978+
979+
skipIdentifierName(): bool {
980+
return this.skip(Token.IDENTIFIER, IdentifierHandling.ALWAYS);
981+
}
982+
983+
skip(token: Token, identifierHandling: IdentifierHandling = IdentifierHandling.DEFAULT): bool {
963984
var posBefore = this.pos;
964985
var tokenBefore = this.token;
965986
var tokenPosBefore = this.tokenPos;
@@ -970,7 +991,7 @@ export class Tokenizer extends DiagnosticEmitter {
970991
break;
971992
}
972993
}
973-
this.token = this.unsafeNext(token == Token.IDENTIFIER, maxCompoundLength);
994+
this.token = this.unsafeNext(identifierHandling, maxCompoundLength);
974995
if (this.token == token) {
975996
this.nextToken = -1;
976997
return true;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
(module
2+
(type $i (func (result i32)))
3+
(memory $0 1)
4+
(export "default" (func $named-export-default/get3))
5+
(export "memory" (memory $0))
6+
(func $named-export-default/get3 (; 0 ;) (type $i) (result i32)
7+
(i32.const 3)
8+
)
9+
)
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
function get3(): i32 {
2+
return 3;
3+
}
4+
5+
export {get3 as default};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
(module
2+
(type $i (func (result i32)))
3+
(global $HEAP_BASE i32 (i32.const 4))
4+
(memory $0 1)
5+
(export "default" (func $named-export-default/get3))
6+
(export "memory" (memory $0))
7+
(func $named-export-default/get3 (; 0 ;) (type $i) (result i32)
8+
(return
9+
(i32.const 3)
10+
)
11+
)
12+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
(module
2+
(type $i (func (result i32)))
3+
(memory $0 1)
4+
(export "getValue" (func $named-import-default/getValue))
5+
(export "memory" (memory $0))
6+
(func $named-export-default/get3 (; 0 ;) (type $i) (result i32)
7+
(i32.const 3)
8+
)
9+
(func $named-import-default/getValue (; 1 ;) (type $i) (result i32)
10+
(call $named-export-default/get3)
11+
)
12+
)
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import {
2+
default as get3
3+
} from "./named-export-default";
4+
5+
export function getValue(): i32 {
6+
return get3();
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
(module
2+
(type $i (func (result i32)))
3+
(global $HEAP_BASE i32 (i32.const 4))
4+
(memory $0 1)
5+
(export "getValue" (func $named-import-default/getValue))
6+
(export "memory" (memory $0))
7+
(func $named-export-default/get3 (; 0 ;) (type $i) (result i32)
8+
(return
9+
(i32.const 3)
10+
)
11+
)
12+
(func $named-import-default/getValue (; 1 ;) (type $i) (result i32)
13+
(return
14+
(call $named-export-default/get3)
15+
)
16+
)
17+
)

0 commit comments

Comments
 (0)