@@ -603,12 +603,32 @@ _PyPegen_new_identifier(Parser *p, const char *n)
603603 return NULL ;
604604}
605605
606+ static expr_ty
607+ name_from_identifier (Parser * p , Token * t , PyObject * id )
608+ {
609+ expr_ty result = _PyAST_Name (id , Load , t -> lineno , t -> col_offset ,
610+ t -> end_lineno , t -> end_col_offset , p -> arena );
611+ if (result != NULL && _PyPegen_insert_memo (p , p -> mark - 1 , NAME , result ) < 0 ) {
612+ p -> error_indicator = 1 ;
613+ return NULL ;
614+ }
615+ return result ;
616+ }
617+
606618static expr_ty
607619_PyPegen_name_from_token (Parser * p , Token * t )
608620{
609621 if (t == NULL ) {
610622 return NULL ;
611623 }
624+ // Token kinds can be memo keys: generated grammar rule IDs start at 1000.
625+ int mark = p -> mark - 1 ;
626+ p -> mark = mark ;
627+ expr_ty cached = NULL ;
628+ if (_PyPegen_is_memoized (p , NAME , & cached )) {
629+ return cached ;
630+ }
631+ p -> mark = mark + 1 ;
612632 const char * s = PyBytes_AsString (t -> bytes );
613633 if (!s ) {
614634 p -> error_indicator = 1 ;
@@ -645,8 +665,7 @@ _PyPegen_name_from_token(Parser *p, Token* t)
645665 if (entry -> hash == hash && entry -> len == len &&
646666 memcmp (entry -> key , s , len ) == 0 )
647667 {
648- return _PyAST_Name (entry -> value , Load , t -> lineno , t -> col_offset ,
649- t -> end_lineno , t -> end_col_offset , p -> arena );
668+ return name_from_identifier (p , t , entry -> value );
650669 }
651670 }
652671 PyObject * id = _PyPegen_new_identifier (p , s );
@@ -660,8 +679,7 @@ _PyPegen_name_from_token(Parser *p, Token* t)
660679 free_slot -> hash = hash ;
661680 free_slot -> value = id ;
662681 }
663- return _PyAST_Name (id , Load , t -> lineno , t -> col_offset , t -> end_lineno ,
664- t -> end_col_offset , p -> arena );
682+ return name_from_identifier (p , t , id );
665683}
666684
667685expr_ty
0 commit comments