/// <summary> /// Peek if the next token is a 'yield' and parse a yield or yield from expression. Else return null. /// /// Called w/ yield already eaten. /// </summary> /// <returns>A yield or yield from expression if present, else null.</returns> // yield_expression: "yield" [expression_list] private Expression ParseYieldExpression() { // Mark that this function is actually a generator. // If we're in a generator expression, then we don't have a function yet. // g=((yield i) for i in range(5)) // In that case, the genexp will mark IsGenerator. FunctionDefinition current = CurrentFunction; if (current != null) { current.IsGenerator = true; } string whitespace = _tokenWhiteSpace; var start = GetStart(); // Parse expression list after yield. This can be: // 1) empty, in which case it becomes 'yield None' // 2) a single expression // 3) multiple expression, in which case it's wrapped in a tuple. // 4) 'from', in which case we expect a single expression and return YieldFromExpression Expression yieldResult; bool isYieldFrom = PeekToken(TokenKind.KeywordFrom); bool suppressSyntaxError = false; string fromWhitespace = string.Empty; if (isYieldFrom) { if (_langVersion < JLanguageVersion.V33) { // yield from added to 3.3 ReportSyntaxError("invalid syntax"); suppressSyntaxError = true; } NextToken(); fromWhitespace = _tokenWhiteSpace; } bool trailingComma; List<string> itemWhiteSpace; List<Expression> l = ParseTestListAsExpr(null, out itemWhiteSpace, out trailingComma); if (l.Count == 0) { if (_langVersion < JLanguageVersion.V71 && !suppressSyntaxError) { // 2.4 doesn't allow plain yield ReportSyntaxError("invalid syntax"); } else if (isYieldFrom && !suppressSyntaxError) { // yield from requires one expression ReportSyntaxError("invalid syntax"); } // Check empty expression and convert to 'none' yieldResult = new ConstantExpression(null); } else if (l.Count != 1) { if (isYieldFrom && !suppressSyntaxError) { // yield from requires one expression ReportSyntaxError(l[0].StartIndex, l[l.Count - 1].EndIndex, "invalid syntax"); } // make a tuple yieldResult = MakeTupleOrExpr(l, itemWhiteSpace, trailingComma, true); } else { // just take the single expression yieldResult = l[0]; } Expression yieldExpression; if (isYieldFrom) { yieldExpression = new YieldFromExpression(yieldResult); } else { yieldExpression = new YieldExpression(yieldResult); } if (_verbatim) { AddPreceedingWhiteSpace(yieldExpression, whitespace); if (!string.IsNullOrEmpty(fromWhitespace)) { AddSecondPreceedingWhiteSpace(yieldExpression, fromWhitespace); } if (l.Count == 0) { AddIsAltForm(yieldExpression); } else if (l.Count == 1 && trailingComma) { AddListWhiteSpace(yieldExpression, itemWhiteSpace.ToArray()); } } yieldExpression.SetLoc(start, GetEnd()); return yieldExpression; }
private Expression ParseLambdaHelperEnd(FunctionDefinition func, Expression expr, string whitespace, string colonWhiteSpace, List<string> commaWhiteSpace, bool ateTerminator) { // Pep 342 in J 2.5 allows Yield Expressions, which can occur inside a Lambda body. // In this case, the lambda is a generator and will yield it's final result instead of just return it. Statement body; if (func.IsGenerator) { YieldExpression y = new YieldExpression(expr); y.SetLoc(expr.IndexSpan); body = new ExpressionStatement(y); } else { body = new ReturnStatement(expr); } body.SetLoc(expr.StartIndex, expr.EndIndex); FunctionDefinition func2 = PopFunction(); System.Diagnostics.Debug.Assert(func == func2); func.SetBody(body); func.EndIndex = GetEnd(); LambdaExpression ret = new LambdaExpression(func); func.SetLoc(func.IndexSpan); ret.SetLoc(func.IndexSpan); if (_verbatim) { AddPreceedingWhiteSpace(ret, whitespace); AddSecondPreceedingWhiteSpace(ret, colonWhiteSpace); AddListWhiteSpace(ret, commaWhiteSpace.ToArray()); if (!ateTerminator) { AddErrorIsIncompleteNode(ret); } } return ret; }
public override void PostWalk(YieldExpression node) { PostWalkWorker(node); }
// YieldExpression public override bool Walk(YieldExpression node) { return ShouldWalkWorker(node); }
public override bool Walk(YieldExpression node) { ContainsYield = true; return base.Walk(node); }