| # Copyright 2021 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| """Parser for a comments file.""" |
| |
| import re |
| |
| COMMENTS_STR = "=== COMMENTS ===\n" |
| COMMENT_SEP_STR = "=" * 72 + "\n" |
| DASHES_STR = "-" * 36 + "\n" |
| FILE_LINE_RE = re.compile( |
| "File (?P<name>[^\s]+)( \(snapshot (?P<snapshot>\d+)\))?") |
| LINE_LINE_RE = re.compile("Line (?P<number>\d+): (?P<text>.*)\n") |
| |
| |
| class Parser(object): |
| |
| def __init__(self, linesiter): |
| self._lines = linesiter |
| |
| def OnPreambleLine(self, line): |
| pass |
| |
| def OnFinishPreamble(self): |
| pass |
| |
| def OnOverallComment(self, comment): |
| pass |
| |
| def OnFileComment(self, path, line, text, comment): |
| pass |
| |
| def OnError(self, msg): |
| pass |
| |
| def Parse(self): |
| self.ReadPreamble() |
| self.OnFinishPreamble() |
| self.ReadOverallComment() |
| self.ReadFileComments() |
| |
| def ReadPreamble(self): |
| for line in self._lines: |
| if line == COMMENTS_STR: |
| break |
| self.OnPreambleLine(line) |
| else: |
| self.OnError("No COMMENTS line found") |
| |
| def ReadOverallComment(self): |
| self.OnOverallComment(self.ReadComment()) |
| |
| def ReadComment(self): |
| ret = "" |
| for line in self._lines: |
| if line == COMMENT_SEP_STR: |
| break |
| ret += line |
| else: |
| self.OnError("No final separator line") |
| return ret |
| |
| def ReadFileComments(self): |
| while self.ReadFileComment(): |
| pass |
| |
| def ReadFileComment(self): |
| try: |
| path = self.ReadFileLine() |
| except StopIteration: |
| return False |
| self.SkipDashes() |
| line, text = self.ReadLineLine() |
| comment = self.ReadComment() |
| self.OnFileComment(path, line, text, comment) |
| return True |
| |
| def ReadFileLine(self): |
| line = next(self._lines) |
| match = FILE_LINE_RE.search(line) |
| if not match: |
| self.OnError("Invalid file line: %s" % line) |
| return match.group("name") |
| |
| def SkipDashes(self): |
| line = next(self._lines) |
| if line != DASHES_STR: |
| self.OnError("Expecting dashes: %s" % line) |
| |
| def ReadLineLine(self): |
| line = next(self._lines) |
| match = LINE_LINE_RE.match(line) |
| if not match: |
| self.OnError("Invalid line line: %s " % line) |
| return int(match.group("number")), match.group("text") |