diff --git a/ast/lexer.vp b/ast/lexer.vp index c8b9af9..2818c43 100644 --- a/ast/lexer.vp +++ b/ast/lexer.vp @@ -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':