Add support for parsing shorthand property assignments.

This commit is contained in:
Cyrus Najmabadi
2014-11-04 22:34:59 -08:00
parent fff8ef8b84
commit ae87b08e33
4 changed files with 42 additions and 17 deletions

View File

@@ -1986,7 +1986,17 @@ module TypeScript.Parser {
consumeToken(switchKeyword);
var openParenToken = eatToken(SyntaxKind.OpenParenToken);
var expression = parseExpression(/*allowIn:*/ true);
var expression: IExpressionSyntax;
// if we have "switch {"
// then don't try to consume the { as the start of an expression.
if (openParenToken.fullWidth() === 0 && currentToken().kind === SyntaxKind.OpenBraceToken) {
expression = eatIdentifierToken();
}
else {
expression = parseExpression(/*allowIn:*/ true);
}
var closeParenToken = eatToken(SyntaxKind.CloseParenToken);
var openBraceToken = eatToken(SyntaxKind.OpenBraceToken);
@@ -3312,8 +3322,23 @@ module TypeScript.Parser {
else if (isFunctionPropertyAssignment(inErrorRecovery)) {
return parseFunctionPropertyAssignment();
}
else if (isSimplePropertyAssignment(inErrorRecovery)) {
return parseSimplePropertyAssignment();
else if (isSimpleOrShorthandPropertyAssignment(inErrorRecovery)) {
var _currentToken = currentToken();
if (isIdentifier(_currentToken) && peekToken(1).kind !== SyntaxKind.ColonToken) {
// To be a shorthand property assignment we must have an identifier (and not a
// keyword or literal) and it must not be followed by a colon.
return consumeToken(_currentToken);
}
else {
// If we didn't have an identifier, then we must have gotten a keyword or a
// literal. Neither of these are allowed in a shorthand property, so this must
// be a simple property assignment.
//
// Also, if we have an identifier and it is followed by a colon then this is
// definitely a simple property assignment.
return new SimplePropertyAssignmentSyntax(parseNodeData,
eatPropertyName(), eatToken(SyntaxKind.ColonToken), tryParseAssignmentExpressionOrHigher(/*force:*/ true, /*allowIn:*/ true));
}
}
else {
return undefined;
@@ -3323,7 +3348,7 @@ module TypeScript.Parser {
function isPropertyAssignment(inErrorRecovery: boolean): boolean {
return isAccessor(modifierCount(), inErrorRecovery) ||
isFunctionPropertyAssignment(inErrorRecovery) ||
isSimplePropertyAssignment(inErrorRecovery);
isSimpleOrShorthandPropertyAssignment(inErrorRecovery);
}
function eatPropertyName(): ISyntaxToken {
@@ -3344,15 +3369,10 @@ module TypeScript.Parser {
parseBlock(/*parseBlockEvenWithNoOpenBrace:*/ false, /*checkForStrictMode:*/ true));
}
function isSimplePropertyAssignment(inErrorRecovery: boolean): boolean {
function isSimpleOrShorthandPropertyAssignment(inErrorRecovery: boolean): boolean {
return isPropertyName(currentToken(), inErrorRecovery);
}
function parseSimplePropertyAssignment(): SimplePropertyAssignmentSyntax {
return new SimplePropertyAssignmentSyntax(parseNodeData,
eatPropertyName(), eatToken(SyntaxKind.ColonToken), tryParseAssignmentExpressionOrHigher(/*force:*/ true, /*allowIn:*/ true));
}
function isPropertyName(token: ISyntaxToken, inErrorRecovery: boolean): boolean {
// NOTE: we do *not* want to check "isIdentifier" here. Any IdentifierName is
// allowed here, even reserved words like keywords.
@@ -3372,6 +3392,10 @@ module TypeScript.Parser {
}
}
return isLiteralPropertyName(token);
}
function isLiteralPropertyName(token: ISyntaxToken): boolean {
// We allow a template literal while parser for error tolerance. We'll report errors
// on this later in the grammar checker walker.
var kind = token.kind;

View File

@@ -219,7 +219,7 @@ module TypeScript.Scanner {
}
class FixedWidthTokenWithNoTrivia implements ISyntaxToken {
public _primaryExpressionBrand: any; public _memberExpressionBrand: any; public _leftHandSideExpressionBrand: any; public _postfixExpressionBrand: any; public _unaryExpressionBrand: any; public _expressionBrand: any; public _typeBrand: any; public _nameBrand: any;
public _primaryExpressionBrand: any; public _memberExpressionBrand: any; public _leftHandSideExpressionBrand: any; public _postfixExpressionBrand: any; public _unaryExpressionBrand: any; public _expressionBrand: any; public _typeBrand: any; public _nameBrand: any; public _propertyAssignmentBrand: any;
public parent: ISyntaxElement;
public childCount: number;
@@ -254,7 +254,7 @@ module TypeScript.Scanner {
FixedWidthTokenWithNoTrivia.prototype.childCount = 0;
class LargeScannerToken implements ISyntaxToken {
public _primaryExpressionBrand: any; public _memberExpressionBrand: any; public _leftHandSideExpressionBrand: any; public _postfixExpressionBrand: any; public _unaryExpressionBrand: any; public _expressionBrand: any; public _typeBrand: any; public _nameBrand: any;
public _primaryExpressionBrand: any; public _memberExpressionBrand: any; public _leftHandSideExpressionBrand: any; public _postfixExpressionBrand: any; public _unaryExpressionBrand: any; public _expressionBrand: any; public _typeBrand: any; public _nameBrand: any; public _propertyAssignmentBrand: any;
public parent: ISyntaxElement;
public childCount: number;

View File

@@ -450,7 +450,7 @@ module TypeScript {
_memberDeclarationBrand: any;
}
export interface IPropertyAssignmentSyntax extends ISyntaxNode {
export interface IPropertyAssignmentSyntax extends ISyntaxNodeOrToken {
_propertyAssignmentBrand: any;
}

View File

@@ -1,7 +1,7 @@
///<reference path='references.ts' />
module TypeScript {
export interface ISyntaxToken extends ISyntaxNodeOrToken, INameSyntax, IPrimaryExpressionSyntax {
export interface ISyntaxToken extends ISyntaxNodeOrToken, INameSyntax, IPrimaryExpressionSyntax, IPropertyAssignmentSyntax {
// Adjusts the full start of this token. Should only be called by the parser.
setFullStart(fullStart: number): void;
@@ -304,7 +304,8 @@ module TypeScript.Syntax {
}
class EmptyToken implements ISyntaxToken {
public _primaryExpressionBrand: any; public _memberExpressionBrand: any; public _leftHandSideExpressionBrand: any; public _postfixExpressionBrand: any; public _unaryExpressionBrand: any; public _expressionBrand: any; public _typeBrand: any; public _nameBrand: any;
public _primaryExpressionBrand: any; public _memberExpressionBrand: any; public _leftHandSideExpressionBrand: any; public _postfixExpressionBrand: any; public _unaryExpressionBrand: any; public _expressionBrand: any; public _typeBrand: any; public _nameBrand: any; public _propertyAssignmentBrand: any;
public parent: ISyntaxElement;
public childCount: number;
@@ -418,7 +419,7 @@ module TypeScript.Syntax {
EmptyToken.prototype.childCount = 0;
class RealizedToken implements ISyntaxToken {
public _primaryExpressionBrand: any; public _memberExpressionBrand: any; public _leftHandSideExpressionBrand: any; public _postfixExpressionBrand: any; public _unaryExpressionBrand: any; public _expressionBrand: any; public _typeBrand: any; public _nameBrand: any;
public _primaryExpressionBrand: any; public _memberExpressionBrand: any; public _leftHandSideExpressionBrand: any; public _postfixExpressionBrand: any; public _unaryExpressionBrand: any; public _expressionBrand: any; public _typeBrand: any; public _nameBrand: any; public _propertyAssignmentBrand: any;
private _fullStart: number;
private _isKeywordConvertedToIdentifier: boolean;
@@ -491,7 +492,7 @@ module TypeScript.Syntax {
RealizedToken.prototype.childCount = 0;
class ConvertedKeywordToken implements ISyntaxToken {
public _primaryExpressionBrand: any; public _memberExpressionBrand: any; public _leftHandSideExpressionBrand: any; public _postfixExpressionBrand: any; public _unaryExpressionBrand: any; public _expressionBrand: any; public _typeBrand: any; public _nameBrand: any;
public _primaryExpressionBrand: any; public _memberExpressionBrand: any; public _leftHandSideExpressionBrand: any; public _postfixExpressionBrand: any; public _unaryExpressionBrand: any; public _expressionBrand: any; public _typeBrand: any; public _nameBrand: any; public _propertyAssignmentBrand: any;
public parent: ISyntaxElement;
public kind: SyntaxKind;