Path: blob/main/Tools/c-analyzer/c_parser/parser/_global.py
12 views
import re12from ._regexes import (3GLOBAL as _GLOBAL,4)5from ._common import (6log_match,7parse_var_decl,8set_capture_groups,9)10from ._compound_decl_body import DECL_BODY_PARSERS11from ._func_body import parse_function_statics as parse_function_body121314GLOBAL = set_capture_groups(_GLOBAL, (15'EMPTY',16'COMPOUND_LEADING',17'COMPOUND_KIND',18'COMPOUND_NAME',19'FORWARD_KIND',20'FORWARD_NAME',21'MAYBE_INLINE_ACTUAL',22'TYPEDEF_DECL',23'TYPEDEF_FUNC_PARAMS',24'VAR_STORAGE',25'FUNC_INLINE',26'VAR_DECL',27'FUNC_PARAMS',28'FUNC_DELIM',29'FUNC_LEGACY_PARAMS',30'VAR_INIT',31'VAR_ENDING',32))33GLOBAL_RE = re.compile(rf'^ \s* {GLOBAL}', re.VERBOSE)343536def parse_globals(source, anon_name):37for srcinfo in source:38m = GLOBAL_RE.match(srcinfo.text)39if not m:40# We need more text.41continue42for item in _parse_next(m, srcinfo, anon_name):43if callable(item):44parse_body = item45yield from parse_body(source)46else:47yield item48else:49# We ran out of lines.50if srcinfo is not None:51srcinfo.done()52return535455def _parse_next(m, srcinfo, anon_name):56(57empty,58# compound type decl (maybe inline)59compound_leading, compound_kind, compound_name,60forward_kind, forward_name, maybe_inline_actual,61# typedef62typedef_decl, typedef_func_params,63# vars and funcs64storage, func_inline, decl,65func_params, func_delim, func_legacy_params,66var_init, var_ending,67) = m.groups()68remainder = srcinfo.text[m.end():]6970if empty:71log_match('global empty', m)72srcinfo.advance(remainder)7374elif maybe_inline_actual:75log_match('maybe_inline_actual', m)76# Ignore forward declarations.77# XXX Maybe return them too (with an "isforward" flag)?78if not maybe_inline_actual.strip().endswith(';'):79remainder = maybe_inline_actual + remainder80yield srcinfo.resolve(forward_kind, None, forward_name)81if maybe_inline_actual.strip().endswith('='):82# We use a dummy prefix for a fake typedef.83# XXX Ideally this case would not be caught by MAYBE_INLINE_ACTUAL.84_, name, data = parse_var_decl(f'{forward_kind} {forward_name} fake_typedef_{forward_name}')85yield srcinfo.resolve('typedef', data, name, parent=None)86remainder = f'{name} {remainder}'87srcinfo.advance(remainder)8889elif compound_kind:90kind = compound_kind91name = compound_name or anon_name('inline-')92# Immediately emit a forward declaration.93yield srcinfo.resolve(kind, name=name, data=None)9495# un-inline the decl. Note that it might not actually be inline.96# We handle the case in the "maybe_inline_actual" branch.97srcinfo.nest(98remainder,99f'{compound_leading or ""} {compound_kind} {name}',100)101def parse_body(source):102_parse_body = DECL_BODY_PARSERS[compound_kind]103104data = [] # members105ident = f'{kind} {name}'106for item in _parse_body(source, anon_name, ident):107if item.kind == 'field':108data.append(item)109else:110yield item111# XXX Should "parent" really be None for inline type decls?112yield srcinfo.resolve(kind, data, name, parent=None)113114srcinfo.resume()115yield parse_body116117elif typedef_decl:118log_match('typedef', m)119kind = 'typedef'120_, name, data = parse_var_decl(typedef_decl)121if typedef_func_params:122return_type = data123# This matches the data for func declarations.124data = {125'storage': None,126'inline': None,127'params': f'({typedef_func_params})',128'returntype': return_type,129'isforward': True,130}131yield srcinfo.resolve(kind, data, name, parent=None)132srcinfo.advance(remainder)133134elif func_delim or func_legacy_params:135log_match('function', m)136kind = 'function'137_, name, return_type = parse_var_decl(decl)138func_params = func_params or func_legacy_params139data = {140'storage': storage,141'inline': func_inline,142'params': f'({func_params})',143'returntype': return_type,144'isforward': func_delim == ';',145}146147yield srcinfo.resolve(kind, data, name, parent=None)148srcinfo.advance(remainder)149150if func_delim == '{' or func_legacy_params:151def parse_body(source):152yield from parse_function_body(source, name, anon_name)153yield parse_body154155elif var_ending:156log_match('global variable', m)157kind = 'variable'158_, name, vartype = parse_var_decl(decl)159data = {160'storage': storage,161'vartype': vartype,162}163yield srcinfo.resolve(kind, data, name, parent=None)164165if var_ending == ',':166# It was a multi-declaration, so queue up the next one.167_, qual, typespec, _ = vartype.values()168remainder = f'{storage or ""} {qual or ""} {typespec} {remainder}'169srcinfo.advance(remainder)170171if var_init:172_data = f'{name} = {var_init.strip()}'173yield srcinfo.resolve('statement', _data, name=None)174175else:176# This should be unreachable.177raise NotImplementedError178179180