Simplify parsing.

This commit is contained in:
Cyrus Najmabadi 2014-11-25 21:30:26 -08:00
parent a8949ee196
commit 70ecd0b00c

View file

@ -1219,18 +1219,17 @@ module TypeScript.Parser {
return parseSyntaxList<IClassElementSyntax>(ListParsingState.ClassDeclaration_ClassElements)
}
function isAccessor(modifierCount: number, inErrorRecovery: boolean): boolean {
var tokenKind = peekToken(modifierCount).kind;
function isAccessor(inErrorRecovery: boolean): boolean {
var tokenKind = currentToken().kind;
if (tokenKind !== SyntaxKind.GetKeyword &&
tokenKind !== SyntaxKind.SetKeyword) {
return false;
}
return isPropertyName(/*peekIndex:*/ modifierCount + 1, inErrorRecovery);
return isPropertyName(/*peekIndex:*/ 1, inErrorRecovery);
}
function parseAccessor(): IAccessorSyntax {
var modifiers = parseModifiers();
function parseAccessor(modifiers: ISyntaxToken[]): IAccessorSyntax {
var _currentToken = currentToken();
var tokenKind = _currentToken.kind;
@ -1267,36 +1266,36 @@ module TypeScript.Parser {
// Note: the order of these calls is important. Specifically, isMemberVariableDeclaration
// checks for a subset of the conditions of the previous two calls.
var _modifierCount = modifierCount();
return isConstructorDeclaration(_modifierCount) ||
isAccessor(_modifierCount, inErrorRecovery) ||
isIndexMemberDeclaration(_modifierCount) ||
isMemberVariableOrFunctionDeclaration(_modifierCount, inErrorRecovery);
return _modifierCount > 0 ||
isConstructorDeclaration() ||
isAccessor(inErrorRecovery) ||
isIndexMemberDeclaration() ||
isMemberVariableOrFunctionDeclaration(inErrorRecovery);
}
function isMemberVariableOrFunctionDeclaration(peekIndex: number, inErrorRecovery: boolean) {
var tokenN = peekToken(peekIndex);
var tokenNKind = tokenN.kind;
function isMemberVariableOrFunctionDeclaration(inErrorRecovery: boolean) {
var token0 = currentToken();
var token0Kind = token0.kind;
// If we have a '*', then this is a generator function.
if (tokenNKind === SyntaxKind.AsteriskToken) {
if (token0Kind === SyntaxKind.AsteriskToken) {
if (inErrorRecovery) {
// If we're in error recovery, we might see a random * that is part of some
// expression. Really, in order to view this as a generator function, we want
// to see at least '*id<' or '*id('. Otherwise, we won't think of this as the
// start of a member variable/function.
return peekToken(peekIndex + 1).kind === SyntaxKind.IdentifierName &&
(peekToken(peekIndex + 2).kind === SyntaxKind.LessThanToken || peekToken(peekIndex + 2).kind === SyntaxKind.OpenParenToken);
return peekToken(1).kind === SyntaxKind.IdentifierName && isCallSignature(/*peekIndex:*/ 2);
}
return true;
}
// Check if its the start of a property or method. Both must start with a property name.
if (!isPropertyName(peekIndex, inErrorRecovery)) {
if (!isPropertyName(0, inErrorRecovery)) {
return false;
}
if (!SyntaxFacts.isAnyKeyword(tokenNKind)) {
if (!SyntaxFacts.isAnyKeyword(token0Kind)) {
// It wasn't a keyword. So this is definitely a member variable or function.
return true;
}
@ -1314,7 +1313,7 @@ module TypeScript.Parser {
// public<
// public <eof>
// public <newline>
var nextToken = peekToken(peekIndex + 1);
var nextToken = peekToken(1);
switch (nextToken.kind) {
case SyntaxKind.SemicolonToken:
case SyntaxKind.EqualsToken:
@ -1338,18 +1337,17 @@ module TypeScript.Parser {
// Have to check for indexers before anything else. That way if we see "[foo:" we
// parse it out as an indexer and not a member function or variable.
var _modifierCount = modifierCount();
if (isConstructorDeclaration(_modifierCount)) {
return parseConstructorDeclaration();
var modifiers = parseModifiers();
if (isConstructorDeclaration()) {
return parseConstructorDeclaration(modifiers);
}
else if (isIndexMemberDeclaration(_modifierCount)) {
return parseIndexMemberDeclaration();
else if (isIndexMemberDeclaration()) {
return parseIndexMemberDeclaration(modifiers);
}
else if (isAccessor(_modifierCount, inErrorRecovery)) {
return parseAccessor();
else if (isAccessor(inErrorRecovery)) {
return parseAccessor(modifiers);
}
else if (isMemberVariableOrFunctionDeclaration(/*peekIndex:*/ _modifierCount, inErrorRecovery)) {
var modifiers = parseModifiers();
else if (modifiers.length > 0 || isMemberVariableOrFunctionDeclaration(inErrorRecovery)) {
var asterixToken = tryEatToken(SyntaxKind.AsteriskToken);
var propertyName = parsePropertyName();
@ -1369,20 +1367,20 @@ module TypeScript.Parser {
}
}
function isConstructorDeclaration(modifierCount: number): boolean {
function isConstructorDeclaration(): boolean {
// Note: we deviate slightly from the spec here. If we see 'constructor' then we
// assume this is a constructor. That means, if a user writes "public constructor;"
// it won't be viewed as a member. As a workaround, they can simply write:
// public 'constructor';
return peekToken(modifierCount).kind === SyntaxKind.ConstructorKeyword;
return currentToken().kind === SyntaxKind.ConstructorKeyword;
}
function parseConstructorDeclaration(): ConstructorDeclarationSyntax {
function parseConstructorDeclaration(modifiers: ISyntaxToken[]): ConstructorDeclarationSyntax {
// Note: if we see an arrow after the close paren, then try to parse out a function
// block anyways. It's likely the user just though '=> expr' was legal anywhere a
// block was legal.
return new ConstructorDeclarationSyntax(contextFlags,
parseModifiers(),
modifiers,
eatToken(SyntaxKind.ConstructorKeyword),
parseCallSignature(/*requireCompleteTypeParameterList:*/ false, /*yieldAndGeneratorParameterContext:*/ false, /*asyncContext:*/ false),
parseFunctionBody(/*isGenerator:*/ false, /*asyncContext:*/ false));
@ -1421,13 +1419,15 @@ module TypeScript.Parser {
eatExplicitOrAutomaticSemicolon(/*allowWithoutNewline:*/ false));
}
function isIndexMemberDeclaration(modifierCount: number): boolean {
return isIndexSignature(modifierCount);
function isIndexMemberDeclaration(): boolean {
return isIndexSignature(/*peekIndex:*/ 0);
}
function parseIndexMemberDeclaration(): IndexMemberDeclarationSyntax {
function parseIndexMemberDeclaration(modifiers: ISyntaxToken[]): IndexMemberDeclarationSyntax {
return new IndexMemberDeclarationSyntax(contextFlags,
parseModifiers(), parseIndexSignature(), eatExplicitOrAutomaticSemicolon(/*allowWithoutNewLine:*/ false));
modifiers,
parseIndexSignature(),
eatExplicitOrAutomaticSemicolon(/*allowWithoutNewLine:*/ false));
}
function isFunctionDeclaration(modifierCount: number): boolean {
@ -3607,8 +3607,9 @@ module TypeScript.Parser {
function tryParsePropertyAssignment(inErrorRecovery: boolean): IPropertyAssignmentSyntax {
// Debug.assert(isPropertyAssignment(/*inErrorRecovery:*/ false));
if (isAccessor(modifierCount(), inErrorRecovery)) {
return parseAccessor();
var modifiers = parseModifiers();
if (isAccessor(inErrorRecovery)) {
return parseAccessor(modifiers);
}
// Note: we don't want to call parsePropertyName here yet as it will convert a keyword
@ -3616,36 +3617,26 @@ module TypeScript.Parser {
// shorthand property assignment.
var _currentToken = currentToken();
if (_currentToken.kind === SyntaxKind.AsyncKeyword) {
// 'async' might start an asynchronous property, or it might just be the name
// of a property.
var token1 = peekToken(1);
if (!token1.hasLeadingNewLine()) {
if (token1.kind === SyntaxKind.AsteriskToken || isPropertyName(/*peekIndex:*/ 1, inErrorRecovery)) {
return parseMemberFunctionDeclaration(
Syntax.list([eatToken(SyntaxKind.AsyncKeyword)]), tryEatToken(SyntaxKind.AsteriskToken), parsePropertyName());
if (modifiers.length === 0) {
if (isIdentifier(_currentToken)) {
var token1 = peekToken(1);
if (token1.kind !== SyntaxKind.ColonToken &&
token1.kind !== SyntaxKind.OpenParenToken &&
token1.kind !== SyntaxKind.LessThanToken) {
// If we don't have one of:
//
// id:
// id(
// id<
//
// then this is a shorthand property assignment. Just return the identifier
// token as is.
return eatIdentifierToken();
}
}
}
if (isIdentifier(_currentToken)) {
var token1 = peekToken(1);
if (token1.kind !== SyntaxKind.ColonToken &&
token1.kind !== SyntaxKind.OpenParenToken &&
token1.kind !== SyntaxKind.LessThanToken) {
// If we don't have one of:
//
// id:
// id(
// id<
//
// then this is a shorthand property assignment. Just return the identifier
// token as is.
return eatIdentifierToken();
}
}
// All the rest of the property assignments start with property names, an asterix.
// They are:
// id: e
@ -3656,12 +3647,12 @@ module TypeScript.Parser {
// *[e]() { }
// async id() { }
// async [e]() { }
if (_currentToken.kind === SyntaxKind.AsteriskToken || isPropertyName(/*peekIndex:*/ 0, inErrorRecovery)) {
if (modifiers.length > 0 || _currentToken.kind === SyntaxKind.AsteriskToken || isPropertyName(/*peekIndex:*/ 0, inErrorRecovery)) {
var asterixToken = tryEatToken(SyntaxKind.AsteriskToken);
var propertyName = parsePropertyName();
if (asterixToken !== undefined || isCallSignature(/*peekIndex:*/ 0)) {
return parseMemberFunctionDeclaration([], asterixToken, propertyName);
if (modifiers.length > 0 || asterixToken !== undefined || isCallSignature(/*peekIndex:*/ 0)) {
return parseMemberFunctionDeclaration(modifiers, asterixToken, propertyName);
}
else {
// PropertyName[?Yield] : AssignmentExpression[In, ?Yield]
@ -3683,7 +3674,9 @@ module TypeScript.Parser {
}
function isPropertyAssignment(inErrorRecovery: boolean): boolean {
return isAccessor(modifierCount(), inErrorRecovery) ||
var _modifierCount = modifierCount();
return _modifierCount > 0 ||
isAccessor(inErrorRecovery) ||
currentToken().kind === SyntaxKind.AsteriskToken ||
isPropertyName(/*peekIndex:*/ 0, inErrorRecovery);
}