Added support for walrus (assignment) operator within set literal expressions if the python version is >= 3.10. The grammar was changed in 3.10 to support this. This addresses #8216.

This commit is contained in:
Eric Traut 2024-06-24 23:56:08 +02:00
parent 3a263135ab
commit bc1fc9f22b
2 changed files with 25 additions and 8 deletions

View File

@ -866,18 +866,22 @@ export namespace BinaryOperationNode {
export interface AssignmentExpressionNode extends ParseNodeBase { export interface AssignmentExpressionNode extends ParseNodeBase {
readonly nodeType: ParseNodeType.AssignmentExpression; readonly nodeType: ParseNodeType.AssignmentExpression;
name: NameNode; name: NameNode;
walrusToken: Token;
rightExpression: ExpressionNode; rightExpression: ExpressionNode;
isParenthesized: boolean;
} }
export namespace AssignmentExpressionNode { export namespace AssignmentExpressionNode {
export function create(name: NameNode, rightExpression: ExpressionNode) { export function create(name: NameNode, walrusToken: Token, rightExpression: ExpressionNode) {
const node: AssignmentExpressionNode = { const node: AssignmentExpressionNode = {
start: name.start, start: name.start,
length: name.length, length: name.length,
nodeType: ParseNodeType.AssignmentExpression, nodeType: ParseNodeType.AssignmentExpression,
id: _nextNodeId++, id: _nextNodeId++,
name, name,
walrusToken,
rightExpression, rightExpression,
isParenthesized: false,
}; };
name.parent = node; name.parent = node;

View File

@ -3184,7 +3184,7 @@ export class Parser {
const rightExpr = this._parseTestExpression(/* allowAssignmentExpression */ false); const rightExpr = this._parseTestExpression(/* allowAssignmentExpression */ false);
return AssignmentExpressionNode.create(leftExpr, rightExpr); return AssignmentExpressionNode.create(leftExpr, walrusToken, rightExpr);
} }
// or_test: and_test ('or' and_test)* // or_test: and_test ('or' and_test)*
@ -3910,11 +3910,11 @@ export class Parser {
possibleTupleNode.parenthesized = true; possibleTupleNode.parenthesized = true;
} }
if (possibleTupleNode.nodeType === ParseNodeType.StringList) { if (
possibleTupleNode.isParenthesized = true; possibleTupleNode.nodeType === ParseNodeType.StringList ||
} possibleTupleNode.nodeType === ParseNodeType.Comprehension ||
possibleTupleNode.nodeType === ParseNodeType.AssignmentExpression
if (possibleTupleNode.nodeType === ParseNodeType.Comprehension) { ) {
possibleTupleNode.isParenthesized = true; possibleTupleNode.isParenthesized = true;
} }
@ -4140,10 +4140,23 @@ export class Parser {
if (this._consumeTokenIfOperator(OperatorType.Power)) { if (this._consumeTokenIfOperator(OperatorType.Power)) {
doubleStarExpression = this._parseExpression(/* allowUnpack */ false); doubleStarExpression = this._parseExpression(/* allowUnpack */ false);
} else { } else {
keyExpression = this._parseTestOrStarExpression(/* allowAssignmentExpression */ false); keyExpression = this._parseTestOrStarExpression(/* allowAssignmentExpression */ true);
// Allow walrus operators in this context only for Python 3.10 and newer.
// Older versions of Python generated a syntax error in this context.
let isWalrusAllowed = this._getLanguageVersion().isGreaterOrEqualTo(pythonVersion3_10);
if (this._consumeTokenIfType(TokenType.Colon)) { if (this._consumeTokenIfType(TokenType.Colon)) {
valueExpression = this._parseTestExpression(/* allowAssignmentExpression */ false); valueExpression = this._parseTestExpression(/* allowAssignmentExpression */ false);
isWalrusAllowed = false;
}
if (
!isWalrusAllowed &&
keyExpression.nodeType === ParseNodeType.AssignmentExpression &&
!keyExpression.isParenthesized
) {
this._addSyntaxError(LocMessage.walrusNotAllowed(), keyExpression.walrusToken);
} }
} }