mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-12-13 04:57:55 -06:00
Add support for parsing generator functions and yield expressions.
This commit is contained in:
parent
726de4b402
commit
7e1a62a8c2
@ -125,6 +125,7 @@ module ts {
|
||||
Unterminated_template_literal: { code: 1160, category: DiagnosticCategory.Error, key: "Unterminated template literal." },
|
||||
Unterminated_regular_expression_literal: { code: 1161, category: DiagnosticCategory.Error, key: "Unterminated regular expression literal." },
|
||||
An_object_member_cannot_be_declared_optional: { code: 1162, category: DiagnosticCategory.Error, key: "An object member cannot be declared optional." },
|
||||
yield_expression_must_be_contained_within_a_generator_declaration: { code: 1163, category: DiagnosticCategory.Error, key: "'yield' expression must be contained_within a generator declaration." },
|
||||
Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
|
||||
Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." },
|
||||
Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." },
|
||||
|
||||
@ -491,6 +491,10 @@
|
||||
"category": "Error",
|
||||
"code": 1162
|
||||
},
|
||||
"'yield' expression must be contained_within a generator declaration.": {
|
||||
"category": "Error",
|
||||
"code": 1163
|
||||
},
|
||||
|
||||
"Duplicate identifier '{0}'.": {
|
||||
"category": "Error",
|
||||
|
||||
@ -977,30 +977,6 @@ module ts {
|
||||
return func();
|
||||
}
|
||||
|
||||
function enterGeneratorParameterContextAnd<T>(func: () => T): T {
|
||||
if (generatorParameterContext) {
|
||||
// no need to do anything special if we're already in the [GeneratorParameter] context
|
||||
return func();
|
||||
}
|
||||
|
||||
setGeneratorParameterContext(true);
|
||||
var result = func();
|
||||
setGeneratorParameterContext(false);
|
||||
return result;
|
||||
}
|
||||
|
||||
function exitGeneratorParameterContextAnd<T>(func: () => T): T {
|
||||
if (generatorParameterContext) {
|
||||
setGeneratorParameterContext(false);
|
||||
var result = func();
|
||||
setGeneratorParameterContext(true);
|
||||
return result;
|
||||
}
|
||||
|
||||
// no need to do anything special if we're not in the [GeneratorParameter] context
|
||||
return func();
|
||||
}
|
||||
|
||||
function getLineStarts(): number[] {
|
||||
return lineStarts || (lineStarts = computeLineStarts(sourceText));
|
||||
}
|
||||
@ -1126,7 +1102,17 @@ module ts {
|
||||
}
|
||||
|
||||
function isIdentifier(): boolean {
|
||||
return token === SyntaxKind.Identifier || (strictModeContext ? token > SyntaxKind.LastFutureReservedWord : token > SyntaxKind.LastReservedWord);
|
||||
if (token === SyntaxKind.Identifier) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we have a 'yield' keyword, and we're in the [yield] context, then 'yield' is
|
||||
// considered a keyword and is not an identifier.
|
||||
if (token === SyntaxKind.YieldKeyword && yieldContext) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return strictModeContext ? token > SyntaxKind.LastFutureReservedWord : token > SyntaxKind.LastReservedWord;
|
||||
}
|
||||
|
||||
function parseExpected(t: SyntaxKind): boolean {
|
||||
@ -1247,7 +1233,7 @@ module ts {
|
||||
function parseAnyContextualModifier(): boolean {
|
||||
return isModifier(token) && tryParse(() => {
|
||||
nextToken();
|
||||
return token === SyntaxKind.OpenBracketToken || isPropertyName();
|
||||
return token === SyntaxKind.OpenBracketToken || token === SyntaxKind.AsteriskToken || isPropertyName();
|
||||
});
|
||||
}
|
||||
|
||||
@ -1268,7 +1254,7 @@ module ts {
|
||||
return lookAhead(isClassMemberStart);
|
||||
case ParsingContext.EnumMembers:
|
||||
case ParsingContext.ObjectLiteralMembers:
|
||||
return isPropertyName();
|
||||
return token === SyntaxKind.AsteriskToken || isPropertyName();
|
||||
case ParsingContext.BaseTypeReferences:
|
||||
return isIdentifier() && ((token !== SyntaxKind.ExtendsKeyword && token !== SyntaxKind.ImplementsKeyword) || !lookAhead(() => (nextToken(), isIdentifier())));
|
||||
case ParsingContext.VariableDeclarations:
|
||||
@ -1460,12 +1446,13 @@ module ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseBracketedList<T extends Node>(kind: ParsingContext, parseElement: () => T, startToken: SyntaxKind, endToken: SyntaxKind): NodeArray<T> {
|
||||
if (parseExpected(startToken)) {
|
||||
function parseBracketedList<T extends Node>(kind: ParsingContext, parseElement: () => T, open: SyntaxKind, close: SyntaxKind): NodeArray<T> {
|
||||
if (parseExpected(open)) {
|
||||
var result = parseDelimitedList(kind, parseElement);
|
||||
parseExpected(endToken);
|
||||
parseExpected(close);
|
||||
return result;
|
||||
}
|
||||
|
||||
return createMissingList<T>();
|
||||
}
|
||||
|
||||
@ -1637,7 +1624,15 @@ module ts {
|
||||
if (parseOptional(SyntaxKind.DotDotDotToken)) {
|
||||
node.flags |= NodeFlags.Rest;
|
||||
}
|
||||
node.name = parseIdentifier();
|
||||
|
||||
// SingleNameBinding[Yield,GeneratorParameter] : See 13.2.3
|
||||
// [+GeneratorParameter]BindingIdentifier[Yield]Initializer[In]opt
|
||||
// [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt
|
||||
|
||||
node.name = generatorParameterContext
|
||||
? enterYieldContextAnd(parseIdentifier)
|
||||
: parseIdentifier();
|
||||
|
||||
if (node.name.kind === SyntaxKind.Missing && node.flags === 0 && isModifier(token)) {
|
||||
// in cases like
|
||||
// 'use strict'
|
||||
@ -1654,7 +1649,9 @@ module ts {
|
||||
node.flags |= NodeFlags.QuestionMark;
|
||||
}
|
||||
node.type = parseParameterType();
|
||||
node.initializer = parseInitializer(/*inParameter*/ true);
|
||||
node.initializer = generatorParameterContext
|
||||
? exitYieldContextAnd(parseParameterInitializer)
|
||||
: parseParameterInitializer();
|
||||
|
||||
// Do not check for initializers in an ambient context for parameters. This is not
|
||||
// a grammar error because the grammar allows arbitrary call signatures in
|
||||
@ -1667,18 +1664,28 @@ module ts {
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseSignature(kind: SyntaxKind, returnToken: SyntaxKind, returnTokenRequired: boolean): ParsedSignature {
|
||||
function parseParameterInitializer() {
|
||||
return parseInitializer(/*inParameter*/ true);
|
||||
}
|
||||
|
||||
function parseSignature(kind: SyntaxKind, returnToken: SyntaxKind, returnTokenRequired: boolean, isGenerator: boolean): ParsedSignature {
|
||||
var signature = <ParsedSignature>{};
|
||||
fillSignature(kind, returnToken, returnTokenRequired, signature);
|
||||
fillSignature(kind, returnToken, returnTokenRequired, isGenerator, signature);
|
||||
return signature;
|
||||
}
|
||||
|
||||
function fillSignature(kind: SyntaxKind, returnToken: SyntaxKind, returnTokenRequired: boolean, signature: ParsedSignature): void {
|
||||
function fillSignature(
|
||||
kind: SyntaxKind,
|
||||
returnToken: SyntaxKind,
|
||||
returnTokenRequired: boolean,
|
||||
isGenerator: boolean,
|
||||
signature: ParsedSignature): void {
|
||||
|
||||
if (kind === SyntaxKind.ConstructSignature) {
|
||||
parseExpected(SyntaxKind.NewKeyword);
|
||||
}
|
||||
signature.typeParameters = parseTypeParameters();
|
||||
signature.parameters = parseParameterList(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken);
|
||||
signature.parameters = parseParameterList(/*yieldContext:*/ isGenerator, /*generatorParameterContext:*/ isGenerator);
|
||||
|
||||
if (returnTokenRequired) {
|
||||
parseExpected(returnToken);
|
||||
@ -1691,13 +1698,43 @@ module ts {
|
||||
|
||||
// Because we use this for index signatures as well, we sometimes use
|
||||
// parentheses, and sometimes use brackets.
|
||||
function parseParameterList(startDelimiter: SyntaxKind, endDelimiter: SyntaxKind) {
|
||||
return parseBracketedList(ParsingContext.Parameters, parseParameter, startDelimiter, endDelimiter);
|
||||
function parseParameterList(_yieldContext: boolean, _generatorParameterContext: boolean) {
|
||||
// FormalParameters[Yield,GeneratorParameter] :
|
||||
// ...
|
||||
//
|
||||
// FormalParameter[Yield,GeneratorParameter] :
|
||||
// BindingElement[?Yield, ?GeneratorParameter]
|
||||
//
|
||||
// BindingElement[Yield, GeneratorParameter ] : See 13.2.3
|
||||
// SingleNameBinding[?Yield, ?GeneratorParameter]
|
||||
// [+GeneratorParameter]BindingPattern[?Yield, GeneratorParameter]Initializer[In]opt
|
||||
// [~GeneratorParameter]BindingPattern[?Yield]Initializer[In, ?Yield]opt
|
||||
//
|
||||
// SingleNameBinding[Yield, GeneratorParameter] : See 13.2.3
|
||||
// [+GeneratorParameter]BindingIdentifier[Yield]Initializer[In]opt
|
||||
// [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt
|
||||
if (parseExpected(SyntaxKind.OpenParenToken)) {
|
||||
var savedYieldContext = yieldContext;
|
||||
var savedGeneratorParameterContext = generatorParameterContext;
|
||||
|
||||
setYieldContext(_yieldContext);
|
||||
setGeneratorParameterContext(_generatorParameterContext);
|
||||
|
||||
var result = parseDelimitedList(ParsingContext.Parameters, parseParameter);
|
||||
parseExpected(SyntaxKind.CloseParenToken);
|
||||
|
||||
setYieldContext(savedYieldContext);
|
||||
setGeneratorParameterContext(savedGeneratorParameterContext);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return createMissingList<ParameterDeclaration>();
|
||||
}
|
||||
|
||||
function parseSignatureMember(kind: SyntaxKind, returnToken: SyntaxKind): SignatureDeclaration {
|
||||
var node = <SignatureDeclaration>createNode(kind);
|
||||
fillSignature(kind, returnToken, /* returnTokenRequired */ false, node);
|
||||
fillSignature(kind, returnToken, /* returnTokenRequired */ false, /*isGenerator:*/ false, node);
|
||||
parseSemicolon();
|
||||
return finishNode(node);
|
||||
}
|
||||
@ -1705,7 +1742,7 @@ module ts {
|
||||
function parseIndexSignatureMember(fullStart: number, modifiers: ModifiersArray): SignatureDeclaration {
|
||||
var node = <SignatureDeclaration>createNode(SyntaxKind.IndexSignature, fullStart);
|
||||
setModifiers(node, modifiers);
|
||||
node.parameters = parseParameterList(SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
|
||||
node.parameters = parseBracketedList(ParsingContext.Parameters, parseParameter, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
|
||||
node.type = parseTypeAnnotation();
|
||||
parseSemicolon();
|
||||
return finishNode(node)
|
||||
@ -1723,7 +1760,11 @@ module ts {
|
||||
var method = <MethodDeclaration>createNode(SyntaxKind.Method, fullStart);
|
||||
method.name = name;
|
||||
method.flags = flags;
|
||||
fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, method);
|
||||
|
||||
// Method signatues don't exist in expression contexts. So they have neither
|
||||
// [Yield] nor [GeneratorParameter]
|
||||
fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*isGenerator:*/ false, method);
|
||||
|
||||
parseSemicolon();
|
||||
return finishNode(method);
|
||||
}
|
||||
@ -1806,7 +1847,7 @@ module ts {
|
||||
function parseFunctionType(typeKind: SyntaxKind): SignatureDeclaration {
|
||||
var node = <SignatureDeclaration>createNode(typeKind);
|
||||
fillSignature(typeKind === SyntaxKind.FunctionType ? SyntaxKind.CallSignature : SyntaxKind.ConstructSignature,
|
||||
SyntaxKind.EqualsGreaterThanToken, /* returnTokenRequired */ true, node);
|
||||
SyntaxKind.EqualsGreaterThanToken, /* returnTokenRequired */ true, /*isGenerator:*/ false, node);
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
@ -1926,6 +1967,23 @@ module ts {
|
||||
}
|
||||
|
||||
function parseType(): TypeNode {
|
||||
// The rules about 'yield' only apply to actual code/expression contexts. They don't
|
||||
// apply to 'type' contexts. So we disable these parameters here before moving on.
|
||||
var savedYieldContext = yieldContext;
|
||||
var savedGeneratorParameterContext = generatorParameterContext;
|
||||
|
||||
setYieldContext(false);
|
||||
setGeneratorParameterContext(false);
|
||||
|
||||
var result = parseTypeWorker();
|
||||
|
||||
setYieldContext(savedYieldContext);
|
||||
setGeneratorParameterContext(savedGeneratorParameterContext);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseTypeWorker(): TypeNode {
|
||||
if (isStartOfFunctionType()) {
|
||||
return parseFunctionType(SyntaxKind.FunctionType);
|
||||
}
|
||||
@ -1970,6 +2028,10 @@ module ts {
|
||||
case SyntaxKind.MinusMinusToken:
|
||||
case SyntaxKind.LessThanToken:
|
||||
case SyntaxKind.Identifier:
|
||||
case SyntaxKind.YieldKeyword:
|
||||
// Yield always starts an expression. Either it is an identifier (in which case
|
||||
// it is definitely an expression). Or it's a keyword (either because we're in
|
||||
// a generator, or in strict mode (or both)) and it started a yield expression.
|
||||
return true;
|
||||
default:
|
||||
return isIdentifier();
|
||||
@ -2018,18 +2080,22 @@ module ts {
|
||||
}
|
||||
|
||||
function parseAssignmentExpression(): Expression {
|
||||
// Augmented by TypeScript:
|
||||
//
|
||||
// AssignmentExpression[in]:
|
||||
// 1) ConditionalExpression[in]
|
||||
// 2) LeftHandSideExpression = AssignmentExpression[in]
|
||||
// 3) LeftHandSideExpression AssignmentOperator AssignmentExpression[in]
|
||||
// 4) ArrowFunctionExpression <-- added by TypeScript
|
||||
// AssignmentExpression[in,yield]:
|
||||
// 1) ConditionalExpression[?in,?yield]
|
||||
// 2) LeftHandSideExpression = AssignmentExpression[?in,?yield]
|
||||
// 3) LeftHandSideExpression AssignmentOperator AssignmentExpression[?in,?yield]
|
||||
// 4) ArrowFunctionExpression[?in,?yield]
|
||||
// 5) [+Yield] YieldExpression[?In]
|
||||
//
|
||||
// Note: for ease of implementation we treat productions '2' and '3' as the same thing.
|
||||
// (i.e. they're both BinaryExpressions with an assignment operator in it).
|
||||
|
||||
// First, check if we have an arrow function (production '4') that starts with a parenthesized
|
||||
// First, do the simple check if we have a YieldExpression (production '5').
|
||||
if (isYieldExpression()) {
|
||||
return parseYieldExpression();
|
||||
}
|
||||
|
||||
// Then, check if we have an arrow function (production '4') that starts with a parenthesized
|
||||
// parameter list. If we do, we must *not* recurse for productions 1, 2 or 3. An ArrowFunction is
|
||||
// not a LeftHandSideExpression, nor does it start a ConditionalExpression. So we are done
|
||||
// with AssignmentExpression if we see one.
|
||||
@ -2062,6 +2128,66 @@ module ts {
|
||||
return expr;
|
||||
}
|
||||
|
||||
function isYieldExpression(): boolean {
|
||||
if (token === SyntaxKind.YieldKeyword) {
|
||||
// If we have a 'yield' keyword, and htis is a context where yield expressions are
|
||||
// allowed, then definitely parse out a yield expression.
|
||||
if (yieldContext) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strictModeContext) {
|
||||
// If we're in strict mode, then 'yield' is a keyword, could only ever start
|
||||
// a yield expression.
|
||||
return true;
|
||||
}
|
||||
|
||||
// We're in a context where 'yield expr' is not allowed. However, if we can
|
||||
// definitely tell that the user was trying to parse a 'yield expr' and not
|
||||
// just a normal expr that start with a 'yield' identifier, then parse out
|
||||
// a 'yield expr'. We can then report an error later that they are only
|
||||
// allowed in generator expressions.
|
||||
//
|
||||
// for example, if we see 'yield(foo)', then we'll have to treat that as an
|
||||
// invocation expression of something called 'yield'. However, if we have
|
||||
// 'yield foo' then that is not legal as a normal expression, so we can
|
||||
// definitely recognize this as a yield expression.
|
||||
//
|
||||
// for now we just check if the next token is an identifier. More heuristics
|
||||
// can be added here later as necessary. We just need to make sure that we
|
||||
// don't accidently consume something legal.
|
||||
return lookAhead(() => {
|
||||
nextToken();
|
||||
return !scanner.hasPrecedingLineBreak() && isIdentifier();
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function parseYieldExpression(): YieldExpression {
|
||||
var node = <YieldExpression>createNode(SyntaxKind.YieldExpression);
|
||||
|
||||
// YieldExpression[In] :
|
||||
// yield
|
||||
// yield [no LineTerminator here] [Lexical goal InputElementRegExp]AssignmentExpression[?In, Yield]
|
||||
// yield [no LineTerminator here] * [Lexical goal InputElementRegExp]AssignmentExpression[?In, Yield]
|
||||
nextToken();
|
||||
|
||||
if (!scanner.hasPrecedingLineBreak() &&
|
||||
(token === SyntaxKind.AsteriskToken || isStartOfExpression())) {
|
||||
parseOptional(SyntaxKind.AsteriskToken);
|
||||
|
||||
node.expression = parseAssignmentExpression();
|
||||
return finishNode(node);
|
||||
}
|
||||
else {
|
||||
// if the next token is not on the same line as yield. or we don't have an '*' or
|
||||
// the start of an expressin, then this is just a simple "yield" expression.
|
||||
return finishNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
function parseSimpleArrowFunctionExpression(identifier: Identifier): Expression {
|
||||
Debug.assert(token === SyntaxKind.EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>");
|
||||
parseExpected(SyntaxKind.EqualsGreaterThanToken);
|
||||
@ -2091,7 +2217,8 @@ module ts {
|
||||
var pos = getNodePos();
|
||||
|
||||
if (triState === Tristate.True) {
|
||||
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false);
|
||||
// Arrow function are never generators.
|
||||
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*isGenerator:*/ false);
|
||||
|
||||
// If we have an arrow, then try to parse the body.
|
||||
// Even if not, try to parse if we have an opening brace, just in case we're in an error state.
|
||||
@ -2194,7 +2321,8 @@ module ts {
|
||||
|
||||
function tryParseSignatureIfArrowOrBraceFollows(): ParsedSignature {
|
||||
return tryParse(() => {
|
||||
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false);
|
||||
// Arrow functions are never generators.
|
||||
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*isGenerator:*/ false);
|
||||
|
||||
// Parsing a signature isn't enough.
|
||||
// Parenthesized arrow signatures often look like other valid expressions.
|
||||
@ -2216,7 +2344,7 @@ module ts {
|
||||
var body: Node;
|
||||
|
||||
if (token === SyntaxKind.OpenBraceToken) {
|
||||
body = parseFunctionBlock(/* ignoreMissingOpenBrace */ false);
|
||||
body = parseFunctionBlock(/*allowYield:*/ false, /* ignoreMissingOpenBrace */ false);
|
||||
}
|
||||
else if (isStatement(/* inErrorRecovery */ true) && !isStartOfExpressionStatement() && token !== SyntaxKind.FunctionKeyword) {
|
||||
// Check if we got a plain statement (i.e. no expression-statements, no functions expressions/declarations)
|
||||
@ -2233,7 +2361,7 @@ module ts {
|
||||
// up preemptively closing the containing construct.
|
||||
//
|
||||
// Note: even when 'ignoreMissingOpenBrace' is passed as true, parseBody will still error.
|
||||
body = parseFunctionBlock(/* ignoreMissingOpenBrace */ true);
|
||||
body = parseFunctionBlock(/*allowYield:*/ false, /* ignoreMissingOpenBrace */ true);
|
||||
}
|
||||
else {
|
||||
body = parseAssignmentExpression();
|
||||
@ -2575,15 +2703,17 @@ module ts {
|
||||
|
||||
function parsePropertyAssignment(): Declaration {
|
||||
var nodePos = scanner.getStartPos();
|
||||
var isGenerator = parseOptional(SyntaxKind.AsteriskToken);
|
||||
var tokenIsIdentifier = isIdentifier();
|
||||
var nameToken = token;
|
||||
var propertyName = parsePropertyName();
|
||||
var node: Declaration;
|
||||
if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) {
|
||||
if (isGenerator || token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) {
|
||||
node = <PropertyDeclaration>createNode(SyntaxKind.PropertyAssignment, nodePos);
|
||||
node.name = propertyName;
|
||||
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false);
|
||||
var body = parseFunctionBlock(/* ignoreMissingOpenBrace */ false);
|
||||
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*isGenerator:*/ isGenerator);
|
||||
|
||||
var body = parseFunctionBlock(isGenerator, /* ignoreMissingOpenBrace */ false);
|
||||
// do not propagate property name as name for function expression
|
||||
// for scenarios like
|
||||
// var x = 1;
|
||||
@ -2640,14 +2770,25 @@ module ts {
|
||||
}
|
||||
|
||||
function parseFunctionExpression(): FunctionExpression {
|
||||
// GeneratorExpression :
|
||||
// function * BindingIdentifier[Yield]opt (FormalParameters[Yield, GeneratorParameter]) { GeneratorBody[Yield] }
|
||||
// FunctionExpression:
|
||||
// function BindingIdentifieropt(FormalParameters) { FunctionBody }
|
||||
|
||||
var pos = getNodePos();
|
||||
parseExpected(SyntaxKind.FunctionKeyword);
|
||||
var name = isIdentifier() ? parseIdentifier() : undefined;
|
||||
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false);
|
||||
var body = parseFunctionBlock(/* ignoreMissingOpenBrace */ false);
|
||||
var isGenerator = parseOptional(SyntaxKind.AsteriskToken);
|
||||
var name = isGenerator ? enterYieldContextAnd(parseOptionalIdentifier) : parseOptionalIdentifier();
|
||||
var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*isGenerator:*/ isGenerator);
|
||||
|
||||
var body = parseFunctionBlock(/*allowYield:*/ isGenerator, /* ignoreMissingOpenBrace */ false);
|
||||
return makeFunctionExpression(SyntaxKind.FunctionExpression, pos, name, sig, body);
|
||||
}
|
||||
|
||||
function parseOptionalIdentifier() {
|
||||
return isIdentifier() ? parseIdentifier() : undefined;
|
||||
}
|
||||
|
||||
function makeFunctionExpression(kind: SyntaxKind, pos: number, name: Identifier, sig: ParsedSignature, body: Node): FunctionExpression {
|
||||
var node = <FunctionExpression>createNode(kind, pos);
|
||||
node.name = name;
|
||||
@ -2682,10 +2823,15 @@ module ts {
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseFunctionBlock(ignoreMissingOpenBrace: boolean): Block {
|
||||
function parseFunctionBlock(allowYield: boolean, ignoreMissingOpenBrace: boolean): Block {
|
||||
var savedYieldContext = yieldContext;
|
||||
setYieldContext(allowYield);
|
||||
|
||||
var block = parseBlock(ignoreMissingOpenBrace, /*checkForStrictMode*/ true);
|
||||
block.kind = SyntaxKind.FunctionBlock;
|
||||
|
||||
setYieldContext(savedYieldContext);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
@ -3050,9 +3196,9 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function parseFunctionBlockOrSemicolon(): Block {
|
||||
function parseFunctionBlockOrSemicolon(isGenerator: boolean): Block {
|
||||
if (token === SyntaxKind.OpenBraceToken) {
|
||||
return parseFunctionBlock(/* ignoreMissingOpenBrace */ false);
|
||||
return parseFunctionBlock(isGenerator, /* ignoreMissingOpenBrace */ false);
|
||||
}
|
||||
|
||||
if (canParseSemicolon()) {
|
||||
@ -3111,9 +3257,10 @@ module ts {
|
||||
var node = <FunctionLikeDeclaration>createNode(SyntaxKind.FunctionDeclaration, fullStart);
|
||||
setModifiers(node, modifiers);
|
||||
parseExpected(SyntaxKind.FunctionKeyword);
|
||||
var isGenerator = parseOptional(SyntaxKind.AsteriskToken);
|
||||
node.name = parseIdentifier();
|
||||
fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, node);
|
||||
node.body = parseFunctionBlockOrSemicolon();
|
||||
fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*isGenerator:*/ isGenerator, node);
|
||||
node.body = parseFunctionBlockOrSemicolon(isGenerator);
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
@ -3121,12 +3268,13 @@ module ts {
|
||||
var node = <ConstructorDeclaration>createNode(SyntaxKind.Constructor, pos);
|
||||
setModifiers(node, modifiers);
|
||||
parseExpected(SyntaxKind.ConstructorKeyword);
|
||||
fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, node);
|
||||
node.body = parseFunctionBlockOrSemicolon();
|
||||
fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*isGenerator:*/ false, node);
|
||||
node.body = parseFunctionBlockOrSemicolon(/*isGenerator:*/ false);
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parsePropertyMemberDeclaration(fullStart: number, modifiers: ModifiersArray): Declaration {
|
||||
var isGenerator = parseOptional(SyntaxKind.AsteriskToken);
|
||||
var name = parsePropertyName();
|
||||
var flags = modifiers ? modifiers.flags : 0;
|
||||
if (parseOptional(SyntaxKind.QuestionToken)) {
|
||||
@ -3135,15 +3283,15 @@ module ts {
|
||||
flags |= NodeFlags.QuestionMark;
|
||||
}
|
||||
|
||||
if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) {
|
||||
if (isGenerator || token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) {
|
||||
var method = <MethodDeclaration>createNode(SyntaxKind.Method, fullStart);
|
||||
setModifiers(method, modifiers);
|
||||
if (flags) {
|
||||
method.flags = flags;
|
||||
}
|
||||
method.name = name;
|
||||
fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, method);
|
||||
method.body = parseFunctionBlockOrSemicolon();
|
||||
fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*isGenerator:*/ isGenerator, method);
|
||||
method.body = parseFunctionBlockOrSemicolon(isGenerator);
|
||||
return finishNode(method);
|
||||
}
|
||||
else {
|
||||
@ -3164,8 +3312,8 @@ module ts {
|
||||
var node = <MethodDeclaration>createNode(kind, fullStart);
|
||||
setModifiers(node, modifiers);
|
||||
node.name = parsePropertyName();
|
||||
fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, node);
|
||||
node.body = parseFunctionBlockOrSemicolon();
|
||||
fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*isGenerator:*/ false, node);
|
||||
node.body = parseFunctionBlockOrSemicolon(/*isGenerator:*/ false);
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
@ -3178,6 +3326,10 @@ module ts {
|
||||
nextToken();
|
||||
}
|
||||
|
||||
if (token === SyntaxKind.AsteriskToken) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to get the first property-like token following all modifiers.
|
||||
// This can either be an identifier or the 'get' or 'set' keywords.
|
||||
if (isPropertyName()) {
|
||||
@ -3254,7 +3406,7 @@ module ts {
|
||||
if (token === SyntaxKind.ConstructorKeyword) {
|
||||
return parseConstructorDeclaration(fullStart, modifiers);
|
||||
}
|
||||
if (token >= SyntaxKind.Identifier || token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral) {
|
||||
if (token >= SyntaxKind.Identifier || token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral || token === SyntaxKind.AsteriskToken) {
|
||||
return parsePropertyMemberDeclaration(fullStart, modifiers);
|
||||
}
|
||||
if (token === SyntaxKind.OpenBracketToken) {
|
||||
@ -3273,12 +3425,26 @@ module ts {
|
||||
node.typeParameters = parseTypeParameters();
|
||||
|
||||
// TODO(jfreeman): Parse arbitrary sequence of heritage clauses and error for order and duplicates
|
||||
node.baseType = parseOptional(SyntaxKind.ExtendsKeyword) ? parseTypeReference() : undefined;
|
||||
|
||||
// ClassTail[Yield,GeneratorParameter] : See 14.5
|
||||
// [~GeneratorParameter]ClassHeritage[?Yield]opt { ClassBody[?Yield]opt }
|
||||
// [+GeneratorParameter] ClassHeritageopt { ClassBodyopt }
|
||||
|
||||
node.baseType = generatorParameterContext
|
||||
? exitYieldContextAnd(parseClassBaseType)
|
||||
: parseClassBaseType();
|
||||
|
||||
if (parseOptional(SyntaxKind.ImplementsKeyword)) {
|
||||
node.implementedTypes = parseDelimitedList(ParsingContext.BaseTypeReferences, parseTypeReference);
|
||||
}
|
||||
if (parseExpected(SyntaxKind.OpenBraceToken)) {
|
||||
node.members = parseList(ParsingContext.ClassMembers, /*checkForStrictMode*/ false, parseClassMemberDeclaration);
|
||||
// ClassTail[Yield,GeneratorParameter] : See 14.5
|
||||
// [~GeneratorParameter]ClassHeritage[?Yield]opt { ClassBody[?Yield]opt }
|
||||
// [+GeneratorParameter] ClassHeritageopt { ClassBodyopt }
|
||||
|
||||
node.members = generatorParameterContext
|
||||
? exitYieldContextAnd(parseClassMembers)
|
||||
: parseClassMembers();
|
||||
parseExpected(SyntaxKind.CloseBraceToken);
|
||||
}
|
||||
else {
|
||||
@ -3287,6 +3453,14 @@ module ts {
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseClassMembers() {
|
||||
return parseList(ParsingContext.ClassMembers, /*checkForStrictMode*/ false, parseClassMemberDeclaration);
|
||||
}
|
||||
|
||||
function parseClassBaseType(): TypeReferenceNode {
|
||||
return parseOptional(SyntaxKind.ExtendsKeyword) ? parseTypeReference() : undefined;
|
||||
}
|
||||
|
||||
function parseInterfaceDeclaration(fullStart: number, modifiers: ModifiersArray): InterfaceDeclaration {
|
||||
var node = <InterfaceDeclaration>createNode(SyntaxKind.InterfaceDeclaration, fullStart);
|
||||
setModifiers(node, modifiers);
|
||||
@ -3725,7 +3899,6 @@ module ts {
|
||||
return checkCallOrNewExpression(<NewExpression>node);
|
||||
|
||||
case SyntaxKind.EnumDeclaration: return checkEnumDeclaration(<EnumDeclaration>node);
|
||||
case SyntaxKind.Parameter: return checkParameter(<ParameterDeclaration>node);
|
||||
case SyntaxKind.BinaryExpression: return checkBinaryExpression(<BinaryExpression>node);
|
||||
case SyntaxKind.CatchBlock: return checkCatchBlock(<CatchBlock>node);
|
||||
case SyntaxKind.ClassDeclaration: return checkClassDeclaration(<ClassDeclaration>node);
|
||||
@ -3744,6 +3917,7 @@ module ts {
|
||||
case SyntaxKind.ModuleDeclaration: return checkModuleDeclaration(<ModuleDeclaration>node);
|
||||
case SyntaxKind.ObjectLiteral: return checkObjectLiteral(<ObjectLiteral>node);
|
||||
case SyntaxKind.NumericLiteral: return checkNumericLiteral(<LiteralExpression>node);
|
||||
case SyntaxKind.Parameter: return checkParameter(<ParameterDeclaration>node);
|
||||
case SyntaxKind.PostfixOperator: return checkPostfixOperator(<UnaryExpression>node);
|
||||
case SyntaxKind.PrefixOperator: return checkPrefixOperator(<UnaryExpression>node);
|
||||
case SyntaxKind.Property: return checkProperty(<PropertyDeclaration>node);
|
||||
@ -3760,6 +3934,7 @@ module ts {
|
||||
case SyntaxKind.VariableDeclaration: return checkVariableDeclaration(<VariableDeclaration>node);
|
||||
case SyntaxKind.VariableStatement: return checkVariableStatement(<VariableStatement>node);
|
||||
case SyntaxKind.WithStatement: return checkWithStatement(<WithStatement>node);
|
||||
case SyntaxKind.YieldExpression: return checkYieldExpression(<YieldExpression>node);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4740,6 +4915,12 @@ module ts {
|
||||
return grammarErrorOnFirstToken(node, Diagnostics.with_statements_are_not_allowed_in_strict_mode);
|
||||
}
|
||||
}
|
||||
|
||||
function checkYieldExpression(node: YieldExpression): boolean {
|
||||
if (!(node.parserContextFlags & ParserContextFlags.ParsedInYieldContext)) {
|
||||
return grammarErrorOnFirstToken(node, Diagnostics.yield_expression_must_be_contained_within_a_generator_declaration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function createProgram(rootNames: string[], options: CompilerOptions, host: CompilerHost): Program {
|
||||
|
||||
@ -183,6 +183,7 @@ module ts {
|
||||
ConditionalExpression,
|
||||
TemplateExpression,
|
||||
TemplateSpan,
|
||||
YieldExpression,
|
||||
OmittedExpression,
|
||||
// Element
|
||||
Block,
|
||||
@ -291,7 +292,7 @@ module ts {
|
||||
flags: NodeFlags;
|
||||
// Specific context the parser was in when this node was created. Normally undefined.
|
||||
// Only set when the parser was in some interesting context (like async/yield).
|
||||
parserContextFlags?: NodeFlags;
|
||||
parserContextFlags?: ParserContextFlags;
|
||||
id?: number; // Unique id (used to look up NodeLinks)
|
||||
parent?: Node; // Parent node (initialized by binding)
|
||||
symbol?: Symbol; // Symbol declared by node (initialized by binding)
|
||||
@ -438,6 +439,10 @@ module ts {
|
||||
operator: SyntaxKind;
|
||||
operand: Expression;
|
||||
}
|
||||
|
||||
export interface YieldExpression extends Expression {
|
||||
expression: Expression;
|
||||
}
|
||||
|
||||
export interface BinaryExpression extends Expression {
|
||||
left: Expression;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user