def __next__()

in python/moz/l10n/formats/properties/parse.py [0:0]


    def __next__(self) -> tuple[LineKind, int, str]:
        if self.done:
            raise StopIteration

        lp = self.line_pos
        self.ws()
        if self.pos == len(self.source):
            self.done = True
            return LineKind.EMPTY, lp, ""

        if self.nl():
            self.at_value = False
            return LineKind.EMPTY, lp, ""

        if self.at_value:
            # value
            self.at_value = False
            line_start = start = self.pos
            at_escape = False
            at_cr = False
            idx = -1
            lines: list[str] = []
            for idx, ch in enumerate(self.source[start:]):
                if ch == "\n" or ch == "\r":
                    if at_escape:
                        at_escape = False
                        self.line_pos += 1
                        end = start + idx - 1
                        lines.append(self.source[line_start:end])
                        at_cr = ch == "\r"
                        line_start = start + idx + 1
                    elif ch == "\n" and at_cr:
                        at_cr = False
                        line_start = start + idx + 1
                    else:
                        idx -= 1
                        break
                else:
                    if at_cr:
                        at_cr = False
                    if at_escape:
                        at_escape = False
                    elif ch == "\\":
                        at_escape = True
            self.pos = end = start + idx + 1
            lines.append(self.source[line_start:end])
            self.nl()
            value = "".join(
                esc_re.sub(esc_parse, line.lstrip("\f\t ")) for line in lines
            )
            return LineKind.VALUE, lp, value

        if self.source.startswith(("#", "!"), self.pos):
            # comment
            self.pos += 1
            if self.source.startswith(" ", self.pos):
                # Ignore one space after #, if present.
                self.pos += 1
            start = self.pos
            idx = -1
            for idx, ch in enumerate(self.source[start:]):
                if ch == "\n" or ch == "\r":
                    idx -= 1
                    break
            end = self.pos = start + idx + 1
            self.nl()
            return LineKind.COMMENT, lp, self.source[start:end]

        # key
        start = self.pos
        at_escape = False
        idx = -1
        for idx, ch in enumerate(self.source[start:]):
            if at_escape:
                at_escape = False
            elif ch == "\\":
                at_escape = True
            elif ch in {"\n", "\r", "\t", "\f", " ", "=", ":"}:
                idx -= 1
                break
        end = self.pos = start + idx + 1
        self.ws()
        if self.source.startswith(("=", ":"), self.pos):
            self.pos += 1
        self.at_value = True
        return LineKind.KEY, lp, esc_re.sub(esc_parse, self.source[start:end])