Skip to content

Commit c758acc

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 106eb53 commit c758acc

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
@@ -178,18 +178,50 @@ _get_keyword_or_name_type(Parser *p, struct token *new_token)
178178
return NAME;
179179
}
180180

181+
// Token types whose text is consumed by grammar actions or helpers, other
182+
// than NAME-derived tokens (identifiers and keywords), which always keep
183+
// their text: error actions may print keyword text (e.g. invalid_kwarg's
184+
// "cannot assign to True"). For every other type the token text is never
185+
// read again, so materializing a PyBytes for it is wasted work.
186+
static inline int
187+
token_needs_text(int type)
188+
{
189+
switch (type) {
190+
case NAME:
191+
case NUMBER:
192+
case STRING:
193+
case FSTRING_START:
194+
case FSTRING_MIDDLE:
195+
case FSTRING_END:
196+
case TSTRING_START:
197+
case TSTRING_MIDDLE:
198+
case TSTRING_END:
199+
case TYPE_COMMENT:
200+
case NOTEQUAL: // _PyPegen_check_barry_as_flufl() reads its text
201+
return 1;
202+
default:
203+
return 0;
204+
}
205+
}
206+
181207
static int
182208
initialize_token(Parser *p, Token *parser_token, struct token *new_token, int token_type) {
183209
assert(parser_token != NULL);
184210

185211
parser_token->type = (token_type == NAME) ? _get_keyword_or_name_type(p, new_token) : token_type;
186-
parser_token->bytes = PyBytes_FromStringAndSize(new_token->start, new_token->end - new_token->start);
187-
if (parser_token->bytes == NULL) {
188-
return -1;
212+
if (token_type == NAME || token_needs_text(parser_token->type)) {
213+
parser_token->bytes = PyBytes_FromStringAndSize(
214+
new_token->start, new_token->end - new_token->start);
215+
if (parser_token->bytes == NULL) {
216+
return -1;
217+
}
218+
if (_PyArena_AddPyObject(p->arena, parser_token->bytes) < 0) {
219+
Py_DECREF(parser_token->bytes);
220+
return -1;
221+
}
189222
}
190-
if (_PyArena_AddPyObject(p->arena, parser_token->bytes) < 0) {
191-
Py_DECREF(parser_token->bytes);
192-
return -1;
223+
else {
224+
parser_token->bytes = NULL;
193225
}
194226

195227
parser_token->metadata = NULL;

0 commit comments

Comments
 (0)