@@ -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+
192218static int
193219initialize_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