// expr_stmt: expression_list // expression_list: expression ( "," expression )* [","] // assignment_stmt: (target_list "=")+ (expression_list | yield_expression) // augmented_assignment_stmt ::= target augop (expression_list | yield_expression) // augop: '+=' | '-=' | '*=' | '/=' | '%=' | '**=' | '>>=' | '<<=' | '&=' | '^=' | '|=' | '//=' private Statement ParseExprStmt() { Expression ret = ParseTestListAsExpr(); if (ret is ErrorExpression) { NextToken(); } if (PeekToken(TokenKind.Assign)) { return FinishAssignments(ret); } else { PythonOperator op = GetAssignOperator(PeekToken()); if (op != PythonOperator.None) { NextToken(); Expression rhs; if (MaybeEat(TokenKind.KeywordYield)) { rhs = ParseYieldExpression(); } else { rhs = ParseTestListAsExpr(); } string assignError = ret.CheckAugmentedAssign(); if (assignError != null) { ReportSyntaxError(assignError); } AugmentedAssignStatement aug = new AugmentedAssignStatement(op, ret, rhs); aug.SetLoc(_globalParent, ret.StartIndex, GetEnd()); return aug; } else { Statement stmt = new ExpressionStatement(ret); stmt.SetLoc(_globalParent, ret.IndexSpan); return stmt; } } }
private Statement ParseYieldStmt() { // For yield statements, continue to enforce that it's currently in a function. // This gives us better syntax error reporting for yield-statements than for yield-expressions. FunctionDefinition current = CurrentFunction; if (current == null) { ReportSyntaxError(IronPython.Resources.MisplacedYield); } _isGenerator = true; if (_returnWithValue) { ReportSyntaxError("'return' with argument inside generator"); } Eat(TokenKind.KeywordYield); // See Pep 342: a yield statement is now just an expression statement around a yield expression. Expression e = ParseYieldExpression(); Debug.Assert(e != null); // caller already verified we have a yield. Statement s = new ExpressionStatement(e); s.SetLoc(_globalParent, e.IndexSpan); return s; }
// expr_stmt: expression_list // expression_list: expression ( "," expression )* [","] // assignment_stmt: (target_list "=")+ (expression_list | yield_expression) // augmented_assignment_stmt ::= target augop (expression_list | yield_expression) // augop: '+=' | '-=' | '*=' | '/=' | '%=' | '**=' | '>>=' | '<<=' | '&=' | '^=' | '|=' | '//=' private Statement ParseExprStmt() { Expression ret = ParseTestListAsExpr(false); if (ret is ErrorExpression) { NextToken(); } if (PeekToken(TokenKind.Assign)) { return FinishAssignments(ret); } else { PythonOperator op = GetAssignOperator(PeekToken()); if (op != PythonOperator.None) { NextToken(); Expression rhs; if (MaybeEat(TokenKind.KeywordYield)) { rhs = ParseYieldExpression(); } else { rhs = ParseTestListAsExpr(false); } if (ret is ListExpression || ret is TupleExpression) { ReportSyntaxError(ret.Start, ret.End, "illegal expression for augmented assignment"); } AugmentedAssignStatement aug = new AugmentedAssignStatement(op, ret, rhs); aug.SetLoc(ret.Start, GetEnd()); return aug; } else { Statement stmt = new ExpressionStatement(ret); stmt.SetLoc(ret.Span); return stmt; } } }
// genexpr_for ::= "for" target_list "in" or_test [genexpr_iter] // genexpr_iter ::= (genexpr_for | genexpr_if) * // // "for" has NOT been eaten before entering this method private Expression ParseGeneratorExpression(Expression expr) { ForStatement root = ParseGenExprFor(); Statement current = root; for (; ; ) { if (PeekToken(Tokens.KeywordForToken)) { current = NestGenExpr(current, ParseGenExprFor()); } else if (PeekToken(Tokens.KeywordIfToken)) { current = NestGenExpr(current, ParseGenExprIf()); } else { // Generator Expressions have an implicit function definition and yield around their expression. // (x for i in R) // becomes: // def f(): // for i in R: yield (x) ExpressionStatement ys = new ExpressionStatement(new YieldExpression(expr)); ys.Expression.SetLoc(_globalParent, expr.IndexSpan); ys.SetLoc(_globalParent, expr.IndexSpan); NestGenExpr(current, ys); break; } } // We pass the outermost iterable in as a parameter because Python semantics // say that this one piece is computed at definition time rather than iteration time const string fname = "<genexpr>"; Parameter parameter = new Parameter("__gen_$_parm__", 0); FunctionDefinition func = new FunctionDefinition(fname, new Parameter[] { parameter }, root); func.IsGenerator = true; func.SetLoc(_globalParent, root.StartIndex, GetEnd()); func.HeaderIndex = root.EndIndex; // Transform the root "for" statement Expression outermost = root.List; NameExpression ne = new NameExpression("__gen_$_parm__"); ne.SetLoc(_globalParent, outermost.IndexSpan); root.List = ne; GeneratorExpression ret = new GeneratorExpression(func, outermost); ret.SetLoc(_globalParent, expr.StartIndex, GetEnd()); return ret; }
//expr_stmt: testlist (augassign testlist | ('=' testlist)*) //augassign: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//=' private Statement ParseExprStmt() { Expression lhs = ParseTestListAsExpr(false); if (MaybeEat(TokenKind.Assign)) { List<Expression> l = new List<Expression>(); l.Add(lhs); do { Expression e = ParseTestListAsExpr(false); l.Add(e); } while (MaybeEat(TokenKind.Assign)); int last = l.Count - 1; Expression rhs = (Expression)l[last]; l.RemoveAt(last); Expression[] lhss = l.ToArray(); //We check for legal assignment targets during code generation rather than parsing Statement ret = new AssignStatement(lhss, rhs); ret.SetLoc(GetExternal(), lhs.Start, GetEnd()); return ret; } else { BinaryOperator op = GetAssignOp(PeekToken()); if (op == null) { Statement ret = new ExpressionStatement(lhs); ret.SetLoc(GetExternal(), lhs.Start, GetEnd()); return ret; } else { NextToken(); Expression rhs = ParseTestListAsExpr(false); Statement ret = new AugAssignStatement(op, lhs, rhs); ret.SetLoc(GetExternal(), lhs.Start, GetEnd()); return ret; } } }