(root)/
Python-3.11.7/
Tools/
c-analyzer/
c_parser/
parser/
_global.py
       1  import re
       2  
       3  from ._regexes import (
       4      GLOBAL as _GLOBAL,
       5  )
       6  from ._common import (
       7      log_match,
       8      parse_var_decl,
       9      set_capture_groups,
      10  )
      11  from ._compound_decl_body import DECL_BODY_PARSERS
      12  #from ._func_body import parse_function_body
      13  from ._func_body import parse_function_statics as parse_function_body
      14  
      15  
      16  GLOBAL = set_capture_groups(_GLOBAL, (
      17      'EMPTY',
      18      'COMPOUND_LEADING',
      19      'COMPOUND_KIND',
      20      'COMPOUND_NAME',
      21      'FORWARD_KIND',
      22      'FORWARD_NAME',
      23      'MAYBE_INLINE_ACTUAL',
      24      'TYPEDEF_DECL',
      25      'TYPEDEF_FUNC_PARAMS',
      26      'VAR_STORAGE',
      27      'FUNC_INLINE',
      28      'VAR_DECL',
      29      'FUNC_PARAMS',
      30      'FUNC_DELIM',
      31      'FUNC_LEGACY_PARAMS',
      32      'VAR_INIT',
      33      'VAR_ENDING',
      34  ))
      35  GLOBAL_RE = re.compile(rf'^ \s* {GLOBAL}', re.VERBOSE)
      36  
      37  
      38  def parse_globals(source, anon_name):
      39      for srcinfo in source:
      40          m = GLOBAL_RE.match(srcinfo.text)
      41          if not m:
      42              # We need more text.
      43              continue
      44          for item in _parse_next(m, srcinfo, anon_name):
      45              if callable(item):
      46                  parse_body = item
      47                  yield from parse_body(source)
      48              else:
      49                  yield item
      50      else:
      51          # We ran out of lines.
      52          if srcinfo is not None:
      53              srcinfo.done()
      54          return
      55  
      56  
      57  def _parse_next(m, srcinfo, anon_name):
      58      (
      59       empty,
      60       # compound type decl (maybe inline)
      61       compound_leading, compound_kind, compound_name,
      62       forward_kind, forward_name, maybe_inline_actual,
      63       # typedef
      64       typedef_decl, typedef_func_params,
      65       # vars and funcs
      66       storage, func_inline, decl,
      67       func_params, func_delim, func_legacy_params,
      68       var_init, var_ending,
      69       ) = m.groups()
      70      remainder = srcinfo.text[m.end():]
      71  
      72      if empty:
      73          log_match('global empty', m)
      74          srcinfo.advance(remainder)
      75  
      76      elif maybe_inline_actual:
      77          log_match('maybe_inline_actual', m)
      78          # Ignore forward declarations.
      79          # XXX Maybe return them too (with an "isforward" flag)?
      80          if not maybe_inline_actual.strip().endswith(';'):
      81              remainder = maybe_inline_actual + remainder
      82          yield srcinfo.resolve(forward_kind, None, forward_name)
      83          if maybe_inline_actual.strip().endswith('='):
      84              # We use a dummy prefix for a fake typedef.
      85              # XXX Ideally this case would not be caught by MAYBE_INLINE_ACTUAL.
      86              _, name, data = parse_var_decl(f'{forward_kind} {forward_name} fake_typedef_{forward_name}')
      87              yield srcinfo.resolve('typedef', data, name, parent=None)
      88              remainder = f'{name} {remainder}'
      89          srcinfo.advance(remainder)
      90  
      91      elif compound_kind:
      92          kind = compound_kind
      93          name = compound_name or anon_name('inline-')
      94          # Immediately emit a forward declaration.
      95          yield srcinfo.resolve(kind, name=name, data=None)
      96  
      97          # un-inline the decl.  Note that it might not actually be inline.
      98          # We handle the case in the "maybe_inline_actual" branch.
      99          srcinfo.nest(
     100              remainder,
     101              f'{compound_leading or ""} {compound_kind} {name}',
     102          )
     103          def parse_body(source):
     104              _parse_body = DECL_BODY_PARSERS[compound_kind]
     105  
     106              data = []  # members
     107              ident = f'{kind} {name}'
     108              for item in _parse_body(source, anon_name, ident):
     109                  if item.kind == 'field':
     110                      data.append(item)
     111                  else:
     112                      yield item
     113              # XXX Should "parent" really be None for inline type decls?
     114              yield srcinfo.resolve(kind, data, name, parent=None)
     115  
     116              srcinfo.resume()
     117          yield parse_body
     118  
     119      elif typedef_decl:
     120          log_match('typedef', m)
     121          kind = 'typedef'
     122          _, name, data = parse_var_decl(typedef_decl)
     123          if typedef_func_params:
     124              return_type = data
     125              # This matches the data for func declarations.
     126              data = {
     127                  'storage': None,
     128                  'inline': None,
     129                  'params': f'({typedef_func_params})',
     130                  'returntype': return_type,
     131                  'isforward': True,
     132              }
     133          yield srcinfo.resolve(kind, data, name, parent=None)
     134          srcinfo.advance(remainder)
     135  
     136      elif func_delim or func_legacy_params:
     137          log_match('function', m)
     138          kind = 'function'
     139          _, name, return_type = parse_var_decl(decl)
     140          func_params = func_params or func_legacy_params
     141          data = {
     142              'storage': storage,
     143              'inline': func_inline,
     144              'params': f'({func_params})',
     145              'returntype': return_type,
     146              'isforward': func_delim == ';',
     147          }
     148  
     149          yield srcinfo.resolve(kind, data, name, parent=None)
     150          srcinfo.advance(remainder)
     151  
     152          if func_delim == '{' or func_legacy_params:
     153              def parse_body(source):
     154                  yield from parse_function_body(source, name, anon_name)
     155              yield parse_body
     156  
     157      elif var_ending:
     158          log_match('global variable', m)
     159          kind = 'variable'
     160          _, name, vartype = parse_var_decl(decl)
     161          data = {
     162              'storage': storage,
     163              'vartype': vartype,
     164          }
     165          yield srcinfo.resolve(kind, data, name, parent=None)
     166  
     167          if var_ending == ',':
     168              # It was a multi-declaration, so queue up the next one.
     169              _, qual, typespec, _ = vartype.values()
     170              remainder = f'{storage or ""} {qual or ""} {typespec} {remainder}'
     171          srcinfo.advance(remainder)
     172  
     173          if var_init:
     174              _data = f'{name} = {var_init.strip()}'
     175              yield srcinfo.resolve('statement', _data, name=None)
     176  
     177      else:
     178          # This should be unreachable.
     179          raise NotImplementedError