mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 15:41:43 +00:00 
			
		
		
		
	Some incompatible changes had gone in, and the "ignore" lists weren't properly undated. This change fixes that. It's necessary prior to enabling test_check_c_globals, which I hope to do soon. Note that this does include moving last_resort_memory_error to PyInterpreterState. https://github.com/python/cpython/issues/90110
		
			
				
	
	
		
			131 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			131 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import re
 | 
						|
 | 
						|
from ._regexes import (
 | 
						|
    _ind,
 | 
						|
    STRING_LITERAL,
 | 
						|
    VAR_DECL as _VAR_DECL,
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
def log_match(group, m, depth_before=None, depth_after=None):
 | 
						|
    from . import _logger
 | 
						|
 | 
						|
    if m is not None:
 | 
						|
        text = m.group(0)
 | 
						|
        if text.startswith(('(', ')')) or text.endswith(('(', ')')):
 | 
						|
            _logger.debug(f'matched <{group}> ({text!r})')
 | 
						|
        else:
 | 
						|
            _logger.debug(f'matched <{group}> ({text})')
 | 
						|
 | 
						|
    elif depth_before is not None or depth_after is not None:
 | 
						|
        if depth_before is None:
 | 
						|
            depth_before = '???'
 | 
						|
        elif depth_after is None:
 | 
						|
            depth_after = '???'
 | 
						|
        _logger.log(1, f'depth: %s -> %s', depth_before, depth_after)
 | 
						|
 | 
						|
    else:
 | 
						|
        raise NotImplementedError('this should not have been hit')
 | 
						|
 | 
						|
 | 
						|
#############################
 | 
						|
# regex utils
 | 
						|
 | 
						|
def set_capture_group(pattern, group, *, strict=True):
 | 
						|
    old = f'(?:  # <{group}>'
 | 
						|
    if strict and f'(?:  # <{group}>' not in pattern:
 | 
						|
        raise ValueError(f'{old!r} not found in pattern')
 | 
						|
    return pattern.replace(old, f'(  # <{group}>', 1)
 | 
						|
 | 
						|
 | 
						|
def set_capture_groups(pattern, groups, *, strict=True):
 | 
						|
    for group in groups:
 | 
						|
        pattern = set_capture_group(pattern, group, strict=strict)
 | 
						|
    return pattern
 | 
						|
 | 
						|
 | 
						|
#############################
 | 
						|
# syntax-related utils
 | 
						|
 | 
						|
_PAREN_RE = re.compile(rf'''
 | 
						|
    (?:
 | 
						|
        (?:
 | 
						|
            [^'"()]*
 | 
						|
            {_ind(STRING_LITERAL, 3)}
 | 
						|
         )*
 | 
						|
        [^'"()]*
 | 
						|
        (?:
 | 
						|
            ( [(] )
 | 
						|
            |
 | 
						|
            ( [)] )
 | 
						|
         )
 | 
						|
     )
 | 
						|
    ''', re.VERBOSE)
 | 
						|
 | 
						|
 | 
						|
def match_paren(text, depth=0):
 | 
						|
    pos = 0
 | 
						|
    while (m := _PAREN_RE.match(text, pos)):
 | 
						|
        pos = m.end()
 | 
						|
        _open, _close = m.groups()
 | 
						|
        if _open:
 | 
						|
            depth += 1
 | 
						|
        else:  # _close
 | 
						|
            depth -= 1
 | 
						|
            if depth == 0:
 | 
						|
                return pos
 | 
						|
    else:
 | 
						|
        raise ValueError(f'could not find matching parens for {text!r}')
 | 
						|
 | 
						|
 | 
						|
VAR_DECL = set_capture_groups(_VAR_DECL, (
 | 
						|
    'STORAGE',
 | 
						|
    'TYPE_QUAL',
 | 
						|
    'TYPE_SPEC',
 | 
						|
    'DECLARATOR',
 | 
						|
    'IDENTIFIER',
 | 
						|
    'WRAPPED_IDENTIFIER',
 | 
						|
    'FUNC_IDENTIFIER',
 | 
						|
))
 | 
						|
 | 
						|
 | 
						|
def parse_var_decl(decl):
 | 
						|
    m = re.match(VAR_DECL, decl, re.VERBOSE)
 | 
						|
    (storage, typequal, typespec, declarator,
 | 
						|
     name,
 | 
						|
     wrappedname,
 | 
						|
     funcptrname,
 | 
						|
     ) = m.groups()
 | 
						|
    if name:
 | 
						|
        kind = 'simple'
 | 
						|
    elif wrappedname:
 | 
						|
        kind = 'wrapped'
 | 
						|
        name = wrappedname
 | 
						|
    elif funcptrname:
 | 
						|
        kind = 'funcptr'
 | 
						|
        name = funcptrname
 | 
						|
    else:
 | 
						|
        raise NotImplementedError
 | 
						|
    abstract = declarator.replace(name, '')
 | 
						|
    vartype = {
 | 
						|
        'storage': storage,
 | 
						|
        'typequal': typequal,
 | 
						|
        'typespec': typespec,
 | 
						|
        'abstract': abstract,
 | 
						|
    }
 | 
						|
    return (kind, name, vartype)
 | 
						|
 | 
						|
 | 
						|
#############################
 | 
						|
# parser state utils
 | 
						|
 | 
						|
# XXX Drop this or use it!
 | 
						|
def iter_results(results):
 | 
						|
    if not results:
 | 
						|
        return
 | 
						|
    if callable(results):
 | 
						|
        results = results()
 | 
						|
 | 
						|
    for result, text in results():
 | 
						|
        if result:
 | 
						|
            yield result, text
 |