Swift 词法结构
Swift 的*“词法结构(lexical structure)”* 描述了能构成该语言中有效符号(token)的字符序列。这些合法符号组成了语言中最底层的构建基块,并在之后的章节中用于描述语言的其他部分。一个合法符号由一个标识符(identifier)、关键字(keyword)、标点符号(punctuation)、字面量(literal)或运算符(operator)组成。
通常情况下,符号是考虑了输入文本中最长可能的子字符串,并被随后将介绍的语法约束,根据 Swift 源文件的字符生成的。这种方法称为*“最长匹配(longest match)”,或者“最大适合(maximal munch)”*。
空白与注释
空白(whitespace)有两个用途:分隔源文件中的符号和区分前 缀、后缀和中缀运算符(参见 运算符),在其他情况下空白则会被忽略。以下的字符会被当作空白:空格(U+0020)、换行符(U+000A)、回车符(U+000D)、水平制表符(U+0009)、垂直制表符(U+000B)、换页符(U+000C)以及空字符(U+0000)。
注释被编译器当作空白处理。单行注释由 //
开始直至遇到换行符(U+000A)或者回车符(U+000D)。多行注释由 /*
开始,以 */
结束。多行注释允许嵌套,但注释标记必须成对出现。
注释可以包含其他的格式和标记,如 标记格式参考中所述。
空白语法
whitespace-item
空白项 → 断行符
空白项 → 行内空白
空白项 → 注释
空白项 → 多行注释
空白项 → U+0000,U+0009,U+000B,U+000C 或者 U+0020
line-break
断行符 → U+000A
断行符 → U+000D
断行符 → U+000D 接着是 U+000A
inline-spaces
inline-space
行内空白 → U+0009 或 U+0020
comment
multiline-comment
多行注释 →
/*
多行注释内容*/
comment-text
comment-text-item
注释内容项 → 任何 Unicode 标量值,除了 U+000A 或者 U+000D
multiline-commnet-text
多行注释内容项 → 多行注释.
多行注释内容项 → 注释内容项
多行注释内容项 → 任何 Unicode 标量值,除了
/*
或者*/
标识符
标识符(identifier) 可以由以下的字符开始:大写或小写的字母 A
到 Z
、下划线(_
)、基本多文种平面(Basic Multilingual Plane)中非字符数字组合的 Unicode 字符以及基本多文种平面以外的非个人专用区字符。在首字符之后,允许使用数字和组合 Unicode 字符。
以下划线开头的标识视为内部标识符,即使声明了 public
访问级别。这个约定允许框架作者标记一部分不能被使用方调用或依赖的 API,即便因为某些限制原因导致它的声明必须是公开的。另外,双下划线开头的标识符是为 Swift 编译器和标准库预留的。
使用保留字作为标识符,需要在其前后增加反引号(`
)。例如,class
不是合法的标识符,但可以使用 `class`
。反引号不属于标识符的一部分,`x`
和 x
表示同一标识符。
闭包中如果没有明确指定参数名称, 参数将被隐式命名为 $0
、$1
、$2
等等。这些命名在闭包作用域范围内是合法的标识符。
编译器给含有属性包装器呈现值的属性自动合成以美元符号($)开头的标识符。你的代码可以与这些标识符进行交互,,但是不能使用该前缀声明标识符。更详细的介绍,请查看 特性 章节中的 属性包装器 部分。
标识符语法
identifier
标识符 → 隐式参数名
标识符 → 属性包装器呈现值
identifier-list
identifier-head
头部标识符 → 大写或小写字母 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
identifier-character
标识符字符 → 数值 0 - 9
标识符字符 → U+0300–U+036F,U+1DC0–U+1DFF,U+20D0–U+20FF,或者 U+FE20–U+FE2F
标识符字符 → 头部标识符
identifier-characters
implicit-parameter-name
隐式参数名 → $ 十进制数字列表
property-wrapper-projection
属性包装器呈现值 → $ 标识符字符组
关键字和标点符号
下面这些被保留的关键字不允许用作标识符,除非使用反引号转义,具体描述请参考 标识符。除了 inout
、var
以及 let
之外的关键字可以用作某个函数声明或者函数调用当中的外部参数名,无需添加反引号转义。当一个成员与一个关键字具有相同的名称时,不需要使用反引号来转义对该成员的引用,除非在引用该成员和使用该关键字之间存在歧义 - 例如,self
,Type
和 Protocol
在显式的成员表达式中具有特殊的含义,因此它们必须在该上下文中使用反引号进行转义。
- 用在声明中的关键字:
associatedtype
、class
、deinit
、enum
、extension
、fileprivate
、func
、import
、init
、inout
、internal
、let
、open
、operator
、private
、precedencegroup
、protocol
、public
、rethrows
、static
、struct
、subscript
、typealias
以及var
。 - 用在语句中的关键字:
break
、case
、catch
、continue
、default
、defer
、do
、else
、fallthrough
、for
、guard
、if
、in
、repeat
、return
、throw
、switch
、where
以及while
。 - 用在表达式和类型中的关键字:
Any
、as
、catch
、false
、is
、nil
、rethrows
、self
、Self
、super
、throw
、throws
、true
以及try
。 - 用在模式中的关键字:
_
。 - 以井字号(
#
)开头的关键字:#available
、#colorLiteral
、#column
、#dsohandle
、#elseif
、#else
、#endif
、#error
、#fileID
、#fileLiteral
、#filePath
、#file
、#function
、#if
、#imageLiteral
、#keyPath
、#line