Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
212 changes: 108 additions & 104 deletions Doc/library/token-list.inc

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Grammar/Tokens
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ RARROW '->'
ELLIPSIS '...'
COLONEQUAL ':='
EXCLAMATION '!'
DOLLAR '$'
TERNARY '?'

OP
TYPE_IGNORE
Expand Down
40 changes: 37 additions & 3 deletions Grammar/python.gram
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ simple_stmts[asdl_stmt_seq*]:
# NOTE: assignment MUST precede expression, else parsing a simple assignment
# will throw a SyntaxError.
simple_stmt[stmt_ty] (memo):
| dollar_stmt
| assignment
| &"type" type_alias
| &('import' | 'from' | "lazy") import_stmt
Expand All @@ -134,6 +135,20 @@ simple_stmt[stmt_ty] (memo):
| &'global' global_stmt
| &'nonlocal' nonlocal_stmt

dollar_stmt[stmt_ty]:
| '$' n=NAME {
_PyAST_Assign(
CHECK(asdl_expr_seq*,
_PyPegen_singleton_seq(
p,
_PyAST_Name(n->v.Name.id, Store, EXTRA)
)
),
_PyAST_Constant(Py_None, NULL, EXTRA),
NULL,
EXTRA
)
}
compound_stmt[stmt_ty]:
| &('def' | '@' | 'async') function_def
| &'if' if_stmt
Expand Down Expand Up @@ -717,13 +732,25 @@ expression[expr_ty] (memo):
| invalid_if_expression
| invalid_expression
| invalid_legacy_expression
| question_if_expression
| if_expression
| disjunction
| lambdef

# IMPORTANT:
# The 'no' branch must be 'expression' (which includes question_if_expression
# as one of its alternatives), NOT question_if_expression directly.
# question_if_expression only matches "X ? Y : Z" shape; using it directly
# for 'no' forces the false-branch to ALSO be a ternary, breaking simple
# cases like "12 > 2 ? 5 : 4" where 4 is just a plain expression.
question_if_expression[expr_ty]:
| cond=disjunction '?' yes=expression ':' no=expression {
_PyAST_IfExp(cond, yes, no, EXTRA)
Comment on lines +747 to +748

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Gate the new syntax by feature_version

When callers parse with an older grammar via PyCF_ONLY_AST/ast.parse(..., feature_version=(3, 15)), this rule still accepts a ? b : c because it constructs IfExp directly instead of using CHECK_VERSION. Since this tree is already Python 3.16 (PY_MINOR_VERSION is 16), the new ?: syntax (and the new $ statement rule) should be wrapped in a version check so tools that request an older grammar continue to reject it.

Useful? React with 👍 / 👎.

}
if_expression[expr_ty]:
| a=disjunction 'if' b=disjunction 'else' c=expression { _PyAST_IfExp(b, a, c, EXTRA) }

| a=disjunction 'if' b=disjunction 'else' c=expression {
_PyAST_IfExp(b, a, c, EXTRA)
}
yield_expr[expr_ty]:
| 'yield' 'from' a=expression { _PyAST_YieldFrom(a, EXTRA) }
| 'yield' a=[star_expressions] { _PyAST_Yield(a, EXTRA) }
Expand Down Expand Up @@ -1239,11 +1266,17 @@ invalid_kwarg:
| a='**' expression '=' b=expression {
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "cannot assign to keyword argument unpacking") }

# IMPORTANT: Note that the "_without_invalid" suffix causes the rule to not call invalid rules under it
# IMPORTANT:
# expression_without_invalid must ALSO recognize question_if_expression,
# otherwise the invalid_* rules (which run BEFORE question_if_expression
# in the main `expression` rule) will treat '?' as a syntax error before
# ever letting question_if_expression get a chance to parse it.
expression_without_invalid[expr_ty]:
| a=disjunction 'if' b=disjunction 'else' c=expression { _PyAST_IfExp(b, a, c, EXTRA) }
| question_if_expression
| disjunction
| lambdef

invalid_legacy_expression:
| a=NAME !'(' b=star_expressions {
_PyPegen_check_legacy_stmt(p, a) ? RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b,
Expand Down Expand Up @@ -1659,3 +1692,4 @@ invalid_bitwise_or:
? RAISE_SYNTAX_ERROR_KNOWN_RANGE(b, c, "invalid syntax. Maybe you meant 'or' or '|' instead of '||'?")
: NULL
}

Loading
Loading