diff --git a/src/parser.ts b/src/parser.ts index 3bda5032..7f573a8a 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -2114,7 +2114,7 @@ export class Parser extends DiagnosticEmitter { let identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range()); let asIdentifier: IdentifierExpression | null = null; if (tn.skip(Token.AS)) { - if (tn.skipIdentifierName()) { + if (tn.skipIdentifier(IdentifierHandling.ALWAYS)) { asIdentifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range()); } else { this.error( @@ -2230,7 +2230,7 @@ export class Parser extends DiagnosticEmitter { // before: Identifier ('as' Identifier)? - if (tn.skipIdentifierName()) { + if (tn.skipIdentifier(IdentifierHandling.ALWAYS)) { let identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range()); let asIdentifier: IdentifierExpression | null = null; if (tn.skip(Token.AS)) { @@ -3401,15 +3401,19 @@ export class Parser extends DiagnosticEmitter { break; } default: { - next = this.parseExpression(tn, - isRightAssociative(token) - ? nextPrecedence - : nextPrecedence + 1 - ); - if (!next) return null; // PropertyAccessExpression if (token == Token.DOT) { + if (tn.skipIdentifier()) { + next = Node.createIdentifierExpression(tn.readIdentifier(), tn.range()); + } else { + next = this.parseExpression(tn, + isRightAssociative(token) + ? nextPrecedence + : nextPrecedence + 1 + ); + if (!next) return null; + } if (next.kind == NodeKind.IDENTIFIER) { // expr '.' Identifier expr = Node.createPropertyAccessExpression( expr, @@ -3429,6 +3433,12 @@ export class Parser extends DiagnosticEmitter { // BinaryExpression } else { + next = this.parseExpression(tn, + isRightAssociative(token) + ? nextPrecedence + : nextPrecedence + 1 + ); + if (!next) return null; expr = Node.createBinaryExpression(token, expr, next, tn.range(startPos, tn.pos)); } break; diff --git a/src/tokenizer.ts b/src/tokenizer.ts index 11fabe49..31956f73 100644 --- a/src/tokenizer.ts +++ b/src/tokenizer.ts @@ -356,7 +356,8 @@ export function tokenIsAlsoIdentifier(token: Token): bool { case Token.NAMESPACE: case Token.READONLY: case Token.SET: - case Token.TYPE: return true; + case Token.TYPE: + case Token.VOID: return true; default: return false; } } @@ -972,12 +973,8 @@ export class Tokenizer extends DiagnosticEmitter { return this.nextToken; } - skipIdentifier(): bool { - return this.skip(Token.IDENTIFIER, IdentifierHandling.PREFER); - } - - skipIdentifierName(): bool { - return this.skip(Token.IDENTIFIER, IdentifierHandling.ALWAYS); + skipIdentifier(identifierHandling: IdentifierHandling = IdentifierHandling.PREFER): bool { + return this.skip(Token.IDENTIFIER, identifierHandling); } skip(token: Token, identifierHandling: IdentifierHandling = IdentifierHandling.DEFAULT): bool { diff --git a/tests/parser/class.ts b/tests/parser/class.ts index 18b4d3bf..e80a34b5 100644 --- a/tests/parser/class.ts +++ b/tests/parser/class.ts @@ -6,6 +6,8 @@ export class Valid { static set staticSetter(v: i32) {} instanceField: i32; static staticField: i32; + static void: i32; + void: i32 = Valid.void; } export class Invalid { diff --git a/tests/parser/class.ts.fixture.ts b/tests/parser/class.ts.fixture.ts index a52b7680..81579c56 100644 --- a/tests/parser/class.ts.fixture.ts +++ b/tests/parser/class.ts.fixture.ts @@ -6,6 +6,8 @@ export class Valid { static set staticSetter(v: i32) {} instanceField: i32; static staticField: i32; + static void: i32; + void: i32 = Valid.void; } export class Invalid { constructor() {} @@ -13,11 +15,11 @@ export class Invalid { get instanceGetter(a: i32) {} set instanceSetter() {} } -// ERROR 1092: "Type parameters cannot appear on a constructor declaration." in class.ts:13:13 -// ERROR 1110: "Type expected." in class.ts:16:20 -// ERROR 1094: "An accessor cannot have type parameters." in class.ts:21:20 -// ERROR 1054: "A 'get' accessor cannot have parameters." in class.ts:21:6 -// ERROR 1110: "Type expected." in class.ts:21:31 -// ERROR 1094: "An accessor cannot have type parameters." in class.ts:26:20 -// ERROR 1049: "A 'set' accessor must have exactly one parameter." in class.ts:26:6 -// ERROR 1095: "A 'set' accessor cannot have a return type annotation." in class.ts:26:25 +// ERROR 1092: "Type parameters cannot appear on a constructor declaration." in class.ts:15:13 +// ERROR 1110: "Type expected." in class.ts:18:20 +// ERROR 1094: "An accessor cannot have type parameters." in class.ts:23:20 +// ERROR 1054: "A 'get' accessor cannot have parameters." in class.ts:23:6 +// ERROR 1110: "Type expected." in class.ts:23:31 +// ERROR 1094: "An accessor cannot have type parameters." in class.ts:28:20 +// ERROR 1049: "A 'set' accessor must have exactly one parameter." in class.ts:28:6 +// ERROR 1095: "A 'set' accessor cannot have a return type annotation." in class.ts:28:25