Path: blob/main/Tools/c-analyzer/c_parser/parser/_compound_decl_body.py
12 views
import re12from ._regexes import (3STRUCT_MEMBER_DECL as _STRUCT_MEMBER_DECL,4ENUM_MEMBER_DECL as _ENUM_MEMBER_DECL,5)6from ._common import (7log_match,8parse_var_decl,9set_capture_groups,10)111213#############################14# struct / union1516STRUCT_MEMBER_DECL = set_capture_groups(_STRUCT_MEMBER_DECL, (17'COMPOUND_TYPE_KIND',18'COMPOUND_TYPE_NAME',19'SPECIFIER_QUALIFIER',20'DECLARATOR',21'SIZE',22'ENDING',23'CLOSE',24))25STRUCT_MEMBER_RE = re.compile(rf'^ \s* {STRUCT_MEMBER_DECL}', re.VERBOSE)262728def parse_struct_body(source, anon_name, parent):29done = False30while not done:31done = True32for srcinfo in source:33m = STRUCT_MEMBER_RE.match(srcinfo.text)34if m:35break36else:37# We ran out of lines.38if srcinfo is not None:39srcinfo.done()40return41for item in _parse_struct_next(m, srcinfo, anon_name, parent):42if callable(item):43parse_body = item44yield from parse_body(source)45else:46yield item47done = False484950def _parse_struct_next(m, srcinfo, anon_name, parent):51(inline_kind, inline_name,52qualspec, declarator,53size,54ending,55close,56) = m.groups()57remainder = srcinfo.text[m.end():]5859if close:60log_match('compound close', m)61srcinfo.advance(remainder)6263elif inline_kind:64log_match('compound inline', m)65kind = inline_kind66name = inline_name or anon_name('inline-')67# Immediately emit a forward declaration.68yield srcinfo.resolve(kind, name=name, data=None)6970# un-inline the decl. Note that it might not actually be inline.71# We handle the case in the "maybe_inline_actual" branch.72srcinfo.nest(73remainder,74f'{kind} {name}',75)76def parse_body(source):77_parse_body = DECL_BODY_PARSERS[kind]7879data = [] # members80ident = f'{kind} {name}'81for item in _parse_body(source, anon_name, ident):82if item.kind == 'field':83data.append(item)84else:85yield item86# XXX Should "parent" really be None for inline type decls?87yield srcinfo.resolve(kind, data, name, parent=None)8889srcinfo.resume()90yield parse_body9192else:93# not inline (member)94log_match('compound member', m)95if qualspec:96_, name, data = parse_var_decl(f'{qualspec} {declarator}')97if not name:98name = anon_name('struct-field-')99if size:100# data = (data, size)101data['size'] = int(size) if size.isdigit() else size102else:103# This shouldn't happen (we expect each field to have a name).104raise NotImplementedError105name = sized_name or anon_name('struct-field-')106data = int(size)107108yield srcinfo.resolve('field', data, name, parent) # XXX Restart?109if ending == ',':110remainder = rf'{qualspec} {remainder}'111srcinfo.advance(remainder)112113114#############################115# enum116117ENUM_MEMBER_DECL = set_capture_groups(_ENUM_MEMBER_DECL, (118'CLOSE',119'NAME',120'INIT',121'ENDING',122))123ENUM_MEMBER_RE = re.compile(rf'{ENUM_MEMBER_DECL}', re.VERBOSE)124125126def parse_enum_body(source, _anon_name, _parent):127ending = None128while ending != '}':129for srcinfo in source:130m = ENUM_MEMBER_RE.match(srcinfo.text)131if m:132break133else:134# We ran out of lines.135if srcinfo is not None:136srcinfo.done()137return138remainder = srcinfo.text[m.end():]139140(close,141name, init, ending,142) = m.groups()143if close:144ending = '}'145else:146data = init147yield srcinfo.resolve('field', data, name, _parent)148srcinfo.advance(remainder)149150151#############################152153DECL_BODY_PARSERS = {154'struct': parse_struct_body,155'union': parse_struct_body,156'enum': parse_enum_body,157}158159160