Path: blob/main/Tools/c-analyzer/c_parser/parser/_common.py
12 views
import re12from ._regexes import (3_ind,4STRING_LITERAL,5VAR_DECL as _VAR_DECL,6)789def log_match(group, m, depth_before=None, depth_after=None):10from . import _logger1112if m is not None:13text = m.group(0)14if text.startswith(('(', ')')) or text.endswith(('(', ')')):15_logger.debug(f'matched <{group}> ({text!r})')16else:17_logger.debug(f'matched <{group}> ({text})')1819elif depth_before is not None or depth_after is not None:20if depth_before is None:21depth_before = '???'22elif depth_after is None:23depth_after = '???'24_logger.log(1, f'depth: %s -> %s', depth_before, depth_after)2526else:27raise NotImplementedError('this should not have been hit')282930#############################31# regex utils3233def set_capture_group(pattern, group, *, strict=True):34old = f'(?: # <{group}>'35if strict and f'(?: # <{group}>' not in pattern:36raise ValueError(f'{old!r} not found in pattern')37return pattern.replace(old, f'( # <{group}>', 1)383940def set_capture_groups(pattern, groups, *, strict=True):41for group in groups:42pattern = set_capture_group(pattern, group, strict=strict)43return pattern444546#############################47# syntax-related utils4849_PAREN_RE = re.compile(rf'''50(?:51(?:52[^'"()]*53{_ind(STRING_LITERAL, 3)}54)*55[^'"()]*56(?:57( [(] )58|59( [)] )60)61)62''', re.VERBOSE)636465def match_paren(text, depth=0):66pos = 067while (m := _PAREN_RE.match(text, pos)):68pos = m.end()69_open, _close = m.groups()70if _open:71depth += 172else: # _close73depth -= 174if depth == 0:75return pos76else:77raise ValueError(f'could not find matching parens for {text!r}')787980VAR_DECL = set_capture_groups(_VAR_DECL, (81'STORAGE',82'TYPE_QUAL',83'TYPE_SPEC',84'DECLARATOR',85'IDENTIFIER',86'WRAPPED_IDENTIFIER',87'FUNC_IDENTIFIER',88))899091def parse_var_decl(decl):92m = re.match(VAR_DECL, decl, re.VERBOSE)93(storage, typequal, typespec, declarator,94name,95wrappedname,96funcptrname,97) = m.groups()98if name:99kind = 'simple'100elif wrappedname:101kind = 'wrapped'102name = wrappedname103elif funcptrname:104kind = 'funcptr'105name = funcptrname106else:107raise NotImplementedError108abstract = declarator.replace(name, '')109vartype = {110'storage': storage,111'typequal': typequal,112'typespec': typespec,113'abstract': abstract,114}115return (kind, name, vartype)116117118#############################119# parser state utils120121# XXX Drop this or use it!122def iter_results(results):123if not results:124return125if callable(results):126results = results()127128for result, text in results():129if result:130yield result, text131132133