Move parser error to the grammar checker.

Conflicts:
	src/services/syntax/SyntaxGenerator.js.map
This commit is contained in:
Cyrus Najmabadi
2014-11-22 13:21:06 -08:00
parent 5fcbeb59ae
commit 80366711d0
6 changed files with 53 additions and 30 deletions

View File

@@ -1289,7 +1289,7 @@ var definitions = [
children: [
{ name: 'expression', type: 'ILeftHandSideExpressionSyntax' },
{ name: 'openBracketToken', isToken: true, excludeFromAST: true },
{ name: 'argumentExpression', type: 'IExpressionSyntax' },
{ name: 'argumentExpression', type: 'IExpressionSyntax', isOptional: true },
{ name: 'closeBracketToken', isToken: true, excludeFromAST: true }
]
},

File diff suppressed because one or more lines are too long

View File

@@ -2650,7 +2650,7 @@ module TypeScript.Parser {
return token0;
}
function tryParseMemberExpressionOrHigher(_currentToken: ISyntaxToken, force: boolean, inObjectCreation: boolean): IMemberExpressionSyntax {
function tryParseMemberExpressionOrHigher(_currentToken: ISyntaxToken, force: boolean): IMemberExpressionSyntax {
// Note: to make our lives simpler, we decompose the the NewExpression productions and
// place ObjectCreationExpression and FunctionExpression into PrimaryExpression.
// like so:
@@ -2703,7 +2703,7 @@ module TypeScript.Parser {
return undefined;
}
return parseMemberExpressionRest(expression, inObjectCreation);
return parseMemberExpressionRest(expression);
}
function parseCallExpressionRest(expression: ILeftHandSideExpressionSyntax): ILeftHandSideExpressionSyntax {
@@ -2730,7 +2730,7 @@ module TypeScript.Parser {
continue;
case SyntaxKind.OpenBracketToken:
expression = parseElementAccessExpression(expression, _currentToken, /*inObjectCreation:*/ false);
expression = parseElementAccessExpression(expression, _currentToken);
continue;
case SyntaxKind.DotToken:
@@ -2747,14 +2747,14 @@ module TypeScript.Parser {
}
}
function parseMemberExpressionRest(expression: IMemberExpressionSyntax, inObjectCreation: boolean): IMemberExpressionSyntax {
function parseMemberExpressionRest(expression: IMemberExpressionSyntax): IMemberExpressionSyntax {
while (true) {
var _currentToken = currentToken();
var currentTokenKind = _currentToken.kind;
switch (currentTokenKind) {
case SyntaxKind.OpenBracketToken:
expression = parseElementAccessExpression(expression, _currentToken, inObjectCreation);
expression = parseElementAccessExpression(expression, _currentToken);
continue;
case SyntaxKind.DotToken:
@@ -2808,7 +2808,7 @@ module TypeScript.Parser {
expression = parseSuperExpression(_currentToken);
}
else {
expression = tryParseMemberExpressionOrHigher(_currentToken, force, /*inObjectCreation:*/ false);
expression = tryParseMemberExpressionOrHigher(_currentToken, force);
if (expression === undefined) {
return undefined;
}
@@ -2941,29 +2941,18 @@ module TypeScript.Parser {
return allowInAnd(force ? parseAssignmentExpressionOrHigher : tryParseAssignmentExpressionOrHigher);
}
function parseElementAccessArgumentExpression(openBracketToken: ISyntaxToken, inObjectCreation: boolean) {
function parseElementAccessArgumentExpression(openBracketToken: ISyntaxToken) {
// MemberExpression[?Yield] [ Expression[In, ?Yield] ]
// It's not uncommon for a user to write: "new Type[]". Check for that common pattern
// and report a better error message.
if (inObjectCreation && currentToken().kind === SyntaxKind.CloseBracketToken) {
var errorStart = start(openBracketToken, source.text);
var errorEnd = fullEnd(currentToken());
var diagnostic = new Diagnostic(fileName, source.text.lineMap(), errorStart, errorEnd - errorStart,
DiagnosticCode.new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead, undefined);
addDiagnostic(diagnostic);
return createEmptyToken(SyntaxKind.IdentifierName);
}
else {
return allowInAnd(parseExpression);
}
// For error recovery purposes. Allow a missing expression here. We'll report the
// appropriate message in the grammar checker.
return currentToken().kind === SyntaxKind.CloseBracketToken ? undefined : allowInAnd(parseExpression);
}
function parseElementAccessExpression(expression: ILeftHandSideExpressionSyntax, openBracketToken: ISyntaxToken, inObjectCreation: boolean): ElementAccessExpressionSyntax {
function parseElementAccessExpression(expression: ILeftHandSideExpressionSyntax, openBracketToken: ISyntaxToken): ElementAccessExpressionSyntax {
// Debug.assert(currentToken().kind === SyntaxKind.OpenBracketToken);
return new ElementAccessExpressionSyntax(parseNodeData, expression, consumeToken(openBracketToken),
parseElementAccessArgumentExpression(openBracketToken, inObjectCreation), eatToken(SyntaxKind.CloseBracketToken));
parseElementAccessArgumentExpression(openBracketToken), eatToken(SyntaxKind.CloseBracketToken));
}
function tryParsePrimaryExpression(_currentToken: ISyntaxToken, force: boolean): IPrimaryExpressionSyntax {
@@ -3069,7 +3058,7 @@ module TypeScript.Parser {
// this decision.
return new ObjectCreationExpressionSyntax(parseNodeData,
consumeToken(newKeyword), tryParseMemberExpressionOrHigher(currentToken(), /*force:*/ true, /*inObjectCreation:*/ true), tryParseArgumentList());
consumeToken(newKeyword), tryParseMemberExpressionOrHigher(currentToken(), /*force:*/ true), tryParseArgumentList());
}
function parseTemplateExpression(startToken: ISyntaxToken): IPrimaryExpressionSyntax {

View File

@@ -435,7 +435,7 @@ var definitions:ITypeDefinition[] = [
children: [
<any>{ name: 'expression', type: 'ILeftHandSideExpressionSyntax' },
<any>{ name: 'openBracketToken', isToken: true, excludeFromAST: true },
<any>{ name: 'argumentExpression', type: 'IExpressionSyntax' },
<any>{ name: 'argumentExpression', type: 'IExpressionSyntax', isOptional: true },
<any>{ name: 'closeBracketToken', isToken: true, excludeFromAST: true }
]
},

View File

@@ -1347,7 +1347,7 @@ module TypeScript {
this.closeBracketToken = closeBracketToken,
expression.parent = this,
openBracketToken.parent = this,
argumentExpression.parent = this,
argumentExpression && (argumentExpression.parent = this),
closeBracketToken.parent = this;
};
ElementAccessExpressionSyntax.prototype.kind = SyntaxKind.ElementAccessExpression;

View File

@@ -138,8 +138,12 @@ module TypeScript {
}
private pushDiagnostic(element: ISyntaxElement, diagnosticKey: string, args?: any[]): void {
this.pushDiagnosticAt(start(element, this.text), width(element), diagnosticKey, args);
}
private pushDiagnosticAt(start: number, length: number, diagnosticKey: string, args?: any[]): void {
this.diagnostics.push(new Diagnostic(
this.syntaxTree.fileName(), this.syntaxTree.lineMap(), start(element, this.text), width(element), diagnosticKey, args));
this.syntaxTree.fileName(), this.syntaxTree.lineMap(), start, length, diagnosticKey, args));
}
public visitCatchClause(node: CatchClauseSyntax): void {
@@ -715,6 +719,33 @@ module TypeScript {
super.visitSetAccessor(node);
}
public visitElementAccessExpression(node: ElementAccessExpressionSyntax): void {
if (this.checkForMissingArgumentExpression(node)) {
return;
}
super.visitElementAccessExpression(node);
}
public checkForMissingArgumentExpression(node: ElementAccessExpressionSyntax): boolean {
if (node.argumentExpression === undefined) {
if (node.parent.kind === SyntaxKind.ObjectCreationExpression && (<ObjectCreationExpressionSyntax>node.parent).expression === node) {
// Provide a specialized message for the very common case where someone writes:
// new Foo[]
var start = TypeScript.start(node.openBracketToken);
var end = TypeScript.fullEnd(node.closeBracketToken);
this.pushDiagnosticAt(start, end - start, DiagnosticCode.new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead);
}
else {
this.pushDiagnostic(node.closeBracketToken, DiagnosticCode.Expression_expected);
}
return true;
}
return false;
}
public visitEnumDeclaration(node: EnumDeclarationSyntax): void {
if (this.checkForDisallowedDeclareModifier(node.modifiers) ||
this.checkForRequiredDeclareModifier(node, node.identifier, node.modifiers) ||
@@ -1274,8 +1305,7 @@ module TypeScript {
public checkForMissingThrowStatementExpression(node: ThrowStatementSyntax): boolean {
if (node.expression === undefined) {
this.diagnostics.push(new Diagnostic(
this.syntaxTree.fileName(), this.syntaxTree.lineMap(), fullEnd(node.throwKeyword), 0, DiagnosticCode.Expression_expected));
this.pushDiagnosticAt(fullEnd(node.throwKeyword), 0, DiagnosticCode.Expression_expected);
return true;
}