➤原文地址:https://www.cnblogs.com/strengthen/p/9740123.html
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
词汇结构
Swift 的词法结构描述了什么样的字符序列形成了语言的有效标记。这些有效令牌构成语言的最低级构建块,用于描述后续章节中的其余语言。令牌由标识符,关键字,标点符号,文字或运算符组成。
在大多数情况下,通过在下面指定的语法约束内考虑输入文本中可能最长的子字符串,从Swift源文件的字符生成标记。此行为称为最长匹配或最大蒙克。
空白和评论
空白有两种用途:在源文件中分隔标记,并帮助确定运算符是前缀还是后缀(请参阅运算符),否则将被忽略。以下字符被视为空格:空格(U + 0020),换行符(U + 000A),回车符(U + 000D),水平制表符(U + 0009),垂直制表符(U + 000B),换页符(U + 000C)和null(U + 0000)。
编译器将注释视为空格。单行注释以行开头//(U + 000A)或回车符(U + 000D)开头并继续。多行注释以...开头/*并结束*/。允许嵌套多行注释,但必须平衡注释标记。
注释可以包含其他格式和标记,如标记格式参考中所述。
1 GRAMMAR OF WHITESPACE 2 3 whitespace → whitespace-item whitespace opt 4 5 whitespace-item → line-break 6 7 whitespace-item → comment 8 9 whitespace-item → multiline-comment 10 11 whitespace-item → U+0000, U+0009, U+000B, U+000C, or U+0020 12 13 line-break → U+000A 14 15 line-break → U+000D 16 17 line-break → U+000D followed by U+000A 18 19 comment → // comment-text line-break 20 21 multiline-comment → /* multiline-comment-text */ 22 23 comment-text → comment-text-item comment-text opt 24 25 comment-text-item → Any Unicode scalar value except U+000A or U+000D 26 27 multiline-comment-text → multiline-comment-text-item multiline-comment-text opt 28 29 multiline-comment-text-item → multiline-comment 30 31 multiline-comment-text-item → comment-text-item 32 33 multiline-comment-text-item → Any Unicode scalar value except /* or */
标识符
标识符以大写或小写字母A到Z,下划线(_),基本多语言平面中的非组合字母数字Unicode字符或基本多语言平面之外不在专用区域中的字符开头。在第一个字符之后,还允许使用数字和组合Unicode字符。
要使用保留字作为标识符,请`在其前后放置一个反引号(`)。例如,class不是有效的标识符,但是`class`有效。反引号不被视为标识符的一部分; `x`并x具有相同的含义。
有没有明确的参数名称的瓶盖内,参数被隐式命名$0,$1,$2,等等。这些名称是闭包范围内的有效标识符。
1 GRAMMAR OF AN IDENTIFIER 2 3 identifier → identifier-head identifier-characters opt 4 5 identifier → ` identifier-head identifier-characters opt ` 6 7 identifier → implicit-parameter-name 8 9 identifier-list → identifier | identifier , identifier-list 10 11 identifier-head → Upper- or lowercase letter A through Z 12 13 identifier-head → _ 14 15 identifier-head → U+00A8, U+00AA, U+00AD, U+00AF, U+00B2–U+00B5, or U+00B7–U+00BA 16 17 identifier-head → U+00BC–U+00BE, U+00C0–U+00D6, U+00D8–U+00F6, or U+00F8–U+00FF 18 19 identifier-head → U+0100–U+02FF, U+0370–U+167F, U+1681–U+180D, or U+180F–U+1DBF 20 21 identifier-head → U+1E00–U+1FFF 22 23 identifier-head → U+200B–U+200D, U+202A–U+202E, U+203F–U+2040, U+2054, or U+2060–U+206F 24 25 identifier-head → U+2070–U+20CF, U+2100–U+218F, U+2460–U+24FF, or U+2776–U+2793 26 27 identifier-head → U+2C00–U+2DFF or U+2E80–U+2FFF 28 29 identifier-head → U+3004–U+3007, U+3021–U+302F, U+3031–U+303F, or U+3040–U+D7FF 30 31 identifier-head → U+F900–U+FD3D, U+FD40–U+FDCF, U+FDF0–U+FE1F, or U+FE30–U+FE44 32 33 identifier-head → U+FE47–U+FFFD 34 35 identifier-head → U+10000–U+1FFFD, U+20000–U+2FFFD, U+30000–U+3FFFD, or U+40000–U+4FFFD 36 37 identifier-head → U+50000–U+5FFFD, U+60000–U+6FFFD, U+70000–U+7FFFD, or U+80000–U+8FFFD 38 39 identifier-head → U+90000–U+9FFFD, U+A0000–U+AFFFD, U+B0000–U+BFFFD, or U+C0000–U+CFFFD 40 41 identifier-head → U+D0000–U+DFFFD or U+E0000–U+EFFFD 42 43 identifier-character → Digit 0 through 9 44 45 identifier-character → U+0300–U+036F, U+1DC0–U+1DFF, U+20D0–U+20FF, or U+FE20–U+FE2F 46 47 identifier-character → identifier-head 48 49 identifier-characters → identifier-character identifier-characters opt 50 51 implicit-parameter-name → $ decimal-digits
关键词和标点符号
以下关键字是保留的,不能用作标识符,除非它们使用反引号进行转义,如上面标识符中所述。除了inout,var和之外的关键字let可用作函数声明或函数调用中的参数名称,而无需使用反引号进行转义。当成员具有相同的名称作为关键字,并不需要用反引号,转义除了指成员,并使用关键字,例如之间时,有歧义,以该成员引用self,Type以及Protocol在一个特殊的意义显式成员表达式,因此必须在该上下文中使用反引号进行转义。
-
:在声明中使用关键字
associatedtype,class,deinit,enum,extension,fileprivate,func,import,init,inout,internal,let,open,operator,private,protocol,public,static,struct,subscript,typealias,和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,和try。 -
模式中使用的关键字:
_。 -
以数字符号(开头关键词
#:) ,#available,#colorLiteral,#column,#else,#elseif,#endif,#error,#file,#fileLiteral,#function,#if,#imageLiteral,#line,#selector,#sourceLocation和#warning。
-
:在特定情况下保留关键字
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。在它们出现在语法中的上下文之外,它们可以用作标识符。
以下符号被保留作为标点符号,并且不能被用作运算符定制:(,),{,},[,],.,,,:,;,=,@,#,&(作为前缀运算符), ,->,`,?和!(作为后缀运算符)。
文字
文字是一种类型,的值的源代码的表示,诸如数字或字符串。
以下是文字的例子:
1 42 // Integer literal 2 3.14159 // Floating-point literal 3 "Hello, world!" // String literal 4 true // Boolean literal
文字本身没有类型。相反,文字被解析为具有无限精度,而Swift的类型推断试图推断文字的类型。例如,在声明,夫特使用明确的类型的注释(),以推断整数文字的类型是。如果没有合适的类型信息,Swift会推断文字的类型是Swift标准库中定义的默认文字类型之一。默认类型适用于整数文字,浮点文字,字符串文字和布尔文字。例如,在声明中,字符串文字的默认推断类型是。let x: Int8 = 42: Int842Int8IntDoubleStringBoollet str = "Hello, world""Hello, world"String
为文字值指定类型注释时,注释的类型必须是可以从该文字值实例化的类型。也就是说,类型必须符合以下Swift标准库协议之一:ExpressibleByIntegerLiteral用于整数文字,ExpressibleByFloatLiteral用于浮点文字,ExpressibleByStringLiteral用于字符串文字,ExpressibleByBooleanLiteral用于布尔文字,ExpressibleByUnicodeScalarLiteral用于仅包含单个Unicode标量ExpressibleByExtendedGraphemeClusterLiteral的字符串文字,以及用于字符串文字只包含一个扩展的字形集群。例如,Int8符合ExpressibleByIntegerLiteral协议,因此可以42在声明中的整数文字的类型注释中使用它。let x: Int8 = 42
1 GRAMMAR OF A LITERAL 2 3 literal → numeric-literal | string-literal | boolean-literal | nil-literal 4 5 numeric-literal → -opt integer-literal | -opt floating-point-literal 6 7 boolean-literal → true | false 8 9 nil-literal → nil
整数文字
整数文字表示未指定精度的整数值。默认情况下,整数文字以十进制表示; 您可以使用前缀指定备用基础。二进制文字以0b,八进制文字开头0o,十六进制文字开头0x。
十进制文本包含数字0通过9。二进制文字包含0和1,八进制文字包含0通过7,十六进制文字包含0通过9以及A通过F大写或小写。
负整数文字通过将减号(-)加到整数文字来表示,如-42。
_为了便于阅读,数字之间允许使用下划线(),但它们会被忽略,因此不会影响文字的值。整数文字可以0以前导零()开头,但它们同样被忽略,不会影响文字的基数或值。
除非另行指定,否则整数文字的默认推断类型是Swift标准库类型Int。Swift标准库还定义了各种大小的有符号和无符号整数的类型,如Integers中所述。
1 GRAMMAR OF AN INTEGER LITERAL 2 3 integer-literal → binary-literal 4 5 integer-literal → octal-literal 6 7 integer-literal → decimal-literal 8 9 integer-literal → hexadecimal-literal 10 11 binary-literal → 0b binary-digit binary-literal-characters opt 12 13 binary-digit → Digit 0 or 1 14 15 binary-literal-character → binary-digit | _ 16 17 binary-literal-characters → binary-literal-character binary-literal-characters opt 18 19 octal-literal → 0o octal-digit octal-literal-characters opt 20 21 octal-digit → Digit 0 through 7 22 23 octal-literal-character → octal-digit | _ 24 25 octal-literal-characters → octal-literal-character octal-literal-characters opt 26 27 decimal-literal → decimal-digit decimal-literal-characters opt 28 29 decimal-digit → Digit 0 through 9 30 31 decimal-digits → decimal-digit decimal-digits opt 32 33 decimal-literal-character → decimal-digit | _ 34 35 decimal-literal-characters → decimal-literal-character decimal-literal-characters opt 36 37 hexadecimal-literal → 0x hexadecimal-digit hexadecimal-literal-characters opt 38 39 hexadecimal-digit → Digit 0 through 9, a through f, or A through F 40 41 hexadecimal-literal-character → hexadecimal-digit | _ 42 43 hexadecimal-literal-characters → hexadecimal-literal-character hexadecimal-literal-characters opt
浮点文字
浮点文字表示未指定精度的浮点值。
默认情况下,浮点文字以十进制表示(没有前缀),但也可以用十六进制表示(带0x前缀)。
十进制浮点文字由一系列十进制数字组成,后跟小数部分,十进制指数或两者。小数部分由小数点(.)后跟一个十进制数字序列组成。指数由一个大写或小写e前缀后跟一个十进制数字序列组成,这些十进制数字表示e乘以前的值的10的幂。例如,1.25e2表示1.25 x 10 2,其评估结果为125.0。同样,1.25e-2代表1.25 x 10 -2,其评估结果为0.0125。
十六进制浮点文字由0x前缀组成,后跟可选的十六进制小数,后跟十六进制指数。十六进制小数由小数点后跟一系列十六进制数字组成。指数由一个大写或小写p前缀后跟一个十进制数字序列组成,这些十进制数字表示p乘以前的值的2的幂。例如,0xFp2表示15 x 2 2,其评估结果为60。同样,0xFp-2代表15 x 2 -2,其评估结果为3.75。
负浮点文字通过将减号(-)加到浮点文字来表示,如-42.5。
_为了便于阅读,数字之间允许使用下划线(),但它们会被忽略,因此不会影响文字的值。浮点文字可以0以前导零()开头,但它们同样被忽略,不会影响文字的基数或值。
除非另行指定,否则浮点文字的默认推断类型是Swift标准库类型Double,它表示64位浮点数。Swift标准库还定义了一个Float类型,它表示一个32位浮点数。
1 GRAMMAR OF A FLOATING-POINT LITERAL 2 3 floating-point-literal → decimal-literal decimal-fraction opt decimal-exponent opt 4 5 floating-point-literal → hexadecimal-literal hexadecimal-fraction opt hexadecimal-exponent 6 7 decimal-fraction → . decimal-literal 8 9 decimal-exponent → floating-point-e sign opt decimal-literal 10 11 hexadecimal-fraction → . hexadecimal-digit hexadecimal-literal-characters opt 12 13 hexadecimal-exponent → floating-point-p sign opt decimal-literal 14 15 floating-point-e → e | E 16 17 floating-point-p → p | P 18 19 sign → + | -
字符串文字
字符串文字是由引号括起来的字符序列。单行字符串文字由双引号括起,并具有以下形式:
"characters"
字符串文字不能包含未转义的双引号("),未转义的反斜杠(\),回车符或换行符。
多行字符串文字由三个双引号括起,并具有以下形式:
1 """ 2 characters 3 """
与单行字符串文字不同,多行字符串文字可以包含未转义的双引号("),回车符和换行符。它不能包含三个未转义的双引号。
在"""开始多行字符串文字后的换行符不是字符串的一部分。在"""结束文字之前的换行符也不是字符串的一部分。要创建以换行符开头或结尾的多行字符串文字,请将空行写为第一行或最后一行。
多行字符串文字可以使用空格和制表符的任意组合缩进; 此缩进不包含在字符串中。的"""表示结束文字确定压痕:在文字的每个非空行必须以精确地,所述关闭之前出现的相同缩进开始"""; 标签和空格之间没有转换。在缩进之后,您可以包含其他空格和制表符; 这些空格和制表符出现在字符串中。
多行字符串文字中的换行符被规范化以使用换行符。即使您的源文件混合了回车符和换行符,字符串中的所有换行符也是相同的。
在多行字符串文字中,\在行的末尾写一个反斜杠()会省略该字符串中的换行符。反斜杠和换行符之间的任何空格也被省略。您可以使用此语法在源代码中硬包装多行字符串文字,而不更改结果字符串的值。
使用以下转义序列,可以在单行和多行表单的字符串文字中包含特殊字符:
-
空字符(
\0) -
反斜杠(
\\) -
水平标签(
\t) -
换行(
\n) -
回车(
\r) -
双引号(
\") -
单引号(
\') -
Unicode标量(
\u{n}),其中n是十六进制数,有一到八位数
通过在反斜杠(\)之后将表达式放在括号中,可以将表达式的值插入到字符串文字中。插值表达式可以包含字符串文字,但不能包含未转义的反斜杠,回车符或换行符。
例如,以下所有字符串文字都具有相同的值:
1 "1 2 3" 2 "1 2 \("3")" 3 "1 2 \(3)" 4 "1 2 \(1 + 2)" 5 let x = 3; "1 2 \(x)"
字符串文字的默认推断类型是String。有关String类型的更多信息,请参阅字符串和字符和String。
由+运算符连接的字符串文字在编译时连接在一起。例如,以下示例中的textA和的值textB是相同的 - 不执行运行时级联。
1 let textA = "Hello " + "world" 2 let textB = "Hello world"
1 GRAMMAR OF A STRING LITERAL 2 3 string-literal → static-string-literal | interpolated-string-literal 4 5 static-string-literal → " quoted-text opt " 6 7 static-string-literal → """ multiline-quoted-text opt """ 8 9 quoted-text → quoted-text-item quoted-text opt 10 11 quoted-text-item → escaped-character 12 13 quoted-text-item → Any Unicode scalar value except ", \, U+000A, or U+000D 14 15 multiline-quoted-text → multiline-quoted-text-item multiline-quoted-text opt 16 17 multiline-quoted-text-item → escaped-character 18 19 multiline-quoted-text-item → Any Unicode scalar value except \ 20 21 multiline-quoted-text-item → escaped-newline 22 23 interpolated-string-literal → " interpolated-text opt " 24 25 interpolated-string-literal → """ multiline-interpolated-text opt """ 26 27 interpolated-text → interpolated-text-item interpolated-text opt 28 29 interpolated-text-item → \( expression ) | quoted-text-item 30 31 multiline-interpolated-text → multiline-interpolated-text-item multiline-interpolated-text opt 32 33 multiline-interpolated-text-item → \( expression ) | multiline-quoted-text-item 34 35 escaped-character → \0 | \\ | \t | \n | \r | \" | \' 36 37 escaped-character → \u { unicode-scalar-digits } 38 39 unicode-scalar-digits → Between one and eight hexadecimal digits 40 41 escaped-newline → \ whitespace opt line-break
运算符
Swift标准库定义了许多供您使用的运算符,其中许多运算符在Basic Operators和Advanced Operators中进行了讨论。本节描述了可以使用哪些字符来定义自定义运算符。
运算符定制可以使用ASCII字符中的一个开始/,=,-,+,!,*,%,<,>,&,|,^,?,或~,或在下面的语法中定义的Unicode字符(其包括从所述字符中的一个数学运算符,杂项符号,和装饰符号 Unicode块等等。在第一个字符之后,还允许组合Unicode字符。
您还可以定义以点(.)开头的自定义运算符。这些运算符可以包含其他点。例如,.+.被视为单个运算符。如果操作符不以点开头,则其他位置不能包含点。例如,+.+被视为+运算符后面的.+运算符。
虽然您可以定义包含问号(?)的自定义运算符,但它们不能仅包含单个问号字符。此外,虽然运算符可以包含感叹号(!),但后缀运算符不能以问号或感叹号开头。
注意
令牌=,->,//,/*,*/,.,前缀运算符<,&和?,中缀运算符?,而后缀运算符>,!以及?被保留。这些令牌不能超载,也不能用作自定义操作符。
运算符周围的空格用于确定运算符是用作前缀运算符,后缀运算符还是二元运算符。以下规则总结了此行为:
-
如果操作符在两侧或两侧都有空格,则将其视为二元运算符。例如,
+++运算符ina+++b和被视为二元运算符。a +++ b -
如果运算符仅在左侧有空格,则将其视为前缀一元运算符。例如,
+++运算符in 被视为前缀一元运算符。a +++b -
如果运算符仅在右侧有空格,则将其视为后缀一元运算符。例如,
+++运算符in 被视为后缀一元运算符。a+++ b -
如果运算符左侧没有空格但后面紧跟一个点(
.),则将其视为后缀一元运算符。例如,+++运算符ina+++.b被视为后缀一元运算符(而不是)。a+++ .ba +++ .b
对于这些规则的目的,人物(,[和{运算符之前,人物),]和}运算符,和人物之后,,;和:也被认为是空白。
上面的规则有一点需要注意。如果!或者?预定义的运算符在左侧没有空格,则将其视为后缀运算符,而不管它是否在右侧有空格。要使用?可选链接运算符,它必须在左侧没有空格。要在三元条件(? :)运算符中使用它,它必须在两边都有空格。
在某些构造中,具有前导<或>可能被分成两个或更多个令牌的运算符。其余部分以相同的方式处理,可能会再次拆分。因此,没有必要使用空格来消除>构造中的结束字符之间的歧义。在此示例中,结束字符不会被视为单个标记,然后可能会被误解为位移运算符。Dictionary<String, Array<Int>>>>>
要了解如何定义新的自定义运算符,请参阅自定义运算符和运算符声明。要了解如何使现有运算符重载,请参阅运算符方法。
1 GRAMMAR OF OPERATORS 2 3 operator → operator-head operator-characters opt 4 5 operator → dot-operator-head dot-operator-characters 6 7 operator-head → / | = | - | + | ! | * | % | < | > | & | | | ^ | ~ | ? 8 9 operator-head → U+00A1–U+00A7 10 11 operator-head → U+00A9 or U+00AB 12 13 operator-head → U+00AC or U+00AE 14 15 operator-head → U+00B0–U+00B1, U+00B6, U+00BB, U+00BF, U+00D7, or U+00F7 16 17 operator-head → U+2016–U+2017 or U+2020–U+2027 18 19 operator-head → U+2030–U+203E 20 21 operator-head → U+2041–U+2053 22 23 operator-head → U+2055–U+205E 24 25 operator-head → U+2190–U+23FF 26 27 operator-head → U+2500–U+2775 28 29 operator-head → U+2794–U+2BFF 30 31 operator-head → U+2E00–U+2E7F 32 33 operator-head → U+3001–U+3003 34 35 operator-head → U+3008–U+3020 or U+3030 36 37 operator-character → operator-head 38 39 operator-character → U+0300–U+036F 40 41 operator-character → U+1DC0–U+1DFF 42 43 operator-character → U+20D0–U+20FF 44 45 operator-character → U+FE00–U+FE0F 46 47 operator-character → U+FE20–U+FE2F 48 49 operator-character → U+E0100–U+E01EF 50 51 operator-characters → operator-character operator-characters opt 52 53 dot-operator-head → . 54 55 dot-operator-character → . | operator-character 56 57 dot-operator-characters → dot-operator-character dot-operator-characters opt 58 59 binary-operator → operator 60 61 prefix-operator → operator 62 63 postfix-operator → operator