@@ -628,35 +628,11 @@ _PyPegen_new_identifier(Parser *p, const char *n)
628628 return NULL ;
629629}
630630
631- static expr_ty
632- name_from_identifier (Parser * p , Token * t , PyObject * id )
633- {
634- expr_ty result = _PyAST_Name (id , Load , t -> lineno , t -> col_offset ,
635- t -> end_lineno , t -> end_col_offset , p -> arena );
636- if (result != NULL && _PyPegen_insert_memo (p , p -> mark - 1 , NAME , result ) < 0 ) {
637- p -> error_indicator = 1 ;
638- return NULL ;
639- }
640- return result ;
641- }
642-
643- static expr_ty
644- _PyPegen_name_from_token (Parser * p , Token * t )
631+ // Return an arena-owned identifier; callers borrow the reference.
632+ static PyObject *
633+ get_cached_identifier (Parser * p , PyObject * bytes )
645634{
646- if (t == NULL ) {
647- return NULL ;
648- }
649- // Reuse the AST node when backtracking revisits this token. Memo lookup
650- // starts before the token and restores the position after it on a hit.
651- // Token kinds can be memo keys: generated grammar rule IDs start at 1000.
652- int mark = p -> mark - 1 ;
653- p -> mark = mark ;
654- expr_ty cached = NULL ;
655- if (_PyPegen_is_memoized (p , NAME , & cached )) {
656- return cached ;
657- }
658- p -> mark = mark + 1 ;
659- const char * s = PyBytes_AsString (t -> bytes );
635+ const char * s = PyBytes_AsString (bytes );
660636 if (!s ) {
661637 p -> error_indicator = 1 ;
662638 return NULL ;
@@ -666,8 +642,8 @@ _PyPegen_name_from_token(Parser *p, Token* t)
666642 // arena-owned token bytes and values are arena-owned interned strings,
667643 // so borrowed references are valid for the lifetime of the parse
668644 // (including the second error pass, which reuses parser and arena).
669- Py_ssize_t len = PyBytes_GET_SIZE (t -> bytes );
670- Py_hash_t hash = PyObject_Hash (t -> bytes );
645+ Py_ssize_t len = PyBytes_GET_SIZE (bytes );
646+ Py_hash_t hash = PyObject_Hash (bytes );
671647 if (hash == -1 ) {
672648 p -> error_indicator = 1 ;
673649 return NULL ;
@@ -678,7 +654,7 @@ _PyPegen_name_from_token(Parser *p, Token* t)
678654 IDENTIFIER_CACHE_SIZE , sizeof (* p -> identifier_cache ));
679655 if (p -> identifier_cache == NULL ) {
680656 p -> error_indicator = 1 ;
681- return ( expr_ty ) PyErr_NoMemory ();
657+ return PyErr_NoMemory ();
682658 }
683659 }
684660 IdentifierCacheEntry * free_slot = NULL ;
@@ -693,7 +669,7 @@ _PyPegen_name_from_token(Parser *p, Token* t)
693669 if (entry -> hash == hash && entry -> len == len &&
694670 memcmp (entry -> key , s , len ) == 0 )
695671 {
696- return name_from_identifier ( p , t , entry -> value ) ;
672+ return entry -> value ;
697673 }
698674 }
699675 PyObject * id = _PyPegen_new_identifier (p , s );
@@ -707,7 +683,36 @@ _PyPegen_name_from_token(Parser *p, Token* t)
707683 free_slot -> hash = hash ;
708684 free_slot -> value = id ;
709685 }
710- return name_from_identifier (p , t , id );
686+ return id ;
687+ }
688+
689+ static expr_ty
690+ _PyPegen_name_from_token (Parser * p , Token * t )
691+ {
692+ if (t == NULL ) {
693+ return NULL ;
694+ }
695+ // Reuse the AST node when backtracking revisits this token. Memo lookup
696+ // starts before the token and restores the position after it on a hit.
697+ // Token kinds can be memo keys: generated grammar rule IDs start at 1000.
698+ int mark = p -> mark - 1 ;
699+ p -> mark = mark ;
700+ expr_ty cached = NULL ;
701+ if (_PyPegen_is_memoized (p , NAME , & cached )) {
702+ return cached ;
703+ }
704+ p -> mark = mark + 1 ;
705+ PyObject * id = get_cached_identifier (p , t -> bytes );
706+ if (id == NULL ) {
707+ return NULL ;
708+ }
709+ expr_ty result = _PyAST_Name (id , Load , t -> lineno , t -> col_offset ,
710+ t -> end_lineno , t -> end_col_offset , p -> arena );
711+ if (result != NULL && _PyPegen_insert_memo (p , mark , NAME , result ) < 0 ) {
712+ p -> error_indicator = 1 ;
713+ return NULL ;
714+ }
715+ return result ;
711716}
712717
713718expr_ty
0 commit comments