8000 gh-132661: Implement PEP 750 by lysnikolaou · Pull Request #132662 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-132661: Implem 8000 ent PEP 750 #132662

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 104 commits into from
Apr 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
9248287
Implement next version of PEP 750
lysnikolaou Oct 1, 2024
450d771
First fixes; conv and format_spec still not working
lysnikolaou Oct 18, 2024
a095a9b
Change BUILD_INTERPOLATION opcode to simplify
lysnikolaou Oct 18, 2024
499d70c
Add templatelib module & clean-up types/objects etc.
lysnikolaou Oct 20, 2024
f742d45
Support explicit concatenation of template and str
lysnikolaou Oct 21, 2024
0dda3f9
Avoid folding one node template into its content
lysnikolaou Oct 22, 2024
17014e7
Implement __eq__ for template and interpolation
lysnikolaou Oct 23, 2024
94371bd
Fix debug specifier segfault
lysnikolaou Oct 23, 2024
99184cc
Add __match_args__ to Interpolation
lysnikolaou Oct 23, 2024
4e89c87
Fix syntax error prefix in t-strings
lysnikolaou Oct 23, 2024
6bfb095
Fix test_dis
lysnikolaou Oct 23, 2024
560e957
Fix test_fstring
lysnikolaou Oct 23, 2024
4d172c2
Fix test_embed
lysnikolaou Oct 23, 2024
c9362e3
Implement interleaving, hash functions and *args __init__
lysnikolaou Oct 23, 2024
d2bd673
Use Argument Clinic for interpolation_new
lysnikolaou Oct 25, 2024
7ae1b60
Revert to using different grammar rules for tstring due to format_spec
lysnikolaou Oct 25, 2024
5e7304f
Fix code generation for when there's many values in tstring
lysnikolaou Oct 25, 2024
c8f22f0
Remove duplicate parens from template repr
lysnikolaou Oct 25, 2 8000 024
b0dbe27
Fix conversion converter for interpolation __new__
lysnikolaou Oct 25, 2024
b07c419
Merge branch 'main' into tstrings
lysnikolaou Oct 27, 2024
3e84771
Fix test_embed and test_dis -- again
lysnikolaou Nov 1, 2024
9380ab9
Implement implicit concatenation with TemplateStr
lysnikolaou Nov 1, 2024
22f9dc6
Merge branch 'main' into tstrings
lysnikolaou Feb 20, 2025
f207637
Implement new specification of template type
lysnikolaou Feb 20, 2025
29b1386
Replace nb_add with sq_concat
lysnikolaou Feb 20, 2025
aad5d67
Correctly implement str + tstring
lysnikolaou Feb 21, 2025
77822be
Make changes requested by Steering Council (#57)
Wingysam Apr 9, 2025
f3ba0fe
Merge branch 'main' into tstrings
lysnikolaou Apr 9, 2025
422a515
Remove unnecessary _Py_TPFLAGS_MATCH_SELF from Template type (#60)
koxudaxi Apr 9, 2025
bb7359a
Fix memory leak in template concat error handling (#59)
koxudaxi Apr 9, 2025
6a7b448
PEP 750 bug and spec fix (#58)
davepeck Apr 9, 2025
e6d01ef
Fix for segv in `_PyInterpolation_FromStackRefSteal` (#61)
davepeck Apr 10, 2025
0801f17
More minor fixes after merge with main
lysnikolaou Apr 10, 2025
a51e954
Fix JIT build
lysnikolaou Apr 10, 2025
76816a1
Fix Windows build
lysnikolaou Apr 10, 2025
2c53f55
Remove smelly _conversion_converter symbol
lysnikolaou Apr 10, 2025
fa4b531
Fix check-c-globals
lysnikolaou Apr 10, 2025
98e5d83
Fix various stuff in the VM
lysnikolaou Apr 11, 2025
a7c57fe
Add tests
lysnikolaou Apr 11, 2025
d6c470c
Fix Windows build (#64)
AA-Turner Apr 11, 2025
101abe3
Merge branch 'main' into tstrings
lysnikolaou Apr 11, 2025
7573346
Fix lint
lysnikolaou Apr 11, 2025
4f91ea3
Skip test_tstring.py from ruff
lysnikolaou Apr 11, 2025
14d9fa4
Fix parser bug and implement ast_unparse in Python
lysnikolaou Apr 11, 2025
bf89325
Modify CODEOWNERS
lysnikolaou Apr 11, 2025
b7edcd6
Do not use _PyAST_ExprAsUnicode (unparse) for interpolation expression
lysnikolaou Apr 11, 2025
99c3bf4
Remove interpolation_compare() and interpolation_hash() (#65)
davepeck Apr 17, 2025
f09d99f
Add type check macros (#67)
AA-Turner Apr 17, 2025
878eb69
t-strings: cosmetics (#66)
AA-Turner Apr 17, 2025
7ed73fa
Implement GC protocol for template and interpolation types
lysnikolaou Apr 17, 2025
e88d111
Fix test_unparse again!
lysnikolaou Apr 17, 2025
92fd148
Remove unnecessary tp_flag from interpolation type
lysnikolaou Apr 17, 2025
c833f6d
Merge branch 'main' into tstrings
lysnikolaou Apr 17, 2025
8f8a414
Minor fixes (mostly cosmetic)
lysnikolaou Apr 17, 2025
6bfc888
Add test for interleaving
lysnikolaou Apr 17, 2025
0ee90f9
Merge branch 'main' into tstrings
terryjreedy Apr 18, 2025
e6da757
t-strings: Add more syntax tests (#68)
AA-Turner Apr 18, 2025
58b7e5c
Move string.templatelib specific tests to test_string/test_templatlib…
AA-Turner Apr 19, 2025
4c6cb47
Add more concatenation tests (#71)
AA-Turner Apr 19, 2025
5782897
t-strings: Reduce undefined behaviour and general improvements (#72)
AA-Turner Apr 19, 2025
8000
fb68d60
Add ``assertTStringEqual()`` helper (#73)
AA-Turner Apr 21, 2025
174b045
Add a what's new entry (#69)
pauleveritt Apr 21, 2025
62ace68
Fix repr
lysnikolaou Apr 21, 2025
4f6c5df
Fix syntax errors in grammar
lysnikolaou Apr 21, 2025
e84778a
Rename f helper to fstring
lysnikolaou Apr 21, 2025
8b24ff3
Use Py_BuildValue and add error checking for _PyType_GetDict
lysnikolaou Apr 21, 2025
23444df
Return a strong ref from _PyInterpolation_GetValue
lysnikolaou Apr 21, 2025
19aad93
Remove unnecessary function for template concatenation
lysnikolaou Apr 21, 2025
adbc109
Formatting
lysnikolaou Apr 21, 2025
a5e3bde
Add versionadded directive to TSTRING_START docs
lysnikolaou Apr 21, 2025
c8a9482
Add TOK_GET_STRING_PREFIX macro and change tstring field to enum
lysnikolaou Apr 21, 2025
4e32db6
Merge branch 'main' into tstrings
lysnikolaou Apr 21, 2025
a78c082
Minor fixes to lexer and Makefile
lysnikolaou Apr 21, 2025
173e456
Rename fields in tokenizer mode to not be f-string specific
lysnikolaou Apr 21, 2025
a595ccc
Nit: return result instead of -1
lysnikolaou Apr 22, 2025
2282ccc
Move AST test to test_ast
lysnikolaou Apr 22, 2025
53fc995
Fix unparsing implicit concat of t-strings with f-strings
lysnikolaou Apr 22, 2025
58da4e0
Update CODEOWNERS
lysnikolaou Apr 22, 2025
3e10c49
Clean up test_tstring
lysnikolaou Apr 22, 2025
2addef7
Add new tokens TSTRING_MIDDLE & TSTRING_END
lysnikolaou Apr 22, 2025
550fd07
Merge branch 'main' into tstrings
lysnikolaou Apr 22, 2025
06c15de
Make Interpolation.conversion an int and change bytecode def
lysnikolaou Apr 22, 2025
f57647e
Fix ast_unparse and token generator
lysnikolaou Apr 22, 2025
a21391a
Let compiler build template tuples
lysnikolaou Apr 22, 2025
1dca604
Add tp_clear slot and remove UB casts
lysnikolaou Apr 22, 2025
011ca83
Apply Hugo's suggestions from code review
lysnikolaou Apr 22, 2025
1379756
Add empty line to CODEOWNERS
lysnikolaou Apr 22, 2025
4d1f2a5
Add news blurb
lysnikolaou Apr 22, 2025
8842739
t-strings: Various changes (#74)
AA-Turner Apr 23, 2025
cf56234
Merge branch 'main' into tstrings
lysnikolaou Apr 23, 2025
280e90e
Merge branch 'main' into tstrings
AA-Turner Apr 23, 2025
051e8eb
Add pickle support for tstrings (#75)
sobolevn Apr 23, 2025
aa7c603
Merge branch 'main' into tstrings
lysnikolaou Apr 23, 2025
ce78496
Address feedback; fix template_values_get and conversion
lysnikolaou Apr 23, 2025
8468e10
Merge branch 'main' into tstrings
lysnikolaou Apr 24, 2025
9cee9ff
Merge branch 'main' into tstrings
lysnikolaou Apr 25, 2025
0303c25
Add snippets to Lib/test/test_ast/snippets.py
lysnikolaou Apr 25, 2025
6edaba0
Merge branch 'main' into tstrings
sobolevn Apr 28, 2025
ab9026f
Remove _templatelib extension
lysnikolaou Apr 29, 2025
48f771b
Change __reduce__ flags to METH_NOARGS
lysnikolaou Apr 29, 2025
0b1aef9
Merge branch 'main' into tstrings
lysnikolaou Apr 29, 2025
8b0c132
Fix docs for TSTRING_MIDDLE
lysnikolaou Apr 30, 2025
b35ba13
Merge branch 'main' into tstrings
lysnikolaou Apr 30, 2025
44749c7
Fix ERROR_IF
lysnikolaou Apr 30, 2025
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
6 changes: 6 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -320,3 +320,9 @@ Lib/test/test__colorize.py @hugovk

# Fuzzing
Modules/_xxtestfuzz/ @ammaraskar

# t-strings
**/*interpolationobject* @lysnikolaou
**/*templateobject* @lysnikolaou
**/*templatelib* @lysnikolaou
**/*tstring* @lysnikolaou
35 changes: 35 additions & 0 deletions Doc/library/token.rst
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,41 @@ The token constants are:

The token string contains the closing quote(s).

.. data:: TSTRING_START

Token value used to indicate the beginning of a template string literal.

.. impl-detail::

The token string includes the prefix and the opening quote(s), but none
of the contents of the literal.

.. versionadded:: next

.. data:: TSTRING_MIDDLE

Token value used for literal text inside a template string literal
including format specifications.

.. impl-detail::

Replacement fields (that is, the non-literal parts of t-strings) use
the same tokens as other expressions, and are delimited by
:data:`LBRACE`, :data:`RBRACE`, :data:`EXCLAMATION` and :data:`COLON`
tokens.

.. versionadded:: next

.. data:: TSTRING_END

Token value used to indicate the end of a template string literal.

.. impl-detail::

The token string contains the closing quote(s).

.. versionadded:: next

.. data:: ENDMARKER

Token value that indicates the end of input.
Expand Down
71 changes: 71 additions & 0 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ Summary -- release highlights

* :ref:`PEP 649: deferred evaluation of annotations <whatsnew314-pep649>`
* :ref:`PEP 741: Python Configuration C API <whatsnew314-pep741>`
* :ref:`PEP 750: Template Strings <whatsnew314-pep750>`
* :ref:`PEP 758: Allow except and except* expressions without parentheses <whatsnew314-pep758>`
* :ref:`PEP 761: Discontinuation of PGP signatures <whatsnew314-pep761>`
* :ref:`PEP 765: Disallow return/break/continue that exit a finally block <whatsnew314-pep765>`
Expand All @@ -92,6 +93,76 @@ If you encounter :exc:`NameError`\s or pickling errors coming out of
New features
============

.. _whatsnew314-pep750:

PEP 750: Template Strings
-------------------------

Template string literals (t-strings) are a generalization of f-strings,
using a ``t`` in place of the ``f`` prefix. Instead of evaluating
to :class:`str`, t-strings evaluate to a new :class:`!string.templatelib.Template` type:

.. code-block:: python

from string.templatelib import Template

name = "World"
template: Template = t"Hello {name}"

The template can then be combined with functions that operate on the template's
structure to produce a :class:`str` or a string-like result.
For example, sanitizing input:

.. code-block:: python

evil = "<script>alert('evil')</script>"
template = t"<p>{evil}</p>"
assert html(template) == "<p>&lt;script&gt;alert('evil')&lt;/script&gt;</p>"

As another example, generating HTML attributes from data:

.. code-block:: python

attributes = {"src": "shrubbery.jpg", "alt": "looks nice"}
template = t"<img {attributes} />"
assert html(template) == '<img src="shrubbery.jpg" alt="looks nice" class="looks-nice" />'

Unlike f-strings, the ``html`` function has access to template attributes
containing the original information: static strings, interpolations, and values
from the original scope. Unlike existing templating approaches, t-strings build
from the well-known f-string syntax and rules. Template systems thus benefit
from Python tooling as they are much closer to the Python language, syntax,
scoping, and more.

Writing template handlers is straightforward:

.. code-block:: python

from string.templatelib import Template, Interpolation

def lower_upper(template: Template) -> str:
"""Render static parts lowercased and interpolations uppercased."""
parts: list[str] = []
for item in template:
if isinstance(item, Interpolation):
parts.append(str(item.value).upper())
else:
parts.append(item.lower())
return "".join(parts)

name = "world"
assert lower_upper(t"HELLO {name}") == "hello WORLD"

With this in place, developers can write template systems to sanitize SQL, make
safe shell operations, improve logging, tackle modern ideas in web development
(HTML, CSS, and so on), and implement lightweight, custom business DSLs.

See :pep:`750` for more details.

(Contributed by Jim Baker, Guido van Rossum, Paul Everitt, Koudai Aono,
Lysandros Nikolaou, Dave Peck, Adam Turner, Jelle Zijlstra, Bénédikt Tran,
and Pablo Galindo Salgado in :gh:`132661`.)

.. _whatsnew314-pep768:

PEP 768: Safe external debugger interface for CPython
Expand Down
3 changes: 3 additions & 0 deletions Grammar/Tokens
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ SOFT_KEYWORD
FSTRING_START
FSTRING_MIDDLE
FSTRING_END
TSTRING_START
TSTRING_MIDDLE
TSTRING_END
COMMENT
NL
ERRORTOKEN
Expand Down
59 changes: 51 additions & 8 deletions Grammar/python.gram
10000
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ literal_pattern[pattern_ty]:
literal_expr[expr_ty]:
| signed_number !('+' | '-')
| complex_number
| strings
| &(STRING|FSTRING_START|TSTRING_START) strings
| 'None' { _PyAST_Constant(Py_None, NULL, EXTRA) }
| 'True' { _PyAST_Constant(Py_True, NULL, EXTRA) }
| 'False' { _PyAST_Constant(Py_False, NULL, EXTRA) }
Expand Down Expand Up @@ -859,7 +859,7 @@ atom[expr_ty]:
| 'True' { _PyAST_Constant(Py_True, NULL, EXTRA) }
| 'False' { _PyAST_Constant(Py_False, NULL, EXTRA) }
| 'None' { _PyAST_Constant(Py_None, NULL, EXTRA) }
| &(STRING|FSTRING_START) strings
| &(STRING|FSTRING_START|TSTRING_START) strings
| NUMBER
| &'(' (tuple | group | genexp)
| &'[' (list | listcomp)
Expand Down Expand Up @@ -935,7 +935,7 @@ fstring_middle[expr_ty]:
fstring_replacement_field[expr_ty]:
| '{' a=annotated_rhs debug_expr='='? conversion=[fstring_conversion] format=[fstring_full_format_spec] rbrace='}' {
_PyPegen_formatted_value(p, a, debug_expr, conversion, format, rbrace, EXTRA) }
| invalid_replacement_field
| invalid_fstring_replacement_field
fstring_conversion[ResultTokenWithMetadata*]:
| conv_token="!" conv=NAME { _PyPegen_check_fstring_conversion(p, conv_token, conv) }
fstring_full_format_spec[ResultTokenWithMetadata*]:
Expand All @@ -946,8 +946,27 @@ fstring_format_spec[expr_ty]:
fstring[expr_ty]:
| a=FSTRING_START b=fstring_middle* c=FSTRING_END { _PyPegen_joined_str(p, a, (asdl_expr_seq*)b, c) }

tstring_format_spec_replacement_field[expr_ty]:
| '{' a=annotated_rhs debug_expr='='? conversion=[fstring_conversion] format=[tstring_full_format_spec] rbrace='}' {
_PyPegen_formatted_value(p, a, debug_expr, conversion, format, rbrace, EXTRA) }
| invalid_tstring_replacement_field
tstring_format_spec[expr_ty]:
| t=TSTRING_MIDDLE { _PyPegen_decoded_constant_from_token(p, t) }
| tstring_format_spec_replacement_field
tstring_full_format_spec[ResultTokenWithMetadata*]:
| colon=':' spec=tstring_format_spec* { _PyPegen_setup_full_format_spec(p, colon, (asdl_expr_seq *) spec, EXTRA) }
tstring_replacement_field[expr_ty]:
| '{' a=annotated_rhs debug_expr='='? conversion=[fstring_conversion] format=[tstring_full_format_spec] rbrace='}' {
_PyPegen_interpolation(p, a, debug_expr, conversion, format, rbrace, EXTRA) }
| invalid_tstring_replacement_field
tstring_middle[expr_ty]:
| tstring_replacement_field
| t=TSTRING_MIDDLE { _PyPegen_constant_from_token(p, t) }
tstring[expr_ty] (memo):
| a=TSTRING_START b=tstring_middle* c=TSTRING_END { _PyPegen_template_str(p, a, (asdl_expr_seq*)b, c) }

string[expr_ty]: s[Token*]=STRING { _PyPegen_constant_from_string(p, s) }
strings[expr_ty] (memo): a[asdl_expr_seq*]=(fstring|string)+ { _PyPegen_concatenate_strings(p, a, EXTRA) }
strings[expr_ty] (memo): a[asdl_expr_seq*]=(fstring|string|tstring)+ { _PyPegen_concatenate_strings(p, a, EXTRA) }

list[expr_ty]:
| '[' a=[star_named_expressions] ']' { _PyAST_List(a, Load, EXTRA) }
Expand Down Expand Up @@ -1212,6 +1231,8 @@ invalid_expression:
RAISE_SYNTAX_ERROR_KNOWN_LOCATION (a, "expected expression before 'if', but statement is given") }
| a='lambda' [lambda_params] b=':' &FSTRING_MIDDLE {
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "f-string: lambda expressions are not allowed without parentheses") }
| a='lambda' [lambda_params] b=':' &TSTRING_MIDDLE {
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "t-string: lambda expressions are not allowed without parentheses") }

invalid_named_expression(memo):
| a=expression ':=' expression {
Expand Down Expand Up @@ -1454,28 +1475,50 @@ invalid_starred_expression_unpacking:
invalid_starred_expression:
| '*' { RAISE_SYNTAX_ERROR("Invalid star expression") }

invalid_replacement_field:
invalid_fstring_replacement_field:
| '{' a='=' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before '='") }
| '{' a='!' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before '!'") }
| '{' a=':' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before ':'") }
| '{' a='}' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before '}'") }
| '{' !annotated_rhs { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting a valid expression after '{'")}
| '{' !annotated_rhs { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting a valid expression after '{'") }
| '{' annotated_rhs !('=' | '!' | ':' | '}') {
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting '=', or '!', or ':', or '}'") }
| '{' annotated_rhs '=' !('!' | ':' | '}') {
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting '!', or ':', or '}'") }
| '{' annotated_rhs '='? invalid_conversion_character
| '{' annotated_rhs '='? invalid_fstring_conversion_character
| '{' annotated_rhs '='? ['!' NAME] !(':' | '}') {
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting ':' or '}'") }
| '{' annotated_rhs '='? ['!' NAME] ':' fstring_format_spec* !'}' {
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting '}', or format specs") }
| '{' annotated_rhs '='? ['!' NAME] !'}' {
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting '}'") }

invalid_conversion_character:
invalid_fstring_conversion_character:
| '!' &(':' | '}') { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: missing conversion character") }
| '!' !NAME { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: invalid conversion character") }

invalid_tstring_replacement_field:
| '{' a='=' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "t-string: valid expression required before '='") }
| '{' a='!' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "t-string: valid expression required before '!'") }
| '{' a=':' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "t-string: valid expression required before ':'") }
| '{' a='}' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "t-string: valid expression required before '}'") }
| '{' !annotated_rhs { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("t-string: expecting a valid expression after '{'") }
| '{' annotated_rhs !('=' | '!' | ':' | '}') {
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("t-string: expecting '=', or '!', or ':', or '}'") }
| '{' annotated_rhs '=' !('!' | ':' | '}') {
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("t-string: expecting '!', or ':', or '}'") }
| '{' annotated_rhs '='? invalid_tstring_conversion_character
| '{' annotated_rhs '='? ['!' NAME] !(':' | '}') {
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("t-string: expecting ':' or '}'") }
| '{' annotated_rhs '='? ['!' NAME] ':' fstring_format_spec* !'}' {
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("t-string: expecting '}', or format specs") }
| '{' annotated_rhs '='? ['!' NAME] !'}' {
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("t-string: expecting '}'") }

invalid_tstring_conversion_character:
| '!' &(':' | '}') { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("t-string: missing conversion character") }
| '!' !NAME { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("t-string: invalid conversion character") }

invalid_arithmetic:
| sum ('+'|'-'|'*'|'/'|'%'|'//'|'@') a='not' b=inversion { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "'not' after an operator must be parenthesized") }
invalid_factor:
Expand Down
24 changes: 21 additions & 3 deletions Include/internal/pycore_ast.h

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

3 changes: 3 additions & 0 deletions Include/internal/pycore_ast_state.h

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

2 changes: 2 additions & 0 deletions Include/internal/pycore_global_objects_fini_generated.h

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

2 changes: 2 additions & 0 deletions Include/internal/pycore_global_strings.h
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(consts)
STRUCT_FOR_ID(context)
STRUCT_FOR_ID(contravariant)
STRUCT_FOR_ID(conversion)
STRUCT_FOR_ID(cookie)
STRUCT_FOR_ID(copy)
STRUCT_FOR_ID(copyreg)
Expand Down Expand Up @@ -428,6 +429,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(exception)
STRUCT_FOR_ID(existing_file_name)
STRUCT_FOR_ID(exp)
STRUCT_FOR_ID(expression)
STRUCT_FOR_ID(extend)
STRUCT_FOR_ID(extra_tokens)
STRUCT_FOR_ID(facility)
Expand Down
Loading
Loading
0