17db96d56Sopenharmony_ciimport re
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_cifrom ._regexes import (
47db96d56Sopenharmony_ci    GLOBAL as _GLOBAL,
57db96d56Sopenharmony_ci)
67db96d56Sopenharmony_cifrom ._common import (
77db96d56Sopenharmony_ci    log_match,
87db96d56Sopenharmony_ci    parse_var_decl,
97db96d56Sopenharmony_ci    set_capture_groups,
107db96d56Sopenharmony_ci)
117db96d56Sopenharmony_cifrom ._compound_decl_body import DECL_BODY_PARSERS
127db96d56Sopenharmony_ci#from ._func_body import parse_function_body
137db96d56Sopenharmony_cifrom ._func_body import parse_function_statics as parse_function_body
147db96d56Sopenharmony_ci
157db96d56Sopenharmony_ci
167db96d56Sopenharmony_ciGLOBAL = set_capture_groups(_GLOBAL, (
177db96d56Sopenharmony_ci    'EMPTY',
187db96d56Sopenharmony_ci    'COMPOUND_LEADING',
197db96d56Sopenharmony_ci    'COMPOUND_KIND',
207db96d56Sopenharmony_ci    'COMPOUND_NAME',
217db96d56Sopenharmony_ci    'FORWARD_KIND',
227db96d56Sopenharmony_ci    'FORWARD_NAME',
237db96d56Sopenharmony_ci    'MAYBE_INLINE_ACTUAL',
247db96d56Sopenharmony_ci    'TYPEDEF_DECL',
257db96d56Sopenharmony_ci    'TYPEDEF_FUNC_PARAMS',
267db96d56Sopenharmony_ci    'VAR_STORAGE',
277db96d56Sopenharmony_ci    'FUNC_INLINE',
287db96d56Sopenharmony_ci    'VAR_DECL',
297db96d56Sopenharmony_ci    'FUNC_PARAMS',
307db96d56Sopenharmony_ci    'FUNC_DELIM',
317db96d56Sopenharmony_ci    'FUNC_LEGACY_PARAMS',
327db96d56Sopenharmony_ci    'VAR_INIT',
337db96d56Sopenharmony_ci    'VAR_ENDING',
347db96d56Sopenharmony_ci))
357db96d56Sopenharmony_ciGLOBAL_RE = re.compile(rf'^ \s* {GLOBAL}', re.VERBOSE)
367db96d56Sopenharmony_ci
377db96d56Sopenharmony_ci
387db96d56Sopenharmony_cidef parse_globals(source, anon_name):
397db96d56Sopenharmony_ci    for srcinfo in source:
407db96d56Sopenharmony_ci        m = GLOBAL_RE.match(srcinfo.text)
417db96d56Sopenharmony_ci        if not m:
427db96d56Sopenharmony_ci            # We need more text.
437db96d56Sopenharmony_ci            continue
447db96d56Sopenharmony_ci        for item in _parse_next(m, srcinfo, anon_name):
457db96d56Sopenharmony_ci            if callable(item):
467db96d56Sopenharmony_ci                parse_body = item
477db96d56Sopenharmony_ci                yield from parse_body(source)
487db96d56Sopenharmony_ci            else:
497db96d56Sopenharmony_ci                yield item
507db96d56Sopenharmony_ci    else:
517db96d56Sopenharmony_ci        # We ran out of lines.
527db96d56Sopenharmony_ci        if srcinfo is not None:
537db96d56Sopenharmony_ci            srcinfo.done()
547db96d56Sopenharmony_ci        return
557db96d56Sopenharmony_ci
567db96d56Sopenharmony_ci
577db96d56Sopenharmony_cidef _parse_next(m, srcinfo, anon_name):
587db96d56Sopenharmony_ci    (
597db96d56Sopenharmony_ci     empty,
607db96d56Sopenharmony_ci     # compound type decl (maybe inline)
617db96d56Sopenharmony_ci     compound_leading, compound_kind, compound_name,
627db96d56Sopenharmony_ci     forward_kind, forward_name, maybe_inline_actual,
637db96d56Sopenharmony_ci     # typedef
647db96d56Sopenharmony_ci     typedef_decl, typedef_func_params,
657db96d56Sopenharmony_ci     # vars and funcs
667db96d56Sopenharmony_ci     storage, func_inline, decl,
677db96d56Sopenharmony_ci     func_params, func_delim, func_legacy_params,
687db96d56Sopenharmony_ci     var_init, var_ending,
697db96d56Sopenharmony_ci     ) = m.groups()
707db96d56Sopenharmony_ci    remainder = srcinfo.text[m.end():]
717db96d56Sopenharmony_ci
727db96d56Sopenharmony_ci    if empty:
737db96d56Sopenharmony_ci        log_match('global empty', m)
747db96d56Sopenharmony_ci        srcinfo.advance(remainder)
757db96d56Sopenharmony_ci
767db96d56Sopenharmony_ci    elif maybe_inline_actual:
777db96d56Sopenharmony_ci        log_match('maybe_inline_actual', m)
787db96d56Sopenharmony_ci        # Ignore forward declarations.
797db96d56Sopenharmony_ci        # XXX Maybe return them too (with an "isforward" flag)?
807db96d56Sopenharmony_ci        if not maybe_inline_actual.strip().endswith(';'):
817db96d56Sopenharmony_ci            remainder = maybe_inline_actual + remainder
827db96d56Sopenharmony_ci        yield srcinfo.resolve(forward_kind, None, forward_name)
837db96d56Sopenharmony_ci        if maybe_inline_actual.strip().endswith('='):
847db96d56Sopenharmony_ci            # We use a dummy prefix for a fake typedef.
857db96d56Sopenharmony_ci            # XXX Ideally this case would not be caught by MAYBE_INLINE_ACTUAL.
867db96d56Sopenharmony_ci            _, name, data = parse_var_decl(f'{forward_kind} {forward_name} fake_typedef_{forward_name}')
877db96d56Sopenharmony_ci            yield srcinfo.resolve('typedef', data, name, parent=None)
887db96d56Sopenharmony_ci            remainder = f'{name} {remainder}'
897db96d56Sopenharmony_ci        srcinfo.advance(remainder)
907db96d56Sopenharmony_ci
917db96d56Sopenharmony_ci    elif compound_kind:
927db96d56Sopenharmony_ci        kind = compound_kind
937db96d56Sopenharmony_ci        name = compound_name or anon_name('inline-')
947db96d56Sopenharmony_ci        # Immediately emit a forward declaration.
957db96d56Sopenharmony_ci        yield srcinfo.resolve(kind, name=name, data=None)
967db96d56Sopenharmony_ci
977db96d56Sopenharmony_ci        # un-inline the decl.  Note that it might not actually be inline.
987db96d56Sopenharmony_ci        # We handle the case in the "maybe_inline_actual" branch.
997db96d56Sopenharmony_ci        srcinfo.nest(
1007db96d56Sopenharmony_ci            remainder,
1017db96d56Sopenharmony_ci            f'{compound_leading or ""} {compound_kind} {name}',
1027db96d56Sopenharmony_ci        )
1037db96d56Sopenharmony_ci        def parse_body(source):
1047db96d56Sopenharmony_ci            _parse_body = DECL_BODY_PARSERS[compound_kind]
1057db96d56Sopenharmony_ci
1067db96d56Sopenharmony_ci            data = []  # members
1077db96d56Sopenharmony_ci            ident = f'{kind} {name}'
1087db96d56Sopenharmony_ci            for item in _parse_body(source, anon_name, ident):
1097db96d56Sopenharmony_ci                if item.kind == 'field':
1107db96d56Sopenharmony_ci                    data.append(item)
1117db96d56Sopenharmony_ci                else:
1127db96d56Sopenharmony_ci                    yield item
1137db96d56Sopenharmony_ci            # XXX Should "parent" really be None for inline type decls?
1147db96d56Sopenharmony_ci            yield srcinfo.resolve(kind, data, name, parent=None)
1157db96d56Sopenharmony_ci
1167db96d56Sopenharmony_ci            srcinfo.resume()
1177db96d56Sopenharmony_ci        yield parse_body
1187db96d56Sopenharmony_ci
1197db96d56Sopenharmony_ci    elif typedef_decl:
1207db96d56Sopenharmony_ci        log_match('typedef', m)
1217db96d56Sopenharmony_ci        kind = 'typedef'
1227db96d56Sopenharmony_ci        _, name, data = parse_var_decl(typedef_decl)
1237db96d56Sopenharmony_ci        if typedef_func_params:
1247db96d56Sopenharmony_ci            return_type = data
1257db96d56Sopenharmony_ci            # This matches the data for func declarations.
1267db96d56Sopenharmony_ci            data = {
1277db96d56Sopenharmony_ci                'storage': None,
1287db96d56Sopenharmony_ci                'inline': None,
1297db96d56Sopenharmony_ci                'params': f'({typedef_func_params})',
1307db96d56Sopenharmony_ci                'returntype': return_type,
1317db96d56Sopenharmony_ci                'isforward': True,
1327db96d56Sopenharmony_ci            }
1337db96d56Sopenharmony_ci        yield srcinfo.resolve(kind, data, name, parent=None)
1347db96d56Sopenharmony_ci        srcinfo.advance(remainder)
1357db96d56Sopenharmony_ci
1367db96d56Sopenharmony_ci    elif func_delim or func_legacy_params:
1377db96d56Sopenharmony_ci        log_match('function', m)
1387db96d56Sopenharmony_ci        kind = 'function'
1397db96d56Sopenharmony_ci        _, name, return_type = parse_var_decl(decl)
1407db96d56Sopenharmony_ci        func_params = func_params or func_legacy_params
1417db96d56Sopenharmony_ci        data = {
1427db96d56Sopenharmony_ci            'storage': storage,
1437db96d56Sopenharmony_ci            'inline': func_inline,
1447db96d56Sopenharmony_ci            'params': f'({func_params})',
1457db96d56Sopenharmony_ci            'returntype': return_type,
1467db96d56Sopenharmony_ci            'isforward': func_delim == ';',
1477db96d56Sopenharmony_ci        }
1487db96d56Sopenharmony_ci
1497db96d56Sopenharmony_ci        yield srcinfo.resolve(kind, data, name, parent=None)
1507db96d56Sopenharmony_ci        srcinfo.advance(remainder)
1517db96d56Sopenharmony_ci
1527db96d56Sopenharmony_ci        if func_delim == '{' or func_legacy_params:
1537db96d56Sopenharmony_ci            def parse_body(source):
1547db96d56Sopenharmony_ci                yield from parse_function_body(source, name, anon_name)
1557db96d56Sopenharmony_ci            yield parse_body
1567db96d56Sopenharmony_ci
1577db96d56Sopenharmony_ci    elif var_ending:
1587db96d56Sopenharmony_ci        log_match('global variable', m)
1597db96d56Sopenharmony_ci        kind = 'variable'
1607db96d56Sopenharmony_ci        _, name, vartype = parse_var_decl(decl)
1617db96d56Sopenharmony_ci        data = {
1627db96d56Sopenharmony_ci            'storage': storage,
1637db96d56Sopenharmony_ci            'vartype': vartype,
1647db96d56Sopenharmony_ci        }
1657db96d56Sopenharmony_ci        yield srcinfo.resolve(kind, data, name, parent=None)
1667db96d56Sopenharmony_ci
1677db96d56Sopenharmony_ci        if var_ending == ',':
1687db96d56Sopenharmony_ci            # It was a multi-declaration, so queue up the next one.
1697db96d56Sopenharmony_ci            _, qual, typespec, _ = vartype.values()
1707db96d56Sopenharmony_ci            remainder = f'{storage or ""} {qual or ""} {typespec} {remainder}'
1717db96d56Sopenharmony_ci        srcinfo.advance(remainder)
1727db96d56Sopenharmony_ci
1737db96d56Sopenharmony_ci        if var_init:
1747db96d56Sopenharmony_ci            _data = f'{name} = {var_init.strip()}'
1757db96d56Sopenharmony_ci            yield srcinfo.resolve('statement', _data, name=None)
1767db96d56Sopenharmony_ci
1777db96d56Sopenharmony_ci    else:
1787db96d56Sopenharmony_ci        # This should be unreachable.
1797db96d56Sopenharmony_ci        raise NotImplementedError
180