Skip to content

Commit a79db87

Browse files
committed
Fix parsing of properties and field names using semi-reserved keywords
1 parent 4289683 commit a79db87

File tree

4 files changed

+34
-23
lines changed

4 files changed

+34
-23
lines changed

src/parser.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2114,7 +2114,7 @@ export class Parser extends DiagnosticEmitter {
21142114
let identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
21152115
let asIdentifier: IdentifierExpression | null = null;
21162116
if (tn.skip(Token.AS)) {
2117-
if (tn.skipIdentifierName()) {
2117+
if (tn.skipIdentifier(IdentifierHandling.ALWAYS)) {
21182118
asIdentifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
21192119
} else {
21202120
this.error(
@@ -2230,7 +2230,7 @@ export class Parser extends DiagnosticEmitter {
22302230

22312231
// before: Identifier ('as' Identifier)?
22322232

2233-
if (tn.skipIdentifierName()) {
2233+
if (tn.skipIdentifier(IdentifierHandling.ALWAYS)) {
22342234
let identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
22352235
let asIdentifier: IdentifierExpression | null = null;
22362236
if (tn.skip(Token.AS)) {
@@ -3401,15 +3401,19 @@ export class Parser extends DiagnosticEmitter {
34013401
break;
34023402
}
34033403
default: {
3404-
next = this.parseExpression(tn,
3405-
isRightAssociative(token)
3406-
? nextPrecedence
3407-
: nextPrecedence + 1
3408-
);
3409-
if (!next) return null;
34103404

34113405
// PropertyAccessExpression
34123406
if (token == Token.DOT) {
3407+
if (tn.skipIdentifier()) {
3408+
next = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
3409+
} else {
3410+
next = this.parseExpression(tn,
3411+
isRightAssociative(token)
3412+
? nextPrecedence
3413+
: nextPrecedence + 1
3414+
);
3415+
if (!next) return null;
3416+
}
34133417
if (next.kind == NodeKind.IDENTIFIER) { // expr '.' Identifier
34143418
expr = Node.createPropertyAccessExpression(
34153419
expr,
@@ -3429,6 +3433,12 @@ export class Parser extends DiagnosticEmitter {
34293433

34303434
// BinaryExpression
34313435
} else {
3436+
next = this.parseExpression(tn,
3437+
isRightAssociative(token)
3438+
? nextPrecedence
3439+
: nextPrecedence + 1
3440+
);
3441+
if (!next) return null;
34323442
expr = Node.createBinaryExpression(token, expr, next, tn.range(startPos, tn.pos));
34333443
}
34343444
break;

src/tokenizer.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,8 @@ export function tokenIsAlsoIdentifier(token: Token): bool {
356356
case Token.NAMESPACE:
357357
case Token.READONLY:
358358
case Token.SET:
359-
case Token.TYPE: return true;
359+
case Token.TYPE:
360+
case Token.VOID: return true;
360361
default: return false;
361362
}
362363
}
@@ -972,12 +973,8 @@ export class Tokenizer extends DiagnosticEmitter {
972973
return this.nextToken;
973974
}
974975

975-
skipIdentifier(): bool {
976-
return this.skip(Token.IDENTIFIER, IdentifierHandling.PREFER);
977-
}
978-
979-
skipIdentifierName(): bool {
980-
return this.skip(Token.IDENTIFIER, IdentifierHandling.ALWAYS);
976+
skipIdentifier(identifierHandling: IdentifierHandling = IdentifierHandling.PREFER): bool {
977+
return this.skip(Token.IDENTIFIER, identifierHandling);
981978
}
982979

983980
skip(token: Token, identifierHandling: IdentifierHandling = IdentifierHandling.DEFAULT): bool {

tests/parser/class.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ export class Valid<T> {
66
static set staticSetter(v: i32) {}
77
instanceField: i32;
88
static staticField: i32;
9+
static void: i32;
10+
void: i32 = Valid.void;
911
}
1012
export class Invalid<T> {
1113

tests/parser/class.ts.fixture.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,20 @@ export class Valid<T> {
66
static set staticSetter(v: i32) {}
77
instanceField: i32;
88
static staticField: i32;
9+
static void: i32;
10+
void: i32 = Valid.void;
911
}
1012
export class Invalid<T> {
1113
constructor<T>() {}
1214
instanceFunction() {}
1315
get instanceGetter<T>(a: i32) {}
1416
set instanceSetter<T>() {}
1517
}
16-
// ERROR 1092: "Type parameters cannot appear on a constructor declaration." in class.ts:13:13
17-
// ERROR 1110: "Type expected." in class.ts:16:20
18-
// ERROR 1094: "An accessor cannot have type parameters." in class.ts:21:20
19-
// ERROR 1054: "A 'get' accessor cannot have parameters." in class.ts:21:6
20-
// ERROR 1110: "Type expected." in class.ts:21:31
21-
// ERROR 1094: "An accessor cannot have type parameters." in class.ts:26:20
22-
// ERROR 1049: "A 'set' accessor must have exactly one parameter." in class.ts:26:6
23-
// ERROR 1095: "A 'set' accessor cannot have a return type annotation." in class.ts:26:25
18+
// ERROR 1092: "Type parameters cannot appear on a constructor declaration." in class.ts:15:13
19+
// ERROR 1110: "Type expected." in class.ts:18:20
20+
// ERROR 1094: "An accessor cannot have type parameters." in class.ts:23:20
21+
// ERROR 1054: "A 'get' accessor cannot have parameters." in class.ts:23:6
22+
// ERROR 1110: "Type expected." in class.ts:23:31
23+
// ERROR 1094: "An accessor cannot have type parameters." in class.ts:28:20
24+
// ERROR 1049: "A 'set' accessor must have exactly one parameter." in class.ts:28:6
25+
// ERROR 1095: "A 'set' accessor cannot have a return type annotation." in class.ts:28:25

0 commit comments

Comments
 (0)