fixup! gh-153569: Add tokenizer source and cursor primitives · python/cpython@4b0454f · GitHub
Skip to content

Commit 4b0454f

Browse files
committed
fixup! gh-153569: Add tokenizer source and cursor primitives
1 parent 100072c commit 4b0454f

4 files changed

Lines changed: 43 additions & 22 deletions

File tree

Modules/_testinternalcapi/tokenizer.c

Lines changed: 10 additions & 2 deletions

Parser/tokenizer/cursor.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ typedef struct {
1212
int lineno;
1313
} _PyTok_Cursor;
1414

15+
/* Move to the start of a 1-based line. Both setters preserve the cursor on
16+
error. */
1517
PyAPI_FUNC(int) _PyTok_CursorSetLine(_PyTok_Cursor *, int);
16-
/* A line-boundary offset selects the following line. */
18+
/* Move to an offset. A line boundary selects the following line. */
1719
PyAPI_FUNC(int) _PyTok_CursorSetOffset(_PyTok_Cursor *, _PyTok_Off);
1820

1921
static inline void
@@ -24,7 +26,9 @@ _PyTok_CursorInit(_PyTok_Cursor *cursor, const _PyTok_SourceText *source)
2426
};
2527
}
2628

27-
/* EOF with pos before line_end reports byte-column overflow. */
29+
/* Read one byte from the current line, including its terminating newline.
30+
EOF marks the line boundary, not necessarily the end of the source. It is
31+
also returned if advancing would make the byte column unrepresentable. */
2832
static inline int
2933
_PyTok_CursorAdvance(_PyTok_Cursor *cursor)
3034
{
@@ -41,15 +45,18 @@ _PyTok_CursorAdvance(_PyTok_Cursor *cursor)
4145
return Py_CHARMASK(cursor->source->bytes[cursor->pos++]);
4246
}
4347

48+
/* Return the byte at a nonnegative distance within the current line, or EOF
49+
if the distance reaches or crosses the line boundary. */
4450
static inline int
4551
_PyTok_CursorPeek(const _PyTok_Cursor *cursor, int distance)
4652
{
4753
assert(cursor->source != NULL);
4854
assert(cursor->pos >= cursor->line_start);
4955
assert(cursor->pos <= cursor->line_end);
5056
assert(cursor->line_end <= cursor->source->len);
51-
if ((size_t)distance >=
52-
(size_t)(cursor->line_end - cursor->pos)) {
57+
assert(distance >= 0);
58+
if (distance < 0 ||
59+
distance >= cursor->line_end - cursor->pos) {
5360
return EOF;
5461
}
5562
return Py_CHARMASK(cursor->source->bytes[cursor->pos + distance]);

Parser/tokenizer/source.c

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,8 @@ reserve_checkpoints(_PyTok_SourceText *source, int needed)
7575
PyErr_NoMemory();
7676
return -1;
7777
}
78-
if ((size_t)cap > (size_t)PY_SSIZE_T_MAX /
79-
sizeof(*source->line_checkpoints)) {
80-
PyErr_NoMemory();
81-
return -1;
82-
}
83-
_PyTok_Off *checkpoints = PyMem_Realloc(
84-
source->line_checkpoints,
85-
(size_t)cap * sizeof(*source->line_checkpoints));
78+
_PyTok_Off *checkpoints = source->line_checkpoints;
79+
PyMem_Resize(checkpoints, _PyTok_Off, cap);
8680
if (checkpoints == NULL) {
8781
PyErr_NoMemory();
8882
return -1;
@@ -190,10 +184,11 @@ _PyTok_SourceSpanView(const _PyTok_SourceText *source, _PyTok_Span span,
190184
return source->bytes == NULL ? "" : source->bytes + span.start;
191185
}
192186

193-
static int
194-
line_is_implicit(const _PyTok_SourceText *source, int lineno)
187+
int
188+
_PyTok_SourceLineIsImplicit(const _PyTok_SourceText *source, int lineno)
195189
{
196-
if ((lineno - 1) / 8 >= source->implicit_cap) {
190+
if (lineno < 1 || lineno > source->nlines ||
191+
(lineno - 1) / 8 >= source->implicit_cap) {
197192
return 0;
198193
}
199194
return (source->implicit_lines[(lineno - 1) / 8] >>
@@ -251,7 +246,7 @@ _PyTok_SourceLine(const _PyTok_SourceText *source, int lineno,
251246
*line = (_PyTok_Line){
252247
.start = start,
253248
.end = end,
254-
.implicit_newline = line_is_implicit(source, lineno),
249+
.implicit_newline = _PyTok_SourceLineIsImplicit(source, lineno),
255250
.contains_nul = memchr(
256251
source->bytes + start, 0, end - start) != NULL,
257252
};

Parser/tokenizer/source.h

Lines changed: 15 additions & 4 deletions

0 commit comments

Comments
 (0)