Skip to content

字符串和字符 ​

实现状态: 已实现(UTF-8 存储、字素簇计数 Phase 84、for-in、.count、下标、split/trim/... 全部 stdlib 方法、正则字面量 Phase 50+);Character Phase 139 MVP GA 为与 String 区分的标量类型(非完整 Unicode Character 属性库)

字符串是 SYX 与 Swift 差异最显著的领域之一。本章会讲清「字素簇 vs 标量」、「Character 类型」、「插值与转义」、「正则字面量」四个关键点。

创建字符串 ​

swift
let s = "Hello"
let name = "World"
let msg = "Hello, \(name)!"        // 插值
let multi = "a" + "b" + "c"        // 字符串拼接
let multiline = "line one\nline two"
let tabbed = "col1\tcol2\tcol3"

来源:crates/syx-driver/tests/fixtures/lang/string_multiline.sy · examples/main.sy

字符串字面量语法 ​

形式语法说明
单行"…"双引号包裹;支持转义与插值
多行MVP GA"""…""" 可含裸换行与 \(expr) 插值(Phase 139)
转义\n \t \\ \" \(expr)同 Swift
插值\(expr)任意表达式(函数调用、算术、字段访问)
swift
let name = "World"
let count = 3
let s1 = "Hello, \(name)!"
let s2 = "count=\(count + 1)"        // 表达式
let s3 = "items: \([1,2,3].count)"  // 任意表达式合法

重要: 单行字符串内不允许裸换行(L001)。多行 """ 字面量允许裸换行(Phase 139 MVP)。

转义序列 ​

转义含义字节
\n换行 (LF)0x0A
\r回车 (CR)0x0D
\t制表符0x09
\\反斜杠0x5C
\"双引号0x22
\'单引号0x27
\0空字符 (NUL)0x00
\(…)插值(无 0 字节,编译为 StringConcat)—
\x41ASCII 字节0x41
\u{1F600}Unicode 码点emoji 0x1F600
swift
let s = "tab\there\nnewline"
let emoji = "\u{1F600}"            // 😀
let zwnj = "\u{200C}"              // ZWNJ(零宽非连接符)

字符串常用方法 ​

swift
"a,b,c".split(",")                       // ["a", "b", "c"]
"  hi  ".trim()                          // "hi"
"ABC".lowercased()                       // "abc"
"abc".uppercased()                       // "ABC"
"file.txt".hasPrefix("file")             // true
"hello.txt".hasSuffix(".txt")            // true
"hello".substring(0, 3)                  // "hel"  [start, end) 标量索引
"banana".replacingOccurrences("a", "o")  // "bonono"
"abc123".matches("\\d+")                 // ["123"](正则匹配返回子串数组)
"text".count                            // 4(字素簇个数)
"text".isEmpty                           // false
"  ".isEmpty                             // false(空格也是字素簇)

完整 String 方法注册表见 crates/syx-stdlib/src/string_methods.rs(STRING_METHODS)。examples/main.sy 给出端到端示例。

方法签名说明
split(sep: String)Array<String>按分隔符拆分
trim()String去首尾 Unicode 空白
lowercased()StringUnicode simple case mapping(Rust;≠ caseFolded;≠ locale)
uppercased()StringUnicode simple case mapping(Rust;≠ caseFolded;≠ locale)
normalizedNFC(text:)StringUnicode NFC(ADR-228)
normalizedNFD(text:)StringUnicode NFD(ADR-228)
caseFolded(text:)StringUnicode default/full case folding(如 ß→ss;ADR-228)
hasPrefix(s)Bool前缀判断
hasSuffix(s)Bool后缀判断
substring(start, end)String标量子串 [start, end)
replacingOccurrences(target, with)String替换(首次 / 全部依实现)
matches(pattern)Array<String>正则匹配
countInt字素簇个数(非 字节数)
isEmptyBool字素簇数为 0
repeat(n)String重复 n 次

遍历字符串 ​

swift
for c in "abc" {
    print(c)    // 依次输出 "a", "b", "c"
}

循环变量 c 的类型为 Character(Phase 139 起为独立标量类型;运行时非多字符 String)。

实现状态: for-in 已实现;循环变量为 Character(MVP GA;fixtures/lang/character.sy)。

内部表示(重要) ​

层面SYX
存储UTF-8 字节数组(Rust String 后端)
.count / substring / for-inUnicode 字素簇(Phase 84 起,unicode-segmentation 索引)
Character 类型MVP GA(Phase 139;运行时 Value::Character 标量;非完整 Unicode 属性库)
Character.isASCII()MVP GA(单标量检查;非完整 ASCII 属性判定)

Swift 对齐: 组合 emoji(如 👨‍👩‍👧‍👦,家庭)在 Swift 中为 1 个「字符」;SYX 在 Phase 84 字素簇索引下也是 1。

回退标记: Phase 84 之前 .count 按 Unicode 标量计数;老 fixture(stdlib/string_index_honesty.rs 等)保留标量行为测试。如发现 .count 与早期文档不一致,以当前行为为准。

下标 s[i] ​

swift
let s = "syx"
let c: Character = s[0]      // grapheme Character
print(c)                     // "s"

let second = s[1]            // "w"
行为SYX
索引语义Int grapheme offset(Phase 84;ADR-227)
复杂度单次随机访问 O(n)(无 opaque Index / 无 O(1) 缓存)
返回类型Character(grapheme 簇)
越界运行时错误 R003(文案含 out of bounds;≠ 空 Character;≠ R013)
与 Swift≠ opaque String.Index;SYX 用整数偏移

区间访问: 暂未提供 s[0..<3] 切片语法;用 substring(0, 3)(同样为 O(n) grapheme offset)。钉测:m2_s2_02_string_index_honesty。

字符串拼接 ​

swift
let a = "Hello"
let b = ", World"
let c = a + b                       // "Hello, World"
let d = "\(a)\(b)!"                 // 插值拼接
let e = a + b + "!"                 // 与 + 拼接片段相同

+ 运算符在 String 上是 StringConcat 指令的低级 lowering(非 Core Host 函数);运行时内联为字节拷贝。

字符串比较 ​

swift
"abc" == "abc"     // true(值相等,Equatable witness)
"abc" < "abd"      // true(字典序)
"abc" === "abc"    // false(不同 String 对象;=== 比较引用)

比较语义: == 按字素簇序列比较(Phase 84 起);< 字典序(Comparable witness)。=== 比较 VM/MIR 层的对象身份(不常用)。

正则字面量 ​

swift
let matches = "abc123def".matches("\\d+")   // 模式字符串(正则字面量 `/…/` MIR 仍部分)
for m in matches { print(m) }               // "123"

let helloHits = "Hello hello".matches("hello")
print(helloHits.count)
形式状态说明
/pattern/已实现由 crates/syx-regex 解析;与上下文消歧
/pattern/i部分实现flag 在 parser 接受;运行时支持有限
/pattern/m /pattern/s未实现多行/单行 flag

歧义消歧: / 在注释起始上下文不出现(行注释用 //),但在除法表达式中可能歧义(x/y vs 正则)。Parser 通过前瞻 token 区分;典型情况无需担心。

详见 语言参考:词法结构。

字符串与集合互转 ​

swift
let s = "a,b,c"
let parts = s.split(",")                  // ["a", "b", "c"]
let joined = parts.joined("-")            // "a-b-c"

var graphemes: Array<String> = []
for ch in s {
    graphemes.append(ch)                  // 经 for-in 收集字素簇
}
let back = graphemes.joined("")           // "a,b,c"
方向方法
String → Array<String>s.split(sep)
Array<String> → Stringarr.joined(sep)
String → 字素列表for ch in s(append 进 Array)
字素列表 → Stringgraphemes.joined("")

完整示例 ​

来源 fixtures/lang/string_multiline.sy:

swift
func main() {
    let name = "SYX"
    print("Hello, \(name)!")

    print("  Hello, World  ".trim())

    let parts = "a,b,c".split(",")
    for item in parts {
        print(item)
    }

    for m in "abc123def".matches("\\d+") {
        print(m)
    }

    var digits: Array<String> = []
    for ch in "0123456789" {
        digits.append(ch)
    }
    print(digits.count)              // 10
    print(digits[0])                  // "0"
}

内部 API(Core 扩展) ​

字符串 witness(hash / description / debugDescription)通过 Core extension → Host 函数实现(详见 第 32 章 运算符 vs Core Host):

swift
extension String {
    func hash(into hasher: Hasher) {
        __syx_hasher_combine(hasher, self)
    }
    func description() -> String {
        return __syx_value_description(self)
    }
}

String 在 crates/syx-stdlib/src/builtins/string.sy 完整注册;用户代码一般无需直接调用 __syx_*。

诊断 ​

代码触发修复
L001字符串未闭合补全 "
R003s[i] 越界(含负下标)检查索引;≠ 空 Character
S004String 与 Array 互用显式 .split() / .joined()

与 Swift 的差异 ​

SwiftSYX
Character 是独立 structCharacter 是 String 类型别名(运行时单标量)
opaque String.IndexInt grapheme offset(O(n) 随机访问;≠ opaque Index)
s[i] 返回 Character返回 grapheme Character(ADR-226/227)
s[range] 切片s.substring(start, end)
String(format:)未实现;用插值或 Int.toString()
count.count(一致)
String == String字素簇序列相等(Phase 84 起)
String 字面量插值兼容 Swift \(expr) 语法

下一章 → 集合类型

参见 → 语言参考:词法 · 第 5 章 集合类型 · 第 32 章 运算符 vs Core Host

SYX · Apache-2.0