Skip to content

Commit f933782

Browse files
committed
gh-153568: Don't materialize parser token text that is never read
Only tokens whose text is actually consumed get a bytes object; operators and structural tokens no longer allocate one.
1 parent e2118b0 commit f933782

2 files changed

Lines changed: 40 additions & 6 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Speed up the parser by not materializing the text of tokens whose text is
2+
never read.

Parser/pegen.c

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -189,18 +189,50 @@ _get_keyword_or_name_type(Parser *p, struct token *new_token)
189189
return NAME;
190190
}
191191

192+
// Token types whose text is consumed by grammar actions or helpers, other
193+
// than NAME-derived tokens (identifiers and keywords), which always keep
194+
// their text: error actions may print keyword text (e.g. invalid_kwarg's
195+
// "cannot assign to True"). For every other type the token text is never
196+
// read again, so materializing a PyBytes for it is wasted work.
197+
static inline int
198+
token_needs_text(int type)
199+
{
200+
switch (type) {
201+
case NAME:
202+
case NUMBER:
203+
case STRING:
204+
case FSTRING_START:
205+
case FSTRING_MIDDLE:
206+
case FSTRING_END:
207+
case TSTRING_START:
208+
case TSTRING_MIDDLE:
209+
case TSTRING_END:
210+
case TYPE_COMMENT:
211+
case NOTEQUAL: // _PyPegen_check_barry_as_flufl() reads its text
212+
return 1;
213+
default:
214+
return 0;
215+
}
216+
}
217+
192218
static int
193219
initialize_token(Parser *p, Token *parser_token, struct token *new_token, int token_type) {
194220
assert(parser_token != NULL);
195221

196222
parser_token->type = (token_type == NAME) ? _get_keyword_or_name_type(p, new_token) : token_type;
197-
parser_token->bytes = PyBytes_FromStringAndSize(new_token->start, new_token->end - new_token->start);
198-
if (parser_token->bytes == NULL) {
199-
return -1;
223+
if (token_type == NAME || token_needs_text(parser_token->type)) {
224+
parser_token->bytes = PyBytes_FromStringAndSize(
225+
new_token->start, new_token->end - new_token->start);
226+
if (parser_token->bytes == NULL) {
227+
return -1;
228+
}
229+
if (_PyArena_AddPyObject(p->arena, parser_token->bytes) < 0) {
230+
Py_DECREF(parser_token->bytes);
231+
return -1;
232+
}
200233
}
201-
if (_PyArena_AddPyObject(p->arena, parser_token->bytes) < 0) {
202-
Py_DECREF(parser_token->bytes);
203-
return -1;
234+
else {
235+
parser_token->bytes = NULL;
204236
}
205237

206238
parser_token->metadata = NULL;

0 commit comments

Comments
 (0)