Fix parsing of properties and field names using semi-reserved keywords

This commit is contained in:
dcodeIO 2018-11-13 08:48:10 +01:00
parent 4289683946
commit a79db87af9
4 changed files with 34 additions and 23 deletions

View File

@ -2114,7 +2114,7 @@ export class Parser extends DiagnosticEmitter {
let identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range()); let identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
let asIdentifier: IdentifierExpression | null = null; let asIdentifier: IdentifierExpression | null = null;
if (tn.skip(Token.AS)) { if (tn.skip(Token.AS)) {
if (tn.skipIdentifierName()) { if (tn.skipIdentifier(IdentifierHandling.ALWAYS)) {
asIdentifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range()); asIdentifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
} else { } else {
this.error( this.error(
@ -2230,7 +2230,7 @@ export class Parser extends DiagnosticEmitter {
// before: Identifier ('as' Identifier)? // before: Identifier ('as' Identifier)?
if (tn.skipIdentifierName()) { if (tn.skipIdentifier(IdentifierHandling.ALWAYS)) {
let identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range()); let identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
let asIdentifier: IdentifierExpression | null = null; let asIdentifier: IdentifierExpression | null = null;
if (tn.skip(Token.AS)) { if (tn.skip(Token.AS)) {
@ -3401,15 +3401,19 @@ export class Parser extends DiagnosticEmitter {
break; break;
} }
default: { default: {
// PropertyAccessExpression
if (token == Token.DOT) {
if (tn.skipIdentifier()) {
next = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
} else {
next = this.parseExpression(tn, next = this.parseExpression(tn,
isRightAssociative(token) isRightAssociative(token)
? nextPrecedence ? nextPrecedence
: nextPrecedence + 1 : nextPrecedence + 1
); );
if (!next) return null; if (!next) return null;
}
// PropertyAccessExpression
if (token == Token.DOT) {
if (next.kind == NodeKind.IDENTIFIER) { // expr '.' Identifier if (next.kind == NodeKind.IDENTIFIER) { // expr '.' Identifier
expr = Node.createPropertyAccessExpression( expr = Node.createPropertyAccessExpression(
expr, expr,
@ -3429,6 +3433,12 @@ export class Parser extends DiagnosticEmitter {
// BinaryExpression // BinaryExpression
} else { } 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)); expr = Node.createBinaryExpression(token, expr, next, tn.range(startPos, tn.pos));
} }
break; break;

View File

@ -356,7 +356,8 @@ export function tokenIsAlsoIdentifier(token: Token): bool {
case Token.NAMESPACE: case Token.NAMESPACE:
case Token.READONLY: case Token.READONLY:
case Token.SET: case Token.SET:
case Token.TYPE: return true; case Token.TYPE:
case Token.VOID: return true;
default: return false; default: return false;
} }
} }
@ -972,12 +973,8 @@ export class Tokenizer extends DiagnosticEmitter {
return this.nextToken; return this.nextToken;
} }
skipIdentifier(): bool { skipIdentifier(identifierHandling: IdentifierHandling = IdentifierHandling.PREFER): bool {
return this.skip(Token.IDENTIFIER, IdentifierHandling.PREFER); return this.skip(Token.IDENTIFIER, identifierHandling);
}
skipIdentifierName(): bool {
return this.skip(Token.IDENTIFIER, IdentifierHandling.ALWAYS);
} }
skip(token: Token, identifierHandling: IdentifierHandling = IdentifierHandling.DEFAULT): bool { skip(token: Token, identifierHandling: IdentifierHandling = IdentifierHandling.DEFAULT): bool {

View File

@ -6,6 +6,8 @@ export class Valid<T> {
static set staticSetter(v: i32) {} static set staticSetter(v: i32) {}
instanceField: i32; instanceField: i32;
static staticField: i32; static staticField: i32;
static void: i32;
void: i32 = Valid.void;
} }
export class Invalid<T> { export class Invalid<T> {

View File

@ -6,6 +6,8 @@ export class Valid<T> {
static set staticSetter(v: i32) {} static set staticSetter(v: i32) {}
instanceField: i32; instanceField: i32;
static staticField: i32; static staticField: i32;
static void: i32;
void: i32 = Valid.void;
} }
export class Invalid<T> { export class Invalid<T> {
constructor<T>() {} constructor<T>() {}
@ -13,11 +15,11 @@ export class Invalid<T> {
get instanceGetter<T>(a: i32) {} get instanceGetter<T>(a: i32) {}
set instanceSetter<T>() {} set instanceSetter<T>() {}
} }
// ERROR 1092: "Type parameters cannot appear on a constructor declaration." in class.ts:13:13 // ERROR 1092: "Type parameters cannot appear on a constructor declaration." in class.ts:15:13
// ERROR 1110: "Type expected." in class.ts:16:20 // ERROR 1110: "Type expected." in class.ts:18:20
// ERROR 1094: "An accessor cannot have type parameters." in class.ts:21: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:21:6 // ERROR 1054: "A 'get' accessor cannot have parameters." in class.ts:23:6
// ERROR 1110: "Type expected." in class.ts:21:31 // ERROR 1110: "Type expected." in class.ts:23:31
// ERROR 1094: "An accessor cannot have type parameters." in class.ts:26:20 // 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:26:6 // 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:26:25 // ERROR 1095: "A 'set' accessor cannot have a return type annotation." in class.ts:28:25