词法结构
使用语法的最低级组件。
Swift 的词法结构描述了哪些字符序列形成语言的有效标记。这些有效标记构成了语言的最低级构建块,并用于在随后的章节中描述语言的其余部分。一个标记由标识符、关键字、标点符号、字面量或运算符组成。
在大多数情况下,令牌是通过考虑输入文本中可能的最长子字符串,从 Swift 源文件的字符生成的,遵循下面指定的语法约束。这种行为被称为最长匹配或最大贪婪匹配。
空白和注释
空白有两个用途:在源文件中分隔令牌,并区分前缀、后缀和中缀运算符(参见运算符),但其他情况下被忽略。以下字符被视为空白字符:空格 (U+0020)、换行符 (U+000A)、回车符 (U+000D)、水平制表符 (U+0009)、垂直制表符 (U+000B)、换页符 (U+000C) 和空字符 (U+0000)。
注释被编译器视为空白。单行注释以 //
开头,并持续到换行符 (U+000A) 或回车符 (U+000D)。多行注释以 /*
开头,以 */
结束。可以嵌套多行注释,但注释标记必须平衡。
注释可以包含额外的格式和标记,如《标记格式参考》中所述。
空白的语法
whitespace → whitespace-item whitespace?
&#xNAN;whitespace-item → line-break
&#xNAN;whitespace-item → inline-space
&#xNAN;whitespace-item → comment
&#xNAN;whitespace-item → multiline-comment
&#xNAN;whitespace-item → U+0000, U+000B, or U+000Cline-break → U+000A
&#xNAN;line-break → U+000D
&#xNAN;line-break → U+000D followed by U+000Ainline-spaces → inline-space inline-spaces?
&#xNAN;inline-space → U+0009 or U+0020comment →
//
comment-text line-break
&#xNAN;multiline-comment →/*
multiline-comment-text*/
comment-text → comment-text-item comment-text?
&#xNAN;comment-text-item → Any Unicode scalar value except U+000A or U+000Dmultiline-comment-text → multiline-comment-text-item multiline-comment-text?
&#xNAN;multiline-comment-text-item → multiline-comment
&#xNAN;multiline-comment-text-item → comment-text-item
&#xNAN;multiline-comment-text-item → Any Unicode scalar value except/*
or*/
标识符
标识符以大写或小写字母 A 到 Z、下划线 ( _
)、基础多语言平面中的非组合字母数字 Unicode 字符,或不在私有使用区域的基础多语言平面外的字符开头。在第一个字符之后,数字和组合 Unicode 字符也是允许的。
将以下划线开头的标识符、其第一个参数标签以下划线开头的下标,以及其第一个参数标签以下划线开头的初始化器视为内部,即使它们的声明具有 public
访问级别修饰符。此约定允许框架作者标记客户端不能与之交互或依赖的 API 的一部分,尽管某些限制要求声明为公共。此外,以两个下划线开头的标识符保留给 Swift 编译器和标准库。
要将保留字用作标识符,请在它前后放置反引号(`)。例如, class
不是有效的标识符,但 `class`
是有效的。反引号不被视为标识符的一部分; `x`
和 x
具有相同的含义。
在没有显式参数名称的闭包中,参数被隐式命名为 $0
, $1
, $2
等。这些名称在闭包的范围内是有效的标识符。
编译器为具有属性包装投影的属性合成以美元符号( $
)开头的标识符。您的代码可以与这些标识符交互,但您不能声明带有该前缀的标识符。有关更多信息,请参阅属性章节的 propertyWrapper 部分。
标识符的语法
identifier → identifier-head identifier-characters?
&#xNAN;identifier →`
identifier-head identifier-characters?`
&#xNAN;identifier → implicit-parameter-name
&#xNAN;identifier → property-wrapper-projection
&#xNAN;identifier-list → identifier | identifier,
identifier-listidentifier-head → Upper- or lowercase letter A through Z
&#xNAN;identifier-head →_
&#xNAN;identifier-head → U+00A8, U+00AA, U+00AD, U+00AF, U+00B2–U+00B5, or U+00B7–U+00BA
&#xNAN;identifier-head → U+00BC–U+00BE, U+00C0–U+00D6, U+00D8–U+00F6, or U+00F8–U+00FF
&#xNAN;identifier-head → U+0100–U+02FF, U+0370–U+167F, U+1681–U+180D, or U+180F–U+1DBF
&#xNAN;identifier-head → U+1E00–U+1FFF
&#xNAN;identifier-head → U+200B–U+200D, U+202A–U+202E, U+203F–U+2040, U+2054, or U+2060–U+206F
&#xNAN;identifier-head → U+2070–U+20CF, U+2100–U+218F, U+2460–U+24FF, or U+2776–U+2793
&#xNAN;identifier-head → U+2C00–U+2DFF or U+2E80–U+2FFF
&#xNAN;identifier-head → U+3004–U+3007, U+3021–U+302F, U+3031–U+303F, or U+3040–U+D7FF
&#xNAN;identifier-head → U+F900–U+FD3D, U+FD40–U+FDCF, U+FDF0–U+FE1F, or U+FE30–U+FE44
&#xNAN;identifier-head → U+FE47–U+FFFD
&#xNAN;identifier-head → U+10000–U+1FFFD, U+20000–U+2FFFD, U+30000–U+3FFFD, or U+40000–U+4FFFD
&#xNAN;identifier-head → U+50000–U+5FFFD, U+60000–U+6FFFD, U+70000–U+7FFFD, or U+80000–U+8FFFD
&#xNAN;identifier-head → U+90000–U+9FFFD, U+A0000–U+AFFFD, U+B0000–U+BFFFD, or U+C0000–U+CFFFD
&#xNAN;identifier-head → U+D0000–U+DFFFD or U+E0000–U+EFFFDidentifier-character → Digit 0 through 9
&#xNAN;identifier-character → U+0300–U+036F, U+1DC0–U+1DFF, U+20D0–U+20FF, or U+FE20–U+FE2F
&#xNAN;identifier-character → identifier-head
&#xNAN;identifier-characters → identifier-character identifier-characters?implicit-parameter-name →
$
decimal-digits
&#xNAN;property-wrapper-projection →$
identifier-characters
关键字和标点符号
以下关键字是保留的,不能用作标识符,除非使用反引号进行转义,正如上面在标识符中所描述的那样。除 inout
、 var
和 let
之外的关键字可以在函数声明或函数调用中用作参数名,而无需使用反引号进行转义。当成员的名称与关键字相同时,引用该成员时无需使用反引号进行转义,除非在引用成员和使用关键字之间存在歧义——例如, self
、 Type
和 Protocol
在显式成员表达式中具有特殊含义,因此在该上下文中必须使用反引号进行转义。
- 声明中使用的关键字:
associatedtype
、borrowing
、class
、consuming
、deinit
、enum
、extension
、fileprivate
、func
、import
、init
、inout
、internal
、let
、nonisolated
、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
,await
,catch
,false
,is
,nil
,rethrows
,self
,Self
,super
,throw
,throws
,true
和try
. - 在模式中使用的关键字:
_
. - 以数字标志 (
#
) 开头的关键字:#available
,#colorLiteral
,#else
,#elseif
,#endif
,#fileLiteral
,#if
,#imageLiteral
,#keyPath
,#selector
,#sourceLocation
,#unavailable
.
注意
在 Swift 5.9 之前,以下关键词是保留的:
#column
,#dsohandle
,#error
,#fileID
,#filePath
,#file
,#function
,#line
,和#warning
。这些现在被实现为 Swift 标准库中的宏:column
,dsohandle
,error(_:)
,fileID
,filePath
,file
,function
,line
,和warning(_:)
。
- 特定上下文中保留的关键词:
associativity
、convenience
、didSet
、dynamic
、final
、get
、indirect
、infix
、lazy
、left
、mutating
、none
、nonmutating
、optional
、override
、package
、postfix
、precedence
、prefix
、Protocol
、required
、right
、set
、some
、Type
、unowned
、weak
和willSet
。在它们出现在语法的上下文之外时,可以作为标识符使用。
以下标记被保留为标点符号,不能用作自定义运算符: (
, )
, {
, }
, [
, ]
, .
, ,
, :
, ;
, =
, @
, #
, &
(作为前缀运算符), ->
, `
, ?
以及 !
(作为后缀运算符)。
字面量
字面量是值的类型(例如数字或字符串)的源代码表示。
以下是字面量的示例:
42 // Integer literal
3.14159 // Floating-point literal
"Hello, world!" // String literal
/Hello, .*/ // Regular expression literal
true // Boolean literal
字面量本身没有类型。相反,字面量被解析为具有无限精度,Swift 的类型推断会尝试推断字面量的类型。例如,在声明 let x: Int8 = 42
中,Swift 使用显式类型注释 ( : Int8
) 推断整数字面量 42
的类型是 Int8
。如果没有可用的合适类型信息,Swift 会推断字面量的类型是 Swift 标准库中定义的默认字面量类型之一,并列在下面的表格中。当为字面量值指定类型注释时,注释的类型必须是可以从该字面量值实例化的类型。也就是说,该类型必须符合下面表格中列出的 Swift 标准库协议。
文字 | 默认类型 | 协议 |
---|---|---|
整数 | Int | ExpressibleByIntegerLiteral |
浮点数 | Double | ExpressibleByFloatLiteral |
字符串 | String | ExpressibleByStringLiteral , ExpressibleByUnicodeScalarLiteral 用于仅包含单个 Unicode 标量的字符串字面量, ExpressibleByExtendedGraphemeClusterLiteral 用于仅包含单个扩展字符簇的字符串字面量 |
正则表达式 | Regex | 无 |
布尔值 | Bool | ExpressibleByBooleanLiteral |
例如,在声明 let str = "Hello, world"
中,字符串字面量 "Hello, world"
的默认推断类型是 String
。同时, Int8
符合 ExpressibleByIntegerLiteral
协议,因此它可以在声明 let x: Int8 = 42
中用于整数字面量 42
的类型注释。
字面量的语法
literal → numeric-literal | string-literal | regular-expression-literal | boolean-literal | nil-literal
numeric-literal →
-
? integer-literal |-
? floating-point-literal
&#xNAN;boolean-literal →true
|false
&#xNAN;nil-literal →nil
整数字面量
整数字面量表示不确定精度的整数值。默认情况下,整数字面量以十进制表示;您可以使用前缀指定其他进制。二进制字面量以 0b
开头,八进制字面量以 0o
开头,十六进制字面量以 0x
开头。
十进制字面量包含数字 0
到 9
。二进制字面量包含 0
和 1
,八进制字面量包含 0
到 7
,而十六进制字面量包含 0
到 9
以及 A
到 F
的大写或小写形式。
负整数字面量通过在整数字面量前加上负号 ( -
) 来表示,如 -42
。
为了可读性,数字之间允许使用下划线 ( _
),但它们会被忽略,因此不会影响字面量的值。整数字面量可以以前导零 ( 0
) 开头,但它们同样会被忽略,不会影响字面量的基数或值。
除非另有说明,整数字面量的默认推断类型是 Swift 标准库类型 Int
。Swift 标准库还定义了各种大小的有符号和无符号整数类型,如整数中所述。
整数字面量的语法
integer-literal → binary-literal
&#xNAN;integer-literal → octal-literal
&#xNAN;integer-literal → decimal-literal
&#xNAN;integer-literal → hexadecimal-literalbinary-literal →
0b
binary-digit binary-literal-characters?
&#xNAN;binary-digit → Digit 0 or 1
&#xNAN;binary-literal-character → binary-digit |_
&#xNAN;binary-literal-characters → binary-literal-character binary-literal-characters?octal-literal →
0o
octal-digit octal-literal-characters?
&#xNAN;octal-digit → Digit 0 through 7
&#xNAN;octal-literal-character → octal-digit |_
&#xNAN;octal-literal-characters → octal-literal-character octal-literal-characters?decimal-literal → decimal-digit decimal-literal-characters?
&#xNAN;decimal-digit → Digit 0 through 9
&#xNAN;decimal-digits → decimal-digit decimal-digits?
&#xNAN;decimal-literal-character → decimal-digit |_
&#xNAN;decimal-literal-characters → decimal-literal-character decimal-literal-characters?hexadecimal-literal →
0x
hexadecimal-digit hexadecimal-literal-characters?
&#xNAN;hexadecimal-digit → Digit 0 through 9, a through f, or A through F
&#xNAN;hexadecimal-literal-character → hexadecimal-digit |_
&#xNAN;hexadecimal-literal-characters → hexadecimal-literal-character hexadecimal-literal-characters?
浮点字面量
浮点字面量表示不确定精度的浮点值。
默认情况下,浮点字面量以十进制表示(没有前缀),但它们也可以以十六进制表示(带有 0x
前缀)。
十进制浮点文字面量由一系列十进制数字组成,后面跟着十进制小数、十进制指数或两者。十进制小数由一个十进制点 ( .
) 后跟一系列十进制数字组成。指数由一个大写或小写的 e
前缀和一系列十进制数字组成,表示值前面的 e
乘以 10 的幂。例如, 1.25e2
表示 1.25 x 10²,计算结果为 125.0
。类似地, 1.25e-2
表示 1.25 x 10⁻²,计算结果为 0.0125
。
十六进制浮点字面量由一个 0x
前缀组成,后跟一个可选的十六进制分数,最后是一个十六进制指数。十六进制分数由小数点后跟一系列十六进制数字组成。指数由一个大写或小写的 p
前缀后跟一系列十进制数字组成,指示前面的 p
乘以 2 的多少次方。例如, 0xFp2
代表 15 x 2²,计算结果为 60
。类似地, 0xFp-2
代表 15 x 2⁻²,计算结果为 3.75
。
负浮点字面量通过在浮点字面量前添加一个负号 ( -
) 来表示,如 -42.5
。
数字之间允许使用下划线 ( _
) 以提高可读性,但它们会被忽略,因此不会影响字面量的值。浮点字面量可以以前导零 ( 0
) 开头,但它们同样被忽略,不会影响字面量的基数或值。
除非另有说明,浮点文字的默认推断类型是 Swift 标准库类型 Double
,该类型表示 64 位浮点数。Swift 标准库还定义了 Float
类型,表示 32 位浮点数。
浮点字面量的语法
floating-point-literal → decimal-literal decimal-fraction? decimal-exponent?
&#xNAN;floating-point-literal → hexadecimal-literal hexadecimal-fraction? hexadecimal-exponentdecimal-fraction →
.
decimal-literal
&#xNAN;decimal-exponent → floating-point-e sign? decimal-literalhexadecimal-fraction →
.
hexadecimal-digit hexadecimal-literal-characters?
&#xNAN;hexadecimal-exponent → floating-point-p sign? decimal-literalfloating-point-e →
e
|E
&#xNAN;floating-point-p →p
|P
&#xNAN;sign →+
|-
字符串字面量
字符串字面量是由引号包围的一系列字符。单行字符串字面量由双引号包围,具有以下形式:
"<#characters#>"
字符串字面量不能包含未转义的双引号 ( "
)、未转义的反斜杠 ( \
)、回车符或换行符。
多行字符串字面量由三个双引号包围,具有以下形式:
"""
<#characters#>
"""
与单行字符串字面量不同,多行字符串字面量可以包含未转义的双引号 ( "
)、回车符和换行符。它不能包含三个未转义的双引号相邻。
在开始多行字符串字面量的 """
之后的换行符不是字符串的一部分。在结束字面量的 """
之前的换行符也不是字符串的一部分。要创建一个以换行符开头或结尾的多行字符串字面量,请在其第一行或最后一行写一个空行。
多行字符串字面量可以使用空格和制表符的任意组合进行缩进;该缩进不包含在字符串中。结束字面量的 """
决定了缩进:字面量中的每一行非空白行必须以与闭合的 """
前出现的完全相同的缩进开始;制表符和空格之间没有转换。您可以在该缩进后包含额外的空格和制表符;这些空格和制表符将出现在字符串中。
多行字符串字面量中的换行符会被规范化为使用换行符字符。即使您的源文件中混合了回车符和换行符,字符串中的所有换行符也将是相同的。
在多行字符串字面量中,行末写入反斜杠 ( \
) 会从字符串中省略该换行符。在反斜杠和换行符之间的任何空白也将被省略。您可以使用此语法在源代码中强制换行多行字符串字面量,而不改变结果字符串的值。
可以使用以下转义序列在单行和多行形式的字符串字面量中包含特殊字符:
- 空字符 (
\0
) - 反斜杠 (
\\
) - 水平制表符 ( )
- 换行 ( )
- 回车 ( )
- 双引号 (
\"
) - 单引号 (
\'
) - Unicode 标量 (
\u{
n}
),其中 n 是一个具有一到八位数字的十六进制数
表达式的值可以通过在反斜杠后将表达式放在括号中( \
)插入到字符串字面量中。插入的表达式可以包含字符串字面量,但不能包含未转义的反斜杠、回车符或换行符。
例如,以下所有字符串字面量具有相同的值:
"1 2 3"
"1 2 \("3")"
"1 2 \(3)"
"1 2 \(1 + 2)"
let x = 3; "1 2 \(x)"
由扩展分隔符限定的字符串是被引号包围并且用一个或多个数字符号( #
)平衡的一系列字符。由扩展分隔符限定的字符串具有以下形式:
#"<#characters#>"#
#"""
<#characters#>
"""#
由扩展分隔符限定的字符串中的特殊字符在结果字符串中以普通字符的形式出现,而不是以特殊字符的形式出现。您可以使用扩展分隔符来创建具有通常会产生特殊效果的字符的字符串,例如生成字符串插值、启动转义序列或终止字符串。
以下示例显示了一个字符串字面量和一个由扩展分隔符限定的字符串,它们创建了等效的字符串值:
let string = #"\(x) \ " \u{2603}"#
let escaped = "\\(x) \\ \" \\u{2603}"
print(string)
// Prints "\(x) \ " \u{2603}"
print(string == escaped)
// Prints "true"
如果您使用多个数字符号来形成由扩展分隔符分隔的字符串,请不要在数字符号之间放置空格:
print(###"Line 1\###nLine 2"###) // OK
print(# # #"Line 1\# # #nLine 2"# # #) // Error
使用扩展定界符创建的多行字符串字面量具有与常规多行字符串字面量相同的缩进要求。
字符串字面量的默认推断类型是 String
。有关 String
类型的更多信息,请参见字符串和字符以及 String
。
通过 +
运算符连接的字符串字面量在编译时连接。例如,下面示例中的 textA
和 textB
的值是相同的——不执行运行时连接。
let textA = "Hello " + "world"
let textB = "Hello world"
字符串字面量的语法
string-literal → static-string-literal | interpolated-string-literal
string-literal-opening-delimiter → extended-string-literal-delimiter?
"
&#xNAN;string-literal-closing-delimiter →"
extended-string-literal-delimiter?static-string-literal → string-literal-opening-delimiter quoted-text? string-literal-closing-delimiter
&#xNAN;static-string-literal → multiline-string-literal-opening-delimiter multiline-quoted-text? multiline-string-literal-closing-delimitermultiline-string-literal-opening-delimiter → extended-string-literal-delimiter?
"""
&#xNAN;multiline-string-literal-closing-delimiter →"""
extended-string-literal-delimiter?
&#xNAN;extended-string-literal-delimiter →#
extended-string-literal-delimiter?quoted-text → quoted-text-item quoted-text?
&#xNAN;quoted-text-item → escaped-character
&#xNAN;quoted-text-item → Any Unicode scalar value except"
,\
, U+000A, or U+000Dmultiline-quoted-text → multiline-quoted-text-item multiline-quoted-text?
&#xNAN;multiline-quoted-text-item → escaped-character
&#xNAN;multiline-quoted-text-item → Any Unicode scalar value except\
&#xNAN;multiline-quoted-text-item → escaped-newlineinterpolated-string-literal → string-literal-opening-delimiter interpolated-text? string-literal-closing-delimiter
&#xNAN;interpolated-string-literal → multiline-string-literal-opening-delimiter multiline-interpolated-text? multiline-string-literal-closing-delimiterinterpolated-text → interpolated-text-item interpolated-text?
&#xNAN;interpolated-text-item →\(
expression)
| quoted-text-itemmultiline-interpolated-text → multiline-interpolated-text-item multiline-interpolated-text?
&#xNAN;multiline-interpolated-text-item →\(
expression)
| multiline-quoted-text-itemescape-sequence →
\
extended-string-literal-delimiter
&#xNAN;escaped-character → escape-sequence0
| escape-sequence\
| escape-sequencet
| escape-sequencen
| escape-sequencer
| escape-sequence"
| escape-sequence'
&#xNAN;escaped-character → escape-sequenceu
{
unicode-scalar-digits}
&#xNAN;unicode-scalar-digits → Between one and eight hexadecimal digitsescaped-newline → escape-sequence inline-spaces? line-break
正则表达式字面量
正则表达式字面量是一系列字符,以斜杠( /
)为边界,具有以下形式:
/<#regular expression#>/
正则表达式字面量不得以未转义的制表符或空格开头,并且不能包含未转义的斜杠 ( /
)、回车符或换行符。
在正则表达式字面量中,反斜杠被理解为该正则表达式的一部分,而不仅仅是像字符串字面量中的转义字符。它表示后面的特殊字符应被字面解释,或者后面的非特殊字符应以特殊方式解释。例如, /\(/
匹配一个左括号, /\d/
匹配一个数字。
用扩展定界符分隔的正则表达式字面量是由斜杠( /
)和一个或多个井号( #
)所包围的一系列字符。用扩展定界符分隔的正则表达式字面量具有以下形式:
#/<#regular expression#>/#
#/
<#regular expression#>
/#
一个使用扩展定界符的正则表达式字面量可以以未转义的空格或制表符开头,包含未转义的斜杠 ( /
),并跨越多行。对于多行正则表达式字面量,开始定界符必须放在行末,结束定界符必须单独放在一行上。在多行正则表达式字面量中,扩展正则表达式语法默认是启用的——具体来说,空格会被忽略,注释是允许的。
如果您使用多个数字符号来形成一个由扩展定界符限定的正则表达式字面量,请勿在数字符号之间放置空格:
let regex1 = ##/abc/## // OK
let regex2 = # #/abc/# # // Error
如果您需要创建一个空的正则表达式字面量,必须使用扩展分隔符语法。
正则表达式字面量的语法
regular-expression-literal → regular-expression-literal-opening-delimiter regular-expression regular-expression-literal-closing-delimiter
&#xNAN;regular-expression → Any regular expressionregular-expression-literal-opening-delimiter → extended-regular-expression-literal-delimiter?
/
&#xNAN;regular-expression-literal-closing-delimiter →/
extended-regular-expression-literal-delimiter?extended-regular-expression-literal-delimiter →
#
extended-regular-expression-literal-delimiter?
运算符
Swift 标准库定义了许多供您使用的运算符,其中许多在基本运算符和高级运算符中进行了讨论。本节描述了可以用于定义自定义运算符的字符。
自定义运算符可以以 ASCII 字符 /
, =
, -
, +
, !
, *
, %
, <
, >
, &
, |
, ^
, ?
, 或 ~
开头,或者以下面语法中定义的 Unicode 字符开头(包括来自数学运算符、杂项符号和装饰符 Unicode 块的字符等)。在第一个字符之后,也允许组合 Unicode 字符。
您还可以定义以点 ( .
) 开头的自定义运算符。这些运算符可以包含额外的点。例如, .+.
被视为一个单一的运算符。如果运算符不以点开头,则它不能在其他地方包含点。例如, +.+
被视为 +
运算符后跟 .+
运算符。
虽然您可以定义包含问号 ( ?
) 的自定义运算符,但它们不能仅由一个问号字符组成。此外,尽管运算符可以包含感叹号 ( !
),后缀运算符不能以问号或感叹号开头。
注意
令牌
=
,->
,//
,/*
,*/
,.
, 前缀运算符<
,&
, 和?
, 中缀运算符?
, 以及后缀运算符>
,!
, 和?
是保留的。这些令牌不能被重载,也不能用作自定义运算符。
操作符周围的空格用于确定操作符是用作前缀操作符、后缀操作符还是中缀操作符。此行为遵循以下规则:
- 如果操作符两侧都有空格或两侧都没有空格,则将其视为中缀操作符。例如,
+++
操作符在a+++b
和a +++ b
中被视为中缀操作符。 - 如果操作符左侧只有空格,则将其视为前缀一元操作符。例如,
+++
操作符在a +++b
中被视为前缀一元操作符。 - 如果操作符右侧只有空格,则将其视为后缀一元操作符。例如,
+++
操作符在a+++ b
中被视为后缀一元操作符。 - 如果一个运算符左侧没有空格,但紧接着有一个点 (
.
),它会被当作后缀一元运算符。举例来说,+++
运算符在a+++.b
中被视为后缀一元运算符 (a+++ .b
而不是a +++ .b
)。
根据这些规则,在运算符之前的字符 (
、 [
和 {
,运算符之后的字符 )
、 ]
和 }
,以及字符 ,
、 ;
和 :
也被视为空格。
如果 !
或 ?
预定义运算符左侧没有空格,那么它将被视为后缀运算符,无论右侧是否有空格。要将 ?
作为可选链运算符使用,左侧不能有空格。要将其用于三元条件 ( ?
:
) 运算符,必须在两侧都有空格。
如果一个中缀运算符的参数之一是正则表达式字面量,那么该运算符的两侧必须有空格。
在某些结构中,具有前导 <
或 >
的操作符可能会被拆分为两个或多个标记。其余部分以相同方式处理,并可能再次拆分。因此,您无需添加空格以消除像 Dictionary<String, Array<Int>>
中的闭合 >
字符之间的歧义。在此示例中,闭合 >
字符不被视为一个单一标记,因此不会被误解为位移 >>
操作符。
要了解如何定义新的自定义运算符,请参阅自定义运算符和运算符声明。要了解如何重载现有运算符,请参阅运算符方法。
运算符的语法
operator → operator-head operator-characters?
&#xNAN;operator → dot-operator-head dot-operator-characters
operator-head → /
| =
| -
| +
| !
| *
| %
| <
| >
| &
| |
| ^
| ~
| ?
&#xNAN;operator-head → U+00A1–U+00A7
&#xNAN;operator-head → U+00A9 or U+00AB
&#xNAN;operator-head → U+00AC or U+00AE
&#xNAN;operator-head → U+00B0–U+00B1
&#xNAN;operator-head → U+00B6, U+00BB, U+00BF, U+00D7, or U+00F7
&#xNAN;operator-head → U+2016–U+2017
&#xNAN;operator-head → U+2020–U+2027
&#xNAN;operator-head → U+2030–U+203E
&#xNAN;operator-head → U+2041–U+2053
&#xNAN;operator-head → U+2055–U+205E
&#xNAN;operator-head → U+2190–U+23FF
&#xNAN;operator-head → U+2500–U+2775
&#xNAN;operator-head → U+2794–U+2BFF
&#xNAN;operator-head → U+2E00–U+2E7F
&#xNAN;operator-head → U+3001–U+3003
&#xNAN;operator-head → U+3008–U+3020
&#xNAN;operator-head → U+3030
operator-character → operator-head
&#xNAN;operator-character → U+0300–U+036F
&#xNAN;operator-character → U+1DC0–U+1DFF
&#xNAN;operator-character → U+20D0–U+20FF
&#xNAN;operator-character → U+FE00–U+FE0F
&#xNAN;operator-character → U+FE20–U+FE2F
&#xNAN;operator-character → U+E0100–U+E01EF
&#xNAN;operator-characters → operator-character operator-characters?
dot-operator-head → .
&#xNAN;dot-operator-character → .
| operator-character
&#xNAN;dot-operator-characters → dot-operator-character dot-operator-characters?
infix-operator → operator
&#xNAN;prefix-operator → operator
&#xNAN;postfix-operator → operator