Skip to content

Commit 77aa037

Browse files
committed
gh-153569: keep f-string comments with their mode
1 parent 1f2b9aa commit 77aa037

3 files changed

Lines changed: 19 additions & 44 deletions

File tree

Parser/lexer/state.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ void
4343
_PyLexer_PopMode(struct tok_state *tok)
4444
{
4545
assert(tok->tok_mode_stack_index > 0);
46+
tokenizer_mode *mode = _PyLexer_CurrentMode(tok);
47+
PyMem_Free(mode->comments);
4648
tok->tok_mode_stack_index--;
4749
}
4850

@@ -57,15 +59,12 @@ _PyTokenizer_Free(struct tok_state *tok)
5759
Py_XDECREF(tok->module);
5860
_PyTok_ReaderFree(tok);
5961
_PyTok_SourceClear(&tok->source);
62+
for (int i = 0; i <= tok->tok_mode_stack_index; i++) {
63+
PyMem_Free(tok->tok_mode_stack[i].comments);
64+
}
6065
if (tok->tok_mode_stack != tok->tok_mode_stack_inline) {
6166
PyMem_Free(tok->tok_mode_stack);
6267
}
63-
tokenizer_comments *comments = tok->ftstring_comments;
64-
while (comments != NULL) {
65-
tokenizer_comments *previous = comments->previous;
66-
PyMem_Free(comments);
67-
comments = previous;
68-
}
6968
PyMem_Free(tok);
7069
}
7170

Parser/lexer/state.h

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ typedef enum {
3535

3636
#define MAX_EXPR_NESTING 3
3737

38+
typedef struct _tokenizer_comments {
39+
Py_ssize_t count;
40+
Py_ssize_t capacity;
41+
_PyTok_Span spans[];
42+
} tokenizer_comments;
43+
3844
typedef struct _tokenizer_mode {
3945
tokenizer_mode_kind kind;
4046
ftstring_kind ftstring_kind;
@@ -47,6 +53,7 @@ typedef struct _tokenizer_mode {
4753
_PyTok_Off start;
4854
_PyTok_Loc start_loc;
4955
_PyTok_Span expr_span;
56+
tokenizer_comments *comments;
5057
} tokenizer_mode;
5158

5259
static inline int
@@ -68,14 +75,6 @@ _PyLexer_IsRawString(const tokenizer_mode *mode)
6875
mode->ftstring_kind == RAW_TSTRING;
6976
}
7077

71-
typedef struct _tokenizer_comments {
72-
struct _tokenizer_comments *previous;
73-
Py_ssize_t count;
74-
Py_ssize_t capacity;
75-
int mode_index;
76-
_PyTok_Span spans[];
77-
} tokenizer_comments;
78-
7978
/* Tokenizer state */
8079
struct tok_state {
8180
/* Input state; buf <= cur <= inp */
@@ -115,7 +114,6 @@ struct tok_state {
115114
tokenizer_mode tok_mode_stack_inline[TOKENIZER_MODE_INLINE_CAPACITY];
116115
int tok_mode_stack_index;
117116
int tok_mode_stack_capacity;
118-
tokenizer_comments *ftstring_comments;
119117
int tok_extra_tokens;
120118
int comment_newline;
121119
int implicit_newline;
@@ -139,12 +137,6 @@ _PyLexer_InsideFString(const struct tok_state *tok)
139137
return tok->tok_mode_stack_index > 0;
140138
}
141139

142-
static inline int
143-
_PyLexer_ModeDepth(const struct tok_state *tok)
144-
{
145-
return tok->tok_mode_stack_index;
146-
}
147-
148140
static inline char
149141
_PyLexer_CurrentStringPrefix(const struct tok_state *tok)
150142
{

Parser/lexer/string.c

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,6 @@ rewind_to_string_start(struct tok_state *tok, const char *start,
1616
tok->lineno = location.lineno;
1717
}
1818

19-
static tokenizer_comments *
20-
current_comments(const struct tok_state *tok)
21-
{
22-
tokenizer_comments *comments = tok->ftstring_comments;
23-
return comments != NULL &&
24-
comments->mode_index == _PyLexer_ModeDepth(tok)
25-
? comments : NULL;
26-
}
27-
2819
int
2920
_PyLexer_record_ftstring_comment(struct tok_state *tok, const char *start,
3021
const char *end)
@@ -34,9 +25,8 @@ _PyLexer_record_ftstring_comment(struct tok_state *tok, const char *start,
3425
return 0;
3526
}
3627
assert(mode->expr_span.start >= 0);
37-
tokenizer_comments *comments = current_comments(tok);
28+
tokenizer_comments *comments = mode->comments;
3829
if (comments == NULL || comments->count == comments->capacity) {
39-
int create = comments == NULL;
4030
Py_ssize_t max_capacity = (PY_SSIZE_T_MAX -
4131
(Py_ssize_t)sizeof(*comments)) /
4232
(Py_ssize_t)sizeof(*comments->spans);
@@ -53,13 +43,11 @@ _PyLexer_record_ftstring_comment(struct tok_state *tok, const char *start,
5343
return -1;
5444
}
5545
comments = resized;
56-
if (create) {
57-
comments->previous = tok->ftstring_comments;
46+
if (mode->comments == NULL) {
5847
comments->count = 0;
59-
comments->mode_index = _PyLexer_ModeDepth(tok);
6048
}
6149
comments->capacity = capacity;
62-
tok->ftstring_comments = comments;
50+
mode->comments = comments;
6351
}
6452
comments->spans[comments->count++] =
6553
_PyLexer_BufferSpan(tok, start, end);
@@ -79,7 +67,7 @@ _PyLexer_set_ftstring_expr_metadata(struct tok_state *tok, struct token *token)
7967
Py_ssize_t expr_len;
8068
const char *expr = _PyLexer_BufferSpanView(
8169
tok, tok_mode->expr_span, &expr_len);
82-
tokenizer_comments *comments = current_comments(tok);
70+
tokenizer_comments *comments = tok_mode->comments;
8371
PyObject *res;
8472
if (comments != NULL && comments->count > 0) {
8573
Py_ssize_t stripped_size = expr_len;
@@ -130,9 +118,10 @@ _PyLexer_set_ftstring_expr_metadata(struct tok_state *tok, struct token *token)
130118
void
131119
_PyLexer_begin_ftstring_expr(struct tok_state *tok)
132120
{
133-
_PyLexer_CurrentMode(tok)->expr_span = (_PyTok_Span){
121+
tokenizer_mode *mode = _PyLexer_CurrentMode(tok);
122+
mode->expr_span = (_PyTok_Span){
134123
_PyLexer_BufferOffset(tok, tok->cur), -1};
135-
tokenizer_comments *comments = current_comments(tok);
124+
tokenizer_comments *comments = mode->comments;
136125
if (comments != NULL) {
137126
comments->count = 0;
138127
}
@@ -411,11 +400,6 @@ _PyLexer_get_fstring_mode(struct tok_state *tok, tokenizer_mode* current_tok, st
411400

412401
p_start = tok->start;
413402
p_end = tok->cur;
414-
tokenizer_comments *comments = current_comments(tok);
415-
if (comments != NULL) {
416-
tok->ftstring_comments = comments->previous;
417-
PyMem_Free(comments);
418-
}
419403
_PyLexer_PopMode(tok);
420404
return MAKE_TOKEN(FTSTRING_END(current_tok));
421405

0 commit comments

Comments
 (0)