The Swift Programming Language 中文版

词法结构

Swift的词法结构描述了如何在该语言中用字符序列构建合法标记。这些合法标识构成了该语言最底层的基石,并将会被用于描述后续章节的剩余部分。

在大多数情况下,在后续指定的语法约束内,标识将从Swift源文件的输入文本中提取尽可能长的子字符串生成。这种方法称为“最长匹配项”,或者“最大适合”。

空白与注释

空白有两个用途:区分源文件中的标识符和帮助确定一个操作符是前缀还是后缀(参见:运算符),否则忽略。以下字符会被认为是空白:空格(U+0020)、换行符(U+000A)、回车符(U+000D)、水平制表符(U+0009)、垂直制表符(U+000B)、换页符(U+000C)以及空(U+0000)。

注释会被编译器当作空白处理。单行注释以 // 开始直到该行结束。多行注释由 /* 开始,以 */ 结束。注释允许嵌套,但注释标记必须相匹配。

标识符

标识符以大写或小写字母A到Z,下划线(_),基本多语言文种平面 中的非组合Unicode字符或者基本多语言文种平面以外的私有使用区的字符开始。在首字符之后,数字和 Unicode 字符组合也是可以允许的。

要使用保留字作为标识符,需要在其前后增加一个反引号(`)。例如:类不是一个有效的标识符,但class是有效的。反引号不会被当做标识符的一部分;x 和 x 意义相同。

闭包中如果没有明确的参数名称,参数将被隐式命名为 $0、$1、$2... 这些命名在闭包作用域内是有效的标识符。

标识符语法

标识符 → 标识符头 标识符字符 [可选]

标识符 → ` 标识符头 标识符字符 [可选] `

标识符 → 隐式参数名

标识符列表 → 标识符 标识符 , 标识符列表

标识符头 → 大写或小写字母A到Z

标识符头 → U+00A8, U+00AA, U+00AD, U+00AF, U+00B2–U+00B5, 或 U+00B7–U+00BA

标识符头 → U+00BC–U+00BE, U+00C0–U+00D6, U+00D8–U+00F6, 或 U+00F8–U+00FF

标识符头 → U+0100–U+02FF, U+0370–U+167F, U+1681–U+180D, 或 U+180F–U+1DBF

标识符头 → U+1E00–U+1FFF

标识符头 → U+200B–U+200D, U+202A–U+202E, U+203F–U+2040, U+2054, 或 U+2060–U+206F

标识符头 → U+2070–U+20CF, U+2100–U+218F, U+2460–U+24FF, 或 U+2776–U+2793

标识符头 → U+2C00–U+2DFF 或 U+2E80–U+2FFF

标识符头 → U+3004–U+3007, U+3021–U+302F, U+3031–U+303F, 或 U+3040–U+D7FF

标识符头 → U+F900–U+FD3D, U+FD40–U+FDCF, U+FDF0–U+FE1F, 或 U+FE30–U+FE44

标识符头 → U+FE47–U+FFFD

标识符头 → U+10000–U+1FFFD, U+20000–U+2FFFD, U+30000–U+3FFFD, 或 U+40000–U+4FFFD

标识符头 → U+50000–U+5FFFD, U+60000–U+6FFFD, U+70000–U+7FFFD, 或 U+80000–U+8FFFD

标识符头 → U+90000–U+9FFFD, U+A0000–U+AFFFD, U+B0000–U+BFFFD, 或 U+C0000–U+CFFFD

标识符头 → U+D0000–U+DFFFD 或 U+E0000–U+EFFFD

标识符字符 → 数字 0 到 9

标识符字符 → U+0300–U+036F, U+1DC0–U+1DFF, U+20D0–U+20FF, 或 U+FE20–U+FE2F

标识符字符 → 标识符头

标识符字符 → 标识符字符 标识符字符列表 [可选]

隐式参数名 → $十进制数字

关键字

下述被保留的关键字不允许用作标识符,除非它们被反引号转义,参见上面的标识符。

  • 用作声明的关键字:class、deinit、enum、extension、func、imp或 t、init、let、protocol、static、struct、subscript、typealias、var

  • 用作语句的关键字:break、case、continue、default、do、else、fallthrough、if、in、f或 、return、switch、where、while

  • 用作表达和类型的关键字:as、dynamicType、is、new、super、self、Self、Type、COLUMNFILEFUNCTIONLINE

  • 特定上下文中被保留的关键字:associativity、didSet、get、infix、inout、left、mutating、none、nonmutating、operat或 、override、postfix、precedence、prefix、right、set、unowned、unowned(safe)、unowned(unsafe)、weak、willSet,这些关键字在特定上下文之外可以被用于标识符。

字面量

字面量在源代码中表示一个整数,浮点数或字符串类型的值。以下是示例:

42 //整形字面量

3.14159 //浮点型字面量

"Hello, w或 ld!" //字符串型字面量

字面量语法

字面量 → 整型字面量 | 浮点数字面量 | 字符串字面量

整型字面量

整型字面量表示未指定精度的整型值。整型字面量默认为十进制;你可以通过加前缀来改变基数。二进制字面量以 0b 开始,八进制字面量以 0o 开始,十六进制字面量以 0x 开始。

十进制字面量包含数字 0 到 9。二进制字面量只包含 0 和 1,八进制字面量包含数字 0 到 7,十六进制字面量包含数字 0 到 9 以及大写或小写的字母 A 到 F。

负整型字面量的字面量需要在整型字量面前加减号 -,比如 -42。

数字间允许使用下划线 _ 来增加可读性,但下划线会被忽略而不会影响字面量的值。整型字面量可以以0开始,但同样会被忽略而不会影响其基数或字面量的值。

除非另有指定,整型字面量的默认类型为 Swift 标准库类型中的 Int。Swift 标准库还定义了各种不同长度的有符号和无符号的整数类型,请参见 整型。

整型字面量语法

整型字面量 → 二进制字面量

整型字面量 → 八进制字面量

整型字面量 → 十进制字面量

整型字面量 → 十六进制字面量

二进制字面量 → 0b 二进制数字 二进制字面量字符列表 可选

二进制数字 → 数字 0 到 1

二进制字面量字符 → 二进制数字 | _

二进制字面量字符列表 → 二进制字面量字符 二进制字面量字符列表 可选

八进制字面量 → 0o 八进字数字 八进制字符列表 可选

八进字数字 → 数值 0 到 7

八进制字符 → 八进字数字 | _

八进制字符列表 → 八进制字符 八进制字符列表 可选

十进制字面量 → 十进制数字 十进制字符列表 可选

十进制数字 → 数值 0 到 9

十进制数字列表 → 十进制数字 十进制数字列表 可选

十进制字符 → 十进制数字 | _

十进制字符列表 → 十进制字符 十进制字符列表 可选

十六进制字面量 → 0x 十六进制数字 十六进制字面量字符列表 可选

十六进制数字 → 数值 0 到 9, a 到 f,或 A 到 F

十六进制字符 → 十六进制数字 | _

十六进制字面量字符列表 → 十六进制字符 十六进制字面量字符列表 可选

浮点型字面量

浮点型字面量表示未指定精度浮点数的值。

浮点型字面量默认用十进制表示(无前缀),但也可以用十六进制表示(加前缀 0x)。

十进制浮点型字面量由十进制数字后跟小数部分或指数部分组成,或两者都有。十进制小数部分由小数点 . 后跟十进制数字组成。指数部分由大写或小写字母的前缀e 后跟十进制数字组成,这串数字表示 e 之前的数量乘以 10 的几次方。例如:1.25e2 表示 1.25 10^2,也就是 125.0;同样,1.25e-2 表示 1.25 10^-2,也就是 0.0125。

十六进制浮点型字面量由前缀 0x 后跟可选的十六进制小数部分以及十六进制指数部分组成。十六进制小数部分由小数点后跟十六进制数字组成。指数部分由大写或小写字母的前缀p 后跟十进制数字串组成,这串数字表示 p 之前的数量乘以 2 的几次方。例如:0xFp2 表示15 2^2,也就是 60;同样,0xFp-2 表示 15 2^-2,也就是 3.75。

与整型字面量不同,负的浮点型字面量由一元运算符减号 - 和浮点型字面量组成,例如 -42.0。这代表一个表达式,而不是一个浮点整型字面量。

下划线 _ 允许被用于增强可读性,但会被忽略而不影响字面量的值。浮点型字面量也可以在数字前加 0,但同样会被忽略而不影响字面量的值。

除非另外指定,浮点型字面量的默认类型为 Swift 标准库类型中的 Double,表示64位浮点数。Swift 标准库也定义 Float 类型,表示32位浮点数。

浮点型字面量语法

浮点数字面量 → 十进制字面量 十进制分数 可选 十进制指数 可选

浮点数字面量 → 十六进制字面量 十六进制分数 可选 十六进制指数

十进制分数 → . 十进制字面量

十进制指数 → 浮点数e 正负号 可选 十进制字面量

十六进制分数 → . 十六进制字面量 可选

十六进制指数 → 浮点数p 正负号 可选 十六进制字面量

浮点数e → e | E

浮点数p → p | P

正负号 → + | -

字符串型字面量

字符串型字面量是双引号括起来的一个字符序列,形式如下:

" characters "

字符串型字面量中不能包含未转义的双引号 "、未转义的反斜线\、回车符(carriage return)或换行符(line feed)。

特殊符号经如下转义后可在字符串型字面量中使用:

  • 空字符 \0
  • 反斜线 \
  • 水平制表符 \t
  • 换行符 \n
  • 回车符 \r
  • 双引号 \"
  • 单引号 \'

字符也可以用以下方式表示:\x 后跟两位十六进制数字,\u 后跟四位十六进制数字,或 \U 后跟八位十六进制数字。在这些转义序列后跟的数字表示一个Unicode码。

字符串字面量可以在反斜线后面的小括号中插入表达式\()。插入的表达式必须不能包含未的双引号(”),反斜线(\),回车符或换行符。

表达式的计算结果必须是String类的一个有初始化的类型的值。

比如,下面所有的字符串型字面量拥有同样的值:

"1 2 3"

"1 2 (3)"

"1 2 (1 + 2)"

var x = 3; "1 2 (x)"

字符串型字面量的默认类型为 String。组成字符串的字符的类型为 Character,更多关于String和Character类型,请参考 字符串和字符。

字符型字面量语法

字符串型字面量 → " 引用文本 "

引用文本 → 引用文本条目 引用文本 可选

引用文本条目 → 转义字符

引用文本条目 → ( 表达式 )

引用文本条目 → 除了"¬, \¬, U+000A, 或 U+000D的所有Unicode的字符

转义字符 → \0 | \ | \t | \n | \r | \" | \'

转义字符 → \x 十六进制数字 十六进制数字

转义字符 → \u 十六进制数字 十六进制数字 十六进制数字 十六进制数字

转义字符 → \U 十六进制数字 十六进制数字 十六进制数字 十六进制数字 十六进制数字 十六进制数字 十六进制数字 十六进制数字

运算符

Swift标准库定义了许多供你使用的运算符,其中大部分将在 基础运算符 和 高级运算符 中进行阐述。本章节将描述了哪些字符可被用作运算符。

运算符由一个或多个如下字符组成:/、=、-、+、!、、%、<、>、&、|、^、~、.。也就是说,标记 =,->、//、/、*/、. 以及一元前缀运算符 & 属于保留字,这些标记不能被重写或用于定义自定义的运算符。

运算符两侧的空白被用来区分一个运算符是否被用为前缀运算符(prefix operat或 )、后缀运算符(postfix operat或 )或二元运算符(binary operat或 )。规则总结如下:

  • 如果运算符两侧都有空白或两侧都无空白,将被看作二元运算符。例如:a+b 和 a + b 中的运算符+ 被看作二元运算符。

  • 如果运算符只有左侧空白,将被看作前缀一元运算符。例如 a ++b 中的 ++ 被看作前缀一元运算符。

  • 如果运算符只有右侧空白,将被看作后缀一元运算符。例如 a++ b 中的 ++ 被看作后缀一元运算符。

  • 如果运算符左侧没有空白并紧跟 .,将被看作后缀一元运算符。例如 a++.b 中的 ++ 被看作后缀一元运算符(同理, a++ . b 中的 ++ 是后缀一元运算符而 a ++ .b 中的 ++ 不是).

鉴于这些规则的目的,运算符前的字符 (、[ 和 { ;运算符后的字符 )、] 和 } 以及字符 ,、; 和: 同样被认为空白。

以上规则有一点需要注意。如果运算符 ! 或 ? 左侧没有空白,则不管右侧是否有空白都将被看作后缀运算符。如果将 ? 用作修饰可选类型(optional type),左侧必须无空白。如果用于条件运算符 ? :,必须两侧都有空白。

在特定构成中 ,以 < 或 > 开头的运算符会被分离成两个或多个标记,剩余部分以同样的方式会被再次分离。因此,在 Dictionary> 中没有必要添加空白来消除闭合字符 > 的歧义。在这个例子中, 闭合字符 > 被看作单字符标记,而不会被误解为移位运算符 >>。

要学习如何自定义新的,自定义的运算符,请参考 自定义操作符 和 运算符声明。学习如何重写现有运算符,请参考 运算符方法。

运算符语法语法

运算符 → 运算符字符 运算符 可选

运算符字符 → / | = | - | + | ! | * | % | < | > | & | | | ^ | ~ | .

二元运算符 → 运算符

前置运算符 → 运算符

后置运算符 → 运算符