Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Speed up the parser by not materializing the text of tokens whose text is
never read.
44 changes: 38 additions & 6 deletions Parser/pegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,18 +178,50 @@ _get_keyword_or_name_type(Parser *p, struct token *new_token)
return NAME;
}

// Token types whose text is consumed by grammar actions or helpers, other
// than NAME-derived tokens (identifiers and keywords), which always keep
// their text: error actions may print keyword text (e.g. invalid_kwarg's
// "cannot assign to True"). For every other type the token text is never
// read again, so materializing a PyBytes for it is wasted work.
static inline int
token_needs_text(int type)
{
switch (type) {
case NAME:
case NUMBER:
case STRING:
case FSTRING_START:
case FSTRING_MIDDLE:
case FSTRING_END:
case TSTRING_START:
case TSTRING_MIDDLE:
case TSTRING_END:
case TYPE_COMMENT:
case NOTEQUAL: // _PyPegen_check_barry_as_flufl() reads its text
return 1;
default:
return 0;
}
}

static int
initialize_token(Parser *p, Token *parser_token, struct token *new_token, int token_type) {
assert(parser_token != NULL);

parser_token->type = (token_type == NAME) ? _get_keyword_or_name_type(p, new_token) : token_type;
parser_token->bytes = PyBytes_FromStringAndSize(new_token->start, new_token->end - new_token->start);
if (parser_token->bytes == NULL) {
return -1;
if (token_needs_text(parser_token->type)) {
parser_token->bytes = PyBytes_FromStringAndSize(
new_token->start, new_token->end - new_token->start);
if (parser_token->bytes == NULL) {
return -1;
}
if (_PyArena_AddPyObject(p->arena, parser_token->bytes) < 0) {
Py_DECREF(parser_token->bytes);
return -1;
}
}
if (_PyArena_AddPyObject(p->arena, parser_token->bytes) < 0) {
Py_DECREF(parser_token->bytes);
return -1;
else {
parser_token->bytes = NULL;
}

parser_token->metadata = NULL;
Expand Down
Loading