@@ -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+
181207static int
182208initialize_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