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])