Path: blob/main/Tools/c-analyzer/c_parser/parser/_info.py
12 views
#import re12from ..info import KIND, ParsedItem, FileInfo345class TextInfo:67def __init__(self, text, start=None, end=None):8# immutable:9if not start:10start = 111self.start = start1213# mutable:14lines = text.splitlines() or ['']15self.text = text.strip()16if not end:17end = start + len(lines) - 118self.end = end19self.line = lines[-1]2021def __repr__(self):22args = (f'{a}={getattr(self, a)!r}'23for a in ['text', 'start', 'end'])24return f'{type(self).__name__}({", ".join(args)})'2526def add_line(self, line, lno=None):27if lno is None:28lno = self.end + 129else:30if isinstance(lno, FileInfo):31fileinfo = lno32if fileinfo.filename != self.filename:33raise NotImplementedError((fileinfo, self.filename))34lno = fileinfo.lno35# XXX36#if lno < self.end:37# raise NotImplementedError((lno, self.end))38line = line.lstrip()39self.text += ' ' + line40self.line = line41self.end = lno424344class SourceInfo:4546_ready = False4748def __init__(self, filename, _current=None):49# immutable:50self.filename = filename51# mutable:52if isinstance(_current, str):53_current = TextInfo(_current)54self._current = _current55start = -156self._start = _current.start if _current else -157self._nested = []58self._set_ready()5960def __repr__(self):61args = (f'{a}={getattr(self, a)!r}'62for a in ['filename', '_current'])63return f'{type(self).__name__}({", ".join(args)})'6465@property66def start(self):67if self._current is None:68return self._start69return self._current.start7071@property72def end(self):73if self._current is None:74return self._start75return self._current.end7677@property78def text(self):79if self._current is None:80return ''81return self._current.text8283def nest(self, text, before, start=None):84if self._current is None:85raise Exception('nesting requires active source text')86current = self._current87current.text = before88self._nested.append(current)89self._replace(text, start)9091def resume(self, remainder=None):92if not self._nested:93raise Exception('no nested text to resume')94if self._current is None:95raise Exception('un-nesting requires active source text')96if remainder is None:97remainder = self._current.text98self._clear()99self._current = self._nested.pop()100self._current.text += ' ' + remainder101self._set_ready()102103def advance(self, remainder, start=None):104if self._current is None:105raise Exception('advancing requires active source text')106if remainder.strip():107self._replace(remainder, start, fixnested=True)108else:109if self._nested:110self._replace('', start, fixnested=True)111#raise Exception('cannot advance while nesting')112else:113self._clear(start)114115def resolve(self, kind, data, name, parent=None):116# "field" isn't a top-level kind, so we leave it as-is.117if kind and kind != 'field':118kind = KIND._from_raw(kind)119fileinfo = FileInfo(self.filename, self._start)120return ParsedItem(fileinfo, kind, parent, name, data)121122def done(self):123self._set_ready()124125def too_much(self, maxtext, maxlines):126if maxtext and len(self.text) > maxtext:127pass128elif maxlines and self.end - self.start > maxlines:129pass130else:131return False132133#if re.fullmatch(r'[^;]+\[\][ ]*=[ ]*[{]([ ]*\d+,)*([ ]*\d+,?)\s*',134# self._current.text):135# return False136return True137138def _set_ready(self):139if self._current is None:140self._ready = False141else:142self._ready = self._current.text.strip() != ''143144def _used(self):145ready = self._ready146self._ready = False147return ready148149def _clear(self, start=None):150old = self._current151if self._current is not None:152# XXX Fail if self._current wasn't used up?153if start is None:154start = self._current.end155self._current = None156if start is not None:157self._start = start158self._set_ready()159return old160161def _replace(self, text, start=None, *, fixnested=False):162end = self._current.end163old = self._clear(start)164self._current = TextInfo(text, self._start, end)165if fixnested and self._nested and self._nested[-1] is old:166self._nested[-1] = self._current167self._set_ready()168169def _add_line(self, line, lno=None):170if not line.strip():171# We don't worry about multi-line string literals.172return173if self._current is None:174self._start = lno175self._current = TextInfo(line, lno)176else:177# XXX178#if lno < self._current.end:179# # A circular include?180# raise NotImplementedError((lno, self))181self._current.add_line(line, lno)182self._ready = True183184185