feat(ast): lexer 支持 f-string 表达式块嵌套与同引号嵌套字符串(PEP 701)

This commit is contained in:
TermiNexus committed 2026-08-30 07:36:50 +08:00
1 parent 49445ea796
commit f76620199a
1 file changed
+46
+46
View File
@@ -481,6 +481,8 @@ def _read_string(lx: Lexer | t.CPtr):
# Read string content
content_buf_start: t.CSizeT = lx.pos
# f-string {} 表达式块嵌套深度(PEP 701 同引号嵌套字符串支持用)
fstr_depth: t.CInt = 0
while lx.pos < lx.len:
ch = lx.src[lx.pos]
if is_triple:
@@ -506,6 +508,50 @@ def _read_string(lx: Lexer | t.CPtr):
lx.pos += 1
lx.col += 1
else:
if is_fstring:
# {{ 与 }} 是转义字面量,不参与深度计数
if ch == '{' and lx.pos + 1 < lx.len and lx.src[lx.pos + 1] == '{':
lx.pos += 2
lx.col += 2
continue
if ch == '}' and lx.pos + 1 < lx.len and lx.src[lx.pos + 1] == '}':
lx.pos += 2
lx.col += 2
continue
if ch == '{':
fstr_depth += 1
lx.pos += 1
lx.col += 1
continue
if ch == '}':
if fstr_depth > 0:
fstr_depth -= 1
lx.pos += 1
lx.col += 1
continue
if fstr_depth > 0 and (ch == '\'' or ch == '"'):
# {} 表达式块内允许嵌套字符串字面量(PEP 701 同引号嵌套):
# 跳过到匹配引号,块内引号不终止外层 f-string。
nq: t.CChar = ch
lx.pos += 1
lx.col += 1
while lx.pos < lx.len:
c2: t.CChar = lx.src[lx.pos]
if c2 == '\\':
lx.pos += 2
lx.col += 2
continue
if c2 == nq:
lx.pos += 1
lx.col += 1
break
if c2 == '\n':
# 单行字符串不能跨行
lx.error_count += 1
return
lx.pos += 1
lx.col += 1
continue
if ch == quote:
break
if ch == '\n':