词汇结构
Swift的词汇结构描述了哪些字符序列构成语言的有效标记。这些有效令牌构成语言的最低级构建块,用于在随后的章节中描述其余语言。令牌由标识符,关键字,标点符号,文字或运算符组成。
在大多数情况下,通过考虑输入文本中最长的子字符串,在下面指定的语法约束内,从Swift源文件的字符中生成令牌。这种行为被称为最长匹配或最大蒙克。
空白和评论
空白有两个用途:分隔源文件中的标记并帮助确定运算符是前缀还是后缀(请参阅运算符),但忽略它。以下字符被认为是空格:space (U+0020), line feed (U+000A), carriage return (U+000D), horizontal tab (U+0009), vertical tab (U+000B), form feed (U+000C) and null (U+0000).
编译器将注释视为空白。单行注释以//开头并继续,直到换行(U + 000A)或回车(U + 000D)。多行注释以/ *开头并以* /结尾。嵌套多行注释是允许的,但注释标记必须平衡。
GRAMMAR OF WHITESPACE
whitespace → whitespace-item-whitespace-opt-
whitespace-item → line-break-
whitespace-item → comment-
whitespace-item → multiline-comment-
whitespace-item → U+0000, U+0009, U+000B, U+000C, or U+0020
line-break → U+000A
line-break → U+000D
line-break → U+000D followed by U+000A
comment → //-comment-text-line-break-
multiline-comment → /*-multiline-comment-text-*/-
comment-text → comment-text-item-comment-text-opt-
comment-text-item → Any Unicode scalar value except U+000A or U+000D
multiline-comment-text → multiline-comment-text-item-multiline-comment-text-opt-
multiline-comment-text-item → multiline-comment-
multiline-comment-text-item → comment-text-item-
multiline-comment-text-item → Any Unicode scalar value except /*- or */-
注释可以包含其他格式和标记,如标记格式参考中所述。
身份标识
标识符以大写或小写字母A到Z,下划线(_),基本多语言平面中的非合并字母数字Unicode字符或基本多语言平面外部不在私用区域中的字符开头。 在第一个字符之后,数字和组合Unicode字符也被允许。
要使用保留字作为标识符,请在它之前和之后加上反引号(`)。 例如,类不是有效的标识符,但`class`是有效的。 反引号不被视为标识符的一部分; `x`和x具有相同的含义。
在没有显式参数名称的闭包中,这些参数隐式命名为$ 0,$ 1,$ 2等等。 这些名称是封闭范围内的有效标识符。
GRAMMAR OF AN IDENTIFIER
identifier → identifier-head-identifier-characters-opt-
identifier → `-identifier-head-identifier-characters-opt-`-
identifier → implicit-parameter-name-
identifier-list → identifier-identifier-,-identifier-list-
identifier-head → Upper- or lowercase letter A through Z
identifier-head → _-
identifier-head → U+00A8, U+00AA, U+00AD, U+00AF, U+00B2–U+00B5, or U+00B7–U+00BA
identifier-head → U+00BC–U+00BE, U+00C0–U+00D6, U+00D8–U+00F6, or U+00F8–U+00FF
identifier-head → U+0100–U+02FF, U+0370–U+167F, U+1681–U+180D, or U+180F–U+1DBF
identifier-head → U+1E00–U+1FFF
identifier-head → U+200B–U+200D, U+202A–U+202E, U+203F–U+2040, U+2054, or U+2060–U+206F
identifier-head → U+2070–U+20CF, U+2100–U+218F, U+2460–U+24FF, or U+2776–U+2793
identifier-head → U+2C00–U+2DFF or U+2E80–U+2FFF
identifier-head → U+3004–U+3007, U+3021–U+302F, U+3031–U+303F, or U+3040–U+D7FF
identifier-head → U+F900–U+FD3D, U+FD40–U+FDCF, U+FDF0–U+FE1F, or U+FE30–U+FE44
identifier-head → U+FE47–U+FFFD
identifier-head → U+10000–U+1FFFD, U+20000–U+2FFFD, U+30000–U+3FFFD, or U+40000–U+4FFFD
identifier-head → U+50000–U+5FFFD, U+60000–U+6FFFD, U+70000–U+7FFFD, or U+80000–U+8FFFD
identifier-head → U+90000–U+9FFFD, U+A0000–U+AFFFD, U+B0000–U+BFFFD, or U+C0000–U+CFFFD
identifier-head → U+D0000–U+DFFFD or U+E0000–U+EFFFD
identifier-character → Digit 0 through 9
identifier-character → U+0300–U+036F, U+1DC0–U+1DFF, U+20D0–U+20FF, or U+FE20–U+FE2F
identifier-character → identifier-head-
identifier-characters → identifier-character-identifier-characters-opt-
implicit-parameter-name → $-decimal-digits-
关键字和标点符号
以下关键字是保留的,不能用作标识符,除非它们使用反引号进行转义,如上面在标识符中所述。 除inout,var和let以外的关键字可以用作函数声明或函数调用中的参数名称,而不用反引号进行转义。 当成员具有与关键字相同的名称时,对该成员的引用不需要使用反引号进行转义,除非在引用成员和使用关键字之间存在歧义,例如self,Type和Protocol有特殊含义 意思是在一个明确的成员表达式中,所以它们必须在该上下文中用反引号进行转义。
在声明中使用的关键字: associatedtype, class,deinit,extension, fileprivate,func,import,init,inout,internal,let,open,operator,private,protocol,public,static,struct,subscript,typealias and var。
在语句中使用的关键字:break,case,continue,default,defer,do,else,fallthrough,for,guard,if,in,repeat,return,switch,where和while。
在表达式和类型中使用的关键字:as,any,catch,false,is,nil,rethrows,super,self,self,throw,throws,true,and try
用于模式的关键字:_。
以数字符号(#)开头的关键字:#available,#colorLiteral,#column,#else,#elseif,#endif,#file,#fileLiteral,#function,#if,#imageLiteral,#line,#selector,和#sourceLocation。
关键字保留在特定的上下文中:associativity, convenience, dynamic,didSet,final,get,infix,indirect,lazy,left,mutating,none,nonmutating,optional,override,postfix,precedence,prefix,Protocol,required,right,set,Type, unowned,weak和willSet。在语法出现的上下文之外,它们可以用作标识符。
以下标记保留为标点符号,不能用作自定义运算符:(,),{,},[,],。,,,:,;,=,@,#,&(作为前缀运算符) , - >,`,?和! (作为后缀运算符)。
文字
文字是类型值的源代码表示,例如数字或字符串。
以下是文字的例子:
42// Integer literal
3.14159// Floating-point literal
"Hello, world!"// String literal
true// Boolean literal
文字本身没有类型。相反,一个文字被解析为具有无限精度,而Swift的类型推断试图推断文字的类型。例如,在声明中 let x:Int8 = 42,Swift使用显式类型注释(:Int8)来推断整数文字42的类型是Int8。如果没有合适的类型信息,Swift推断文字的类型是Swift标准库中定义的默认文字类型之一。缺省类型是整数文字的Int,浮点文字的双精度,字符串文字的字符串以及布尔文字的布尔。例如,在声明let str =“Hello,world”中,字符串文字“Hello,world”的默认推断类型是String。
在为文字值指定类型注释时,注释的类型必须是可以从该文字值实例化的类型。也就是说,类型必须符合下列特标准库协议之一:ExpressibleByIntegerLiteral为整数常量,ExpressibleByFloatLiteral仅含有一个单一的Unicode标浮点文字,ExpressibleByStringLiteral为字符串常量,ExpressibleByBooleanLiteral为布尔文字,ExpressibleByUnicodeScalarLiteral为字符串文字而ExpressibleByExtendedGraphemeClusterLiteral用于仅包含单个扩展字形群集的字符串文字。例如,Int8符合ExpressibleByIntegerLiteral协议,因此可以在声明let x:Int8 = 42中用于整数常量42的类型注释。
GRAMMAR OF A LITERAL
literal → numeric-literal-string-literal-boolean-literal-nil-literal-
numeric-literal → --opt-integer-literal---opt-floating-point-literal-
boolean-literal → true-false-
nil-literal → nil-
整数文字
整数文字表示未指定精度的整数值。默认情况下,整数文字用十进制表示;您可以使用前缀指定备用基准。二进制文字以0b开头,八进制文字以0开头,十六进制文字以0x开头。
十进制文字包含数字0到9.二进制文字包含0和1,八进制文字包含0到7,十六进制文字包含0到9以及A到F,大写或小写。
如-42所示,负整数文字通过在整数文字前加一个减号( - )来表示。
为了便于阅读,数字之间允许有下划线(_),但它们会被忽略,因此不会影响文字的值。整数文字可以从前导零(0)开始,但它们同样被忽略,不会影响文字的基数或值。
除非另有说明,否则整数文字的默认推断类型是Swift标准库类型Int。 Swift标准库还定义了各种大小的有符号和无符号整数的类型,如整数中所述。
GRAMMAR OF AN INTEGER LITERAL
integer-literal → binary-literal-
integer-literal → octal-literal-
integer-literal → decimal-literal-
integer-literal → hexadecimal-literal-
binary-literal → 0b-binary-digit-binary-literal-characters-opt-
binary-digit → Digit 0 or 1
binary-literal-character → binary-digit-_-
binary-literal-characters → binary-literal-character-binary-literal-characters-opt-
octal-literal → 0o-octal-digit-octal-literal-characters-opt-
octal-digit → Digit 0 through 7
octal-literal-character → octal-digit-_-
octal-literal-characters → octal-literal-character-octal-literal-characters-opt-
decimal-literal → decimal-digit-decimal-literal-characters-opt-
decimal-digit → Digit 0 through 9
decimal-digits → decimal-digit-decimal-digits-opt-
decimal-literal-character → decimal-digit-_-
decimal-literal-characters → decimal-literal-character-decimal-literal-characters-opt-
hexadecimal-literal → 0x-hexadecimal-digit-hexadecimal-literal-characters-opt-
hexadecimal-digit → Digit 0 through 9, a through f, or A through F
hexadecimal-literal-character → hexadecimal-digit-_-
hexadecimal-literal-characters → hexadecimal-literal-character-hexadecimal-literal-characters-opt-
浮点文字
浮点文字表示未指定精度的浮点值。
默认情况下,浮点文字以十进制表示(不带前缀),但也可以用十六进制表示(带有0x前缀)。
十进制浮点文字由一串十进制数字组成,后跟一个小数部分,一个小数指数或两者。小数部分由一个小数点(。)和一串十进制数字组成。指数由一个大写或小写的e前缀组成,后跟一个十进制数字序列,表示e乘以10之前的值的幂。例如,1.25e2代表1.25 x 102,评估为125.0。类似地,1.25e-2表示1.25×10-2,其评估为0.0125。
十六进制浮点文字包含一个0x前缀,后跟一个可选的十六进制小数,后跟一个十六进制指数。十六进制小数由一个小数点组成,后跟一串十六进制数字。指数由一个大写或小写p前缀组成,后跟一个十进制数字序列,表示p乘以2之前的值的幂。例如,0xFp2代表15 x 22,计算结果为60.同样,0xFp-2代表15 x 2-2,计算结果为3.75。
如-42.5所示,负浮点文字通过在浮点文字前加一个减号( - )来表示。
为了便于阅读,数字之间允许有下划线(_),但会被忽略,因此不会影响文字的值。浮点文字可以从前导零(0)开始,但同样被忽略,不会影响文字的基数或值。
除非另有说明,浮点文字的默认推断类型是Swift标准库类型Double,它表示一个64位浮点数。 Swift标准库还定义了一个浮点类型,它表示一个32位浮点数。
GRAMMAR OF A FLOATING-POINT LITERAL
floating-point-literal → decimal-literal-decimal-fraction-opt-decimal-exponent-opt-
floating-point-literal → hexadecimal-literal-hexadecimal-fraction-opt-hexadecimal-exponent-
decimal-fraction → .-decimal-literal-
decimal-exponent → floating-point-e-sign-opt-decimal-literal-
hexadecimal-fraction → .-hexadecimal-digit-hexadecimal-literal-characters-opt-
hexadecimal-exponent → floating-point-p-sign-opt-decimal-literal-
floating-point-e → e-E-
floating-point-p → p-P-
sign → +---
字符串文字
字符串文字是由引号包围的一系列字符。 单行字符串文字由双引号包围,并具有以下格式:
"characters"
字符串文字不能包含未转义的双引号(“),未转义的反斜杠(\),回车符或换行符。
多行字符串由三个双引号包围,并具有以下形式:
"""
characters
与单行字符串不同,多行字符串可以包含未引号的双引号(“),回车符和换行符,它们不能包含三个彼此相邻的未引号的双引号。
“”“开始多行字符串文字之后的换行符不是字符串的一部分,”“”之前的换行结束符也不是字符串的一部分。要制作以换行符开始或结束的多行字符串文字,请将空行写为第一行或最后一行。
多行字符串文字可以使用空格和制表符的任意组合缩进;这个缩进不包含在字符串中。结束文字的“”“决定缩进:文字中的每一个非空行必须以与关闭”“”之前出现的完全相同的缩进开始;标签和空格之间没有转换。您可以在缩进之后添加更多空格和制表符;这些空格和制表符显示在字符串中。
将多行字符串文本中的换行符标准化为使用换行符。即使您的源文件混合了回车符和换行符,字符串中的所有换行符都是相同的。
在多行字符串文字中,在行末写一个反斜杠(\)可省略该字符串中的换行符。反斜杠和换行符之间的任何空格也被忽略。您可以使用此语法在源代码中硬编码多行字符串文字,而不更改结果字符串的值。
使用以下转义序列,可以在单行和多行表单的字符串文字中包含特殊字符:
空字符(\ 0)
反斜线(\\)
水平标签(\ t)
换行(\ n)
回车(\ r)
双引号(\“)
单引号(\')
Unicode标量(\ u {n}),其中n是一个具有一到八位数字的十六进制数字
表达式的值可以通过将反斜杠(\)后的括号中的表达式插入到字符串文字中。 插入的表达式可以包含字符串文字,但不能包含未转义的反斜杠,回车符或换行符。
例如,以下所有字符串文字都具有相同的值:
"1 2 3"
"1 2 \("3")"
"1 2 \(3)"
"1 2 \(1 + 2)"
letx = 3; "1 2 \(x)"
字符串文字的默认推断类型是String。 有关String类型的更多信息,请参阅字符串和字符以及字符串结构参考。
串联的字符串由+运算符在编译时连接在一起。 例如,以下示例中textA和textB的值是相同的 - 不执行运行时级联。
lettextA = "Hello " + "world"
lettextB = "Hello world”
一串文字的格雷玛
字符串文字→静态字符串文字插值字符串文字
static-string-literal→“quoted-textopt”
static-string-literal→“”“multiline-quoted-textopt”“”
quoted-text→quoted-text-itemquoted-textopt
quoted-text-item→escaped-character
quoted-text-item→除“,\,U + 000A或U + 000D以外的任何Unicode标量值
multiline-quoted-text→multiline-quoted-text-itemmultiline-quoted-textopt
多行引用文本项目→转义字符
multiline-quoted-text-item→任何Unicode标量值,除\
multiline-quoted-text-item→escaped-newline
interpolated-string-literal→“interpolated-textopt”
interpolated-string-literal→“”“multiline-interpolated-textopt”“”
插入文本→插入文本迭代过滤文本opt
interpolated-text-item→\(expression)quoted-text-item
多线插值文本→多线插值文本迭代多线插值textopt
多行插值文本项目→\(表达式)多行引用文本项目
escaped-character→\ 0 \\ \ t \ n \ r \“\'
escapeped-character→\ u {unicode-scalar-digits}
unicode-scalar-digits→一到八个十六进制数字
escaped-newline→\ whitespaceoptline-break
运算符
Swift标准库定义了一些供您使用的运算符,其中许多运算符在Basic Operators和Advanced Operators中进行了讨论。本节描述哪些字符可用于定义自定义运算符。
自定义运算符可以以ASCII字符/,=, - ,+,!,*,%,<,>,&,|,^,?或?,或下面语法中定义的一个Unicode字符开头(其中包括来自数学运算符,杂项符号和标志Unicode块等的字符)。在第一个字符之后,还允许组合Unicode字符。
您还可以定义以点(。)开头的自定义运算符。这些操作员可以包含更多的点。例如,。+。被视为单个运营商。如果操作员不以点开始,则不能在别处包含点。例如,+。+被视为+运算符,后跟。+运算符。
虽然您可以定义包含问号(?)的自定义运算符,但它们不能仅由单个问号字符组成。此外,虽然运算符可以包含感叹号(!),但后缀运算符不能以问号或感叹号开头。
注意
tokens =, - >,//,/ *,* /,。,前缀运算符<,&和?,中缀运算符?和后缀运算符>,!和?被保留。这些令牌不能被重载,也不能被用作自定义操作符。
运算符周围的空白用于确定运算符是用作前缀运算符,后缀运算符还是二元运算符。以下规则总结了此行为:
如果操作员在两侧或两侧都有空白,则将其视为二元运算符。例如,+++ b和+++ b中的+++运算符被视为二元运算符。
如果运算符仅在左侧有空白,则将其视为前缀一元运算符。例如,+++ b中的+++运算符被视为前缀一元运算符。
如果一个操作符仅在右侧有空白,它将被视为后缀一元运算符。例如,+++ b中的+++运算符被视为后缀一元运算符。
如果一个操作符在左边没有空格,但后面紧跟着一个点(。),那么它将被视为后缀一元运算符。例如,+++。b中的+++运算符被视为后缀一元运算符(a +++ .b而不是+++ .b)。
出于这些规则的目的,字符(,[,和{在运算符之前的字符),]和}之后,运算符,以及字符,,;和:也被视为空白。
对上述规则有一个警告。如果!要么 ?预定义的运算符在左侧没有空白,它将被视为后缀运算符,而不管它是否在右侧有空白。要使用?作为可选链接运算符,它的左侧不能有空格。要在三元条件(?:)运算符中使用它,它必须在两边都有空白。
在某些结构中,具有前导<或>的运算符可能会拆分为两个或更多个标记。其余部分以相同方式处理,并可能再次分裂。因此,不需要使用空格来消除结构中的闭包>字符之间的歧义,如Dictionary <String,Array <Int >>。在这个例子中,关闭>字符不被视为一个单一的标记,可能会被误解为一个位移>>操作符。
要了解如何定义新的自定义运算符,请参阅自定义运算符和运算符声明。 要了解如何超载现有的运算符,请参阅运算符方法
运算符的语法
operator→operator-headoperator-charactersopt
运算符→点运算符headdot运算符字符
operator-head→/ = - +!*%<>&| ^??
操作员头→U + 00A1-U + 00A7
操作员头→U + 00A9或U + 00AB
操作员头→U + 00AC或U + 00AE
操作员头→U + 00B0-U + 00B1,U + 00B6,U + 00BB,U + 00BF,U + 00D7或U + 00F7
操作员头→U + 2016-U + 2017或U + 2020-U + 2027
操作员头→U + 2030-U + 203E
操作员头→U + 2041-U + 2053
操作员头→U + 2055-U + 205E
操作员头→U + 2190-U + 23FF
操作员头→U + 2500-U + 2775
操作员头→U + 2794-U + 2BFF
操作员头→U + 2E00-U + 2E7F
操作员头→U + 3001-U + 3003
操作员头→U + 3008-U + 3030
操作员字符→操作员头
运营商字符→U + 0300-U + 036F
运算符→U + 1DC0-U + 1DFF
运算符→U + 20D0-U + 20FF
运营商字符→U + FE00-U + FE0F
运算符→U + FE20-U + FE2F
操作符→U + E0100-U + E01EF
operator-characters→operator-characteroperator-charactersopt
点操作员头→。
点运算符字符→。运算符字符
点运算符字符→点运算符字符点运算符字符opt
二元运算符→运算符
前缀运算符→运算符
后缀运算符→运算符