mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 21:51:50 +00:00 
			
		
		
		
	
		
			
	
	
		
			180 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			180 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|   | import re | ||
|  | 
 | ||
|  | from ._regexes import ( | ||
|  |     GLOBAL as _GLOBAL, | ||
|  | ) | ||
|  | from ._common import ( | ||
|  |     log_match, | ||
|  |     parse_var_decl, | ||
|  |     set_capture_groups, | ||
|  | ) | ||
|  | from ._compound_decl_body import DECL_BODY_PARSERS | ||
|  | #from ._func_body import parse_function_body | ||
|  | from ._func_body import parse_function_statics as parse_function_body | ||
|  | 
 | ||
|  | 
 | ||
|  | GLOBAL = set_capture_groups(_GLOBAL, ( | ||
|  |     'EMPTY', | ||
|  |     'COMPOUND_LEADING', | ||
|  |     'COMPOUND_KIND', | ||
|  |     'COMPOUND_NAME', | ||
|  |     'FORWARD_KIND', | ||
|  |     'FORWARD_NAME', | ||
|  |     'MAYBE_INLINE_ACTUAL', | ||
|  |     'TYPEDEF_DECL', | ||
|  |     'TYPEDEF_FUNC_PARAMS', | ||
|  |     'VAR_STORAGE', | ||
|  |     'FUNC_INLINE', | ||
|  |     'VAR_DECL', | ||
|  |     'FUNC_PARAMS', | ||
|  |     'FUNC_DELIM', | ||
|  |     'FUNC_LEGACY_PARAMS', | ||
|  |     'VAR_INIT', | ||
|  |     'VAR_ENDING', | ||
|  | )) | ||
|  | GLOBAL_RE = re.compile(rf'^ \s* {GLOBAL}', re.VERBOSE) | ||
|  | 
 | ||
|  | 
 | ||
|  | def parse_globals(source, anon_name): | ||
|  |     for srcinfo in source: | ||
|  |         m = GLOBAL_RE.match(srcinfo.text) | ||
|  |         if not m: | ||
|  |             # We need more text. | ||
|  |             continue | ||
|  |         for item in _parse_next(m, srcinfo, anon_name): | ||
|  |             if callable(item): | ||
|  |                 parse_body = item | ||
|  |                 yield from parse_body(source) | ||
|  |             else: | ||
|  |                 yield item | ||
|  |     else: | ||
|  |         # We ran out of lines. | ||
|  |         if srcinfo is not None: | ||
|  |             srcinfo.done() | ||
|  |         return | ||
|  | 
 | ||
|  | 
 | ||
|  | def _parse_next(m, srcinfo, anon_name): | ||
|  |     ( | ||
|  |      empty, | ||
|  |      # compound type decl (maybe inline) | ||
|  |      compound_leading, compound_kind, compound_name, | ||
|  |      forward_kind, forward_name, maybe_inline_actual, | ||
|  |      # typedef | ||
|  |      typedef_decl, typedef_func_params, | ||
|  |      # vars and funcs | ||
|  |      storage, func_inline, decl, | ||
|  |      func_params, func_delim, func_legacy_params, | ||
|  |      var_init, var_ending, | ||
|  |      ) = m.groups() | ||
|  |     remainder = srcinfo.text[m.end():] | ||
|  | 
 | ||
|  |     if empty: | ||
|  |         log_match('global empty', m) | ||
|  |         srcinfo.advance(remainder) | ||
|  | 
 | ||
|  |     elif maybe_inline_actual: | ||
|  |         log_match('maybe_inline_actual', m) | ||
|  |         # Ignore forward declarations. | ||
|  |         # XXX Maybe return them too (with an "isforward" flag)? | ||
|  |         if not maybe_inline_actual.strip().endswith(';'): | ||
|  |             remainder = maybe_inline_actual + remainder | ||
|  |         yield srcinfo.resolve(forward_kind, None, forward_name) | ||
|  |         if maybe_inline_actual.strip().endswith('='): | ||
|  |             # We use a dummy prefix for a fake typedef. | ||
|  |             # XXX Ideally this case would not be caught by MAYBE_INLINE_ACTUAL. | ||
|  |             _, name, data = parse_var_decl(f'{forward_kind} {forward_name} fake_typedef_{forward_name}') | ||
|  |             yield srcinfo.resolve('typedef', data, name, parent=None) | ||
|  |             remainder = f'{name} {remainder}' | ||
|  |         srcinfo.advance(remainder) | ||
|  | 
 | ||
|  |     elif compound_kind: | ||
|  |         kind = compound_kind | ||
|  |         name = compound_name or anon_name('inline-') | ||
|  |         # Immediately emit a forward declaration. | ||
|  |         yield srcinfo.resolve(kind, name=name, data=None) | ||
|  | 
 | ||
|  |         # un-inline the decl.  Note that it might not actually be inline. | ||
|  |         # We handle the case in the "maybe_inline_actual" branch. | ||
|  |         srcinfo.nest( | ||
|  |             remainder, | ||
|  |             f'{compound_leading or ""} {compound_kind} {name}', | ||
|  |         ) | ||
|  |         def parse_body(source): | ||
|  |             _parse_body = DECL_BODY_PARSERS[compound_kind] | ||
|  | 
 | ||
|  |             data = []  # members | ||
|  |             ident = f'{kind} {name}' | ||
|  |             for item in _parse_body(source, anon_name, ident): | ||
|  |                 if item.kind == 'field': | ||
|  |                     data.append(item) | ||
|  |                 else: | ||
|  |                     yield item | ||
|  |             # XXX Should "parent" really be None for inline type decls? | ||
|  |             yield srcinfo.resolve(kind, data, name, parent=None) | ||
|  | 
 | ||
|  |             srcinfo.resume() | ||
|  |         yield parse_body | ||
|  | 
 | ||
|  |     elif typedef_decl: | ||
|  |         log_match('typedef', m) | ||
|  |         kind = 'typedef' | ||
|  |         _, name, data = parse_var_decl(typedef_decl) | ||
|  |         if typedef_func_params: | ||
|  |             return_type = data | ||
|  |             # This matches the data for func declarations. | ||
|  |             data = { | ||
|  |                 'storage': None, | ||
|  |                 'inline': None, | ||
|  |                 'params': f'({typedef_func_params})', | ||
|  |                 'returntype': return_type, | ||
|  |                 'isforward': True, | ||
|  |             } | ||
|  |         yield srcinfo.resolve(kind, data, name, parent=None) | ||
|  |         srcinfo.advance(remainder) | ||
|  | 
 | ||
|  |     elif func_delim or func_legacy_params: | ||
|  |         log_match('function', m) | ||
|  |         kind = 'function' | ||
|  |         _, name, return_type = parse_var_decl(decl) | ||
|  |         func_params = func_params or func_legacy_params | ||
|  |         data = { | ||
|  |             'storage': storage, | ||
|  |             'inline': func_inline, | ||
|  |             'params': f'({func_params})', | ||
|  |             'returntype': return_type, | ||
|  |             'isforward': func_delim == ';', | ||
|  |         } | ||
|  | 
 | ||
|  |         yield srcinfo.resolve(kind, data, name, parent=None) | ||
|  |         srcinfo.advance(remainder) | ||
|  | 
 | ||
|  |         if func_delim == '{' or func_legacy_params: | ||
|  |             def parse_body(source): | ||
|  |                 yield from parse_function_body(source, name, anon_name) | ||
|  |             yield parse_body | ||
|  | 
 | ||
|  |     elif var_ending: | ||
|  |         log_match('global variable', m) | ||
|  |         kind = 'variable' | ||
|  |         _, name, vartype = parse_var_decl(decl) | ||
|  |         data = { | ||
|  |             'storage': storage, | ||
|  |             'vartype': vartype, | ||
|  |         } | ||
|  |         yield srcinfo.resolve(kind, data, name, parent=None) | ||
|  | 
 | ||
|  |         if var_ending == ',': | ||
|  |             # It was a multi-declaration, so queue up the next one. | ||
|  |             _, qual, typespec, _ = vartype.values() | ||
|  |             remainder = f'{storage or ""} {qual or ""} {typespec} {remainder}' | ||
|  |         srcinfo.advance(remainder) | ||
|  | 
 | ||
|  |         if var_init: | ||
|  |             _data = f'{name} = {var_init.strip()}' | ||
|  |             yield srcinfo.resolve('statement', _data, name=None) | ||
|  | 
 | ||
|  |     else: | ||
|  |         # This should be unreachable. | ||
|  |         raise NotImplementedError |