(root)/
Python-3.11.7/
Tools/
c-analyzer/
c_parser/
parser/
_compound_decl_body.py
       1  import re
       2  
       3  from ._regexes import (
       4      STRUCT_MEMBER_DECL as _STRUCT_MEMBER_DECL,
       5      ENUM_MEMBER_DECL as _ENUM_MEMBER_DECL,
       6  )
       7  from ._common import (
       8      log_match,
       9      parse_var_decl,
      10      set_capture_groups,
      11  )
      12  
      13  
      14  #############################
      15  # struct / union
      16  
      17  STRUCT_MEMBER_DECL = set_capture_groups(_STRUCT_MEMBER_DECL, (
      18      'COMPOUND_TYPE_KIND',
      19      'COMPOUND_TYPE_NAME',
      20      'SPECIFIER_QUALIFIER',
      21      'DECLARATOR',
      22      'SIZE',
      23      'ENDING',
      24      'CLOSE',
      25  ))
      26  STRUCT_MEMBER_RE = re.compile(rf'^ \s* {STRUCT_MEMBER_DECL}', re.VERBOSE)
      27  
      28  
      29  def parse_struct_body(source, anon_name, parent):
      30      done = False
      31      while not done:
      32          done = True
      33          for srcinfo in source:
      34              m = STRUCT_MEMBER_RE.match(srcinfo.text)
      35              if m:
      36                  break
      37          else:
      38              # We ran out of lines.
      39              if srcinfo is not None:
      40                  srcinfo.done()
      41              return
      42          for item in _parse_struct_next(m, srcinfo, anon_name, parent):
      43              if callable(item):
      44                  parse_body = item
      45                  yield from parse_body(source)
      46              else:
      47                  yield item
      48              done = False
      49  
      50  
      51  def _parse_struct_next(m, srcinfo, anon_name, parent):
      52      (inline_kind, inline_name,
      53       qualspec, declarator,
      54       size,
      55       ending,
      56       close,
      57       ) = m.groups()
      58      remainder = srcinfo.text[m.end():]
      59  
      60      if close:
      61          log_match('compound close', m)
      62          srcinfo.advance(remainder)
      63  
      64      elif inline_kind:
      65          log_match('compound inline', m)
      66          kind = inline_kind
      67          name = inline_name or anon_name('inline-')
      68          # Immediately emit a forward declaration.
      69          yield srcinfo.resolve(kind, name=name, data=None)
      70  
      71          # un-inline the decl.  Note that it might not actually be inline.
      72          # We handle the case in the "maybe_inline_actual" branch.
      73          srcinfo.nest(
      74              remainder,
      75              f'{kind} {name}',
      76          )
      77          def parse_body(source):
      78              _parse_body = DECL_BODY_PARSERS[kind]
      79  
      80              data = []  # members
      81              ident = f'{kind} {name}'
      82              for item in _parse_body(source, anon_name, ident):
      83                  if item.kind == 'field':
      84                      data.append(item)
      85                  else:
      86                      yield item
      87              # XXX Should "parent" really be None for inline type decls?
      88              yield srcinfo.resolve(kind, data, name, parent=None)
      89  
      90              srcinfo.resume()
      91          yield parse_body
      92  
      93      else:
      94          # not inline (member)
      95          log_match('compound member', m)
      96          if qualspec:
      97              _, name, data = parse_var_decl(f'{qualspec} {declarator}')
      98              if not name:
      99                  name = anon_name('struct-field-')
     100              if size:
     101  #                data = (data, size)
     102                  data['size'] = int(size) if size.isdigit() else size
     103          else:
     104              # This shouldn't happen (we expect each field to have a name).
     105              raise NotImplementedError
     106              name = sized_name or anon_name('struct-field-')
     107              data = int(size)
     108  
     109          yield srcinfo.resolve('field', data, name, parent)  # XXX Restart?
     110          if ending == ',':
     111              remainder = rf'{qualspec} {remainder}'
     112          srcinfo.advance(remainder)
     113  
     114  
     115  #############################
     116  # enum
     117  
     118  ENUM_MEMBER_DECL = set_capture_groups(_ENUM_MEMBER_DECL, (
     119      'CLOSE',
     120      'NAME',
     121      'INIT',
     122      'ENDING',
     123  ))
     124  ENUM_MEMBER_RE = re.compile(rf'{ENUM_MEMBER_DECL}', re.VERBOSE)
     125  
     126  
     127  def parse_enum_body(source, _anon_name, _parent):
     128      ending = None
     129      while ending != '}':
     130          for srcinfo in source:
     131              m = ENUM_MEMBER_RE.match(srcinfo.text)
     132              if m:
     133                  break
     134          else:
     135              # We ran out of lines.
     136              if srcinfo is not None:
     137                  srcinfo.done()
     138              return
     139          remainder = srcinfo.text[m.end():]
     140  
     141          (close,
     142           name, init, ending,
     143           ) = m.groups()
     144          if close:
     145              ending = '}'
     146          else:
     147              data = init
     148              yield srcinfo.resolve('field', data, name, _parent)
     149          srcinfo.advance(remainder)
     150  
     151  
     152  #############################
     153  
     154  DECL_BODY_PARSERS = {
     155      'struct': parse_struct_body,
     156      'union': parse_struct_body,
     157      'enum': parse_enum_body,
     158  }