Skip to content

Here's the content formatted in Markdown:

Swift 的词法结构

Swift 的词法结构描述了哪些字符序列构成了该语言的有效标记。这些有效标记构成了该语言的最低级构建块,并在后续章节中用于描述该语言的其他部分。标记由标识符、关键字、标点符号、字面量或运算符组成。

在大多数情况下,标记是根据 Swift 源文件中的字符生成的,方法是考虑输入文本中尽可能长的子字符串,并遵循下文指定的语法约束。此行为称为最长匹配或最大匹配 (maximal munch)。

空格和注释

空格有两种用途:分隔源文件中的标记以及区分前缀、后缀和中缀运算符(参见运算符),否则将被忽略。以下字符被视为空格:

  • 空格 (U+0020)
  • 换行符 (U+000A)
  • 回车符 (U+000D)
  • 水平制表符 (U+0009)
  • 垂直制表符 (U+000B)
  • 换页符 (U+000C)
  • 空字符 (U+0000)

编译器将注释视为空格。单行注释以 // 开头,直到遇到换行符 (U+000A) 或回车符 (U+000D)。多行注释以 /* 开头,以 */ 结尾。允许嵌套多行注释,但注释标记必须匹配。

注释可以包含额外的格式和标记,如标记格式参考中所述。

空格语法

空格 → 空格项空格 ?
空格项 → 换行符
空白项 → 行内空间
空白项 → 注释
空格项 → 多行注释
空白项 → U+0000、U+000B 或 U+000C

换行符 → U+000A
换行符 → U+000D
换行符 → U+000D 后跟 U+000A

内联空间 → 内联空间内联空间 ?
行内空间 → U+0009 或 U+0020

评论 → // 评论文本换行
多行注释 → /* 多行注释文本 */

评论文本 → 评论文本项评论文本 ?
注释文本项 → 除 U+000A 或 U+000D 之外的任何 Unicode 标量值

多行注释文本 → 多行注释文本项多行注释文本 ?
多行注释文本项 → 多行注释
多行注释文本项 → 注释文本项
多行注释文本项 → 除 /* 或 */ 之外的任何 Unicode 标量值

标识符

标识符以 A 到 Z 的大写或小写字母、下划线 ( _ )、基本多文种平面 (BMPP) 中的非组合字母数字 Unicode 字符或基本多文种平面 (BMPP) 之外且不属于私有使用区的字符开头。在第一个字符之后,也可以使用数字和组合 Unicode 字符。

将以下划线开头的标识符、第一个参数标签以下划线开头的下标以及第一个参数标签以下划线开头的初始化器视为内部的,即使它们的声明带有 public 访问级别修饰符。此约定允许框架作者标记 API 的一部分,使客户端不得与之交互或依赖,即使某些限制要求该声明为公共的。此外,以两个下划线开头的标识符保留给 Swift 编译器和标准库使用。

要将保留字用作标识符,请在其前后添加反引号 ()。例如,class不是有效标识符,但 ``class `` 是有效的。反引号不被视为标识符的一部分; x x` 含义相同。

在没有显式指定参数名称的闭包中,参数会被隐式地命名为 $0$1$2 等等。这些名称在闭包作用域内是有效的标识符。

对于具有属性包装器投影的属性,编译器会合成以美元符号 ( $ ) 开头的标识符。您的代码可以与这些标识符交互,但您不能声明带有该前缀的标识符。有关更多信息,请参阅 "属性" 章节的 propertyWrapper 部分。

标识符语法

标识符 → 标识符头标识符字符 ?
标识符 → ` 标识符头标识符字符 ? `
标识符 → 隐式参数名称
标识符 → 属性包装器投影
标识符列表 → 标识符 | 标识符 , 标识符列表

标识符头 → 大写或小写字母 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
标识符字符 → 标识符头
标识符字符 → 标识符字符标识符字符 ?

隐式参数名称 → $ 十进制数字
属性包装器投影 → $ 标识符字符

关键词和标点符号

以下关键字是保留关键字,不能用作标识符,除非使用反引号进行转义,如上文标识符中所述。inoutvarlet 之外的关键字均可用作函数声明或函数调用中的参数名称,而无需使用反引号进行转义。当成员与关键字同名时,对该成员的引用无需使用反引号进行转义,除非引用成员和使用关键字之间存在歧义 - 例如,selfTypeProtocol 在显式成员表达式中具有特殊含义,因此在该上下文中必须使用反引号进行转义。

声明中使用的关键字

associatedtypeborrowingclassconsumingdeinitenumextensionfileprivatefuncimportinitinoutinternalletnonisolatedopenoperatorprecedencegroupprivateprotocolpublicrethrowsstaticstructsubscripttypealiasvar

语句中使用的关键字

breakcasecatchcontinuedefaultdeferdoelsefallthroughforguardifinrepeatreturnswitchthrowwherewhile

表达式和类型中使用的关键字

AnyasawaitcatchfalseisnilrethrowsselfSelfsuperthrowthrowstruetry

模式中使用的关键字

_

以数字符号 (#) 开头的关键字

#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 标准库中以宏的形式实现:columndsohandleerror(_:)fileIDfilePathfilefunctionlinewarning(_:)

在特定上下文中保留的关键字

associativityasyncconveniencedidSetdynamicfinalgetindirectinfixlazyleftmutatingnonenonmutatingoptionaloverridepackagepostfixprecedenceprefixProtocolrequiredrightsetsomeTypeunownedweakwillSet。在它们出现在语法中的上下文之外,它们可以用作标识符。

保留的标点符号

以下标记保留为标点符号,不能用作自定义运算符:

(){}[].,:;=@#&(作为前缀运算符)、->`?!(作为后缀运算符)。

文字

文字是某种类型值的源代码表示,例如数字或字符串。

以下是文字的示例:

swift
42               // 整数字面量
3.14159          // 浮点数字面量
"Hello, world!"  // 字符串字面量
/Hello, .*/      // 正则表达式字面量
true             // 布尔字面量

字面量本身没有类型。相反,字面量会被解析为具有无限精度,并且 Swift 的类型推断会尝试推断该字面量的类型。例如,在声明 let x: Int8 = 42 中,Swift 使用显式类型注解 (: Int8) 推断整数字面量 42 的类型为 Int8。如果没有合适的类型信息,Swift 会推断该字面量的类型是 Swift 标准库中定义的默认字面量类型之一,如下表所示。在为字面量值指定类型注解时,注解的类型必须是可以从该字面量值实例化的类型。也就是说,该类型必须符合下表列出的 Swift 标准库协议。

文字类型默认类型协议
整数IntExpressibleByIntegerLiteral
浮点DoubleExpressibleByFloatLiteral
字符串StringExpressibleByStringLiteral, ExpressibleByUnicodeScalarLiteral(仅包含单个 Unicode 标量的字符串文字), ExpressibleByExtendedGraphemeClusterLiteral(仅包含单个扩展字素簇的字符串文字)
正则表达式Regex
布尔值BoolExpressibleByBooleanLiteral

例如,在声明 let str = "Hello, world" 中,字符串字面量 "Hello, world" 的默认推断类型为 String。此外,Int8 符合 ExpressibleByIntegerLiteral 协议,因此它可以在声明 let x: Int8 = 42 中用作整数字面量 42 类型注解。

文字语法

文字 → 数字文字 | 字符串文字 | 正则表达式文字 | 布尔文字 | 零文字

数字文字 → - ? 整数文字 | - ? 浮点文字
布尔值文字 → true | false
零字面量 → nil

整数文字

整数字面量表示未指定精度的整数值。默认情况下,整数字面量以十进制表示;您可以使用前缀指定其他进制。二进制数字面量以 0b 开头,八进制数字面量以 0o 开头,十六进制数字面量以 0x 开头。

十进制字面值包含数字 09。二进制字面值包含 01,八进制字面值包含 07,十六进制字面值包含 09 以及大写或小写的 AF

负整数文字通过在整数文字前面添加减号(-)来表示,如 -42

为了提高可读性,数字之间可以使用下划线 (_),但它们会被忽略,因此不会影响字面量的值。整数字面量可以以零 (0) 开头,但它们同样会被忽略,并且不会影响字面量的基数或值。

除非另有说明,整数字面量的默认推断类型是 Swift 标准库中的 Int 类型。Swift 标准库还定义了各种大小的有符号和无符号整数类型,如 Integers 中所述。

整数文字语法

整数字面量 → 二进制字面量
整数字面量 → 八进制数字面量
整数字面值 → 十进制数字面值
整数字面量 → 十六进制数字面量

二进制文字 → 0b 二进制数字二进制文字字符 ?
二进制数字 → 数字 0 或 1
二进制文字字符 → 二进制数字 | _
二进制文字字符 → 二进制文字字符二进制文字字符 ?

八进制文字 → 0o 八进制数字八进制文字字符 ?
八进制数字 → 数字 0 到 7
八进制文字字符 → 八进制数字 | _
八进制文字字符 → 八进制文字字符八进制文字字符 ?

十进制文字 → 十进制数字十进制文字字符 ?
十进制数字 → 数字 0 到 9
十进制数字 → 十进制数字十进制数字 ?
十进制文字字符 → 十进制数字 | _
十进制文字字符 → 十进制文字字符十进制文字字符 ?

十六进制文字 → 0x 十六进制数字十六进制文字字符 ?
十六进制数字 → 数字 0 至 9、a 至 f 或 A 至 F
十六进制文字字符 → 十六进制数字 | _
十六进制文字字符 → 十六进制文字字符十六进制文字字符 ?

浮点文字

浮点文字表示未指定精度的浮点值。

默认情况下,浮点文字以十进制表示(无前缀),但也可以用十六进制表示(带有 0x 前缀)。

十进制浮点字面量由一串十进制数字组成,后跟十进制小数、十进制指数或两者兼有。小数部分由一个小数点 (.) 和一串十进制数字组成。指数部分由大写或小写的 e 前缀和一串十进制数字组成,表示 e 前面的值乘以 10 的多少次方。例如,1.25e2 表示 1.25 × 10²,其计算结果为 125.0。同样,1.25e-2 表示 1.25 × 10⁻²,其计算结果为 0.0125

十六进制浮点字面量由 0x 前缀、后跟可选的十六进制小数部分和十六进制指数组成。十六进制小数部分由小数点后跟一串十六进制数字组成。指数部分由大写或小写的 p 前缀和后跟一串十进制数字组成,这些数字指示 p 前面的值乘以 2 的多少次方。例如,0xFp2 表示 15 × 2²,其值为 60。类似地,0xFp-2 表示 15 × 2⁻²,其值为 3.75

负浮点文字通过在浮点文字前面添加减号(-)来表示,如 -42.5

为了提高可读性,数字之间可以使用下划线 (_),但它们会被忽略,因此不会影响字面量的值。浮点字面量可以以零 (0) 开头,但它们同样会被忽略,并且不会影响字面量的基数或值。

除非另有说明,浮点字面量的默认推断类型是 Swift 标准库中的 Double 类型,它表示 64 位浮点数。Swift 标准库还定义了一个 Float 类型,它表示 32 位浮点数。

浮点文字语法

浮点文字 → 十进制文字十进制分数 ? 十进制指数 ?
浮点文字 → 十六进制文字十六进制分数 ? 十六进制指数

十进制小数 → . 十进制字面量
十进制指数 → 浮点数 e 符号 ? 十进制字面量

十六进制小数 → . 十六进制数字十六进制文字字符 ?
十六进制指数 → 浮点数 p 符号 ? 十进制字面量

浮点数-e → e | E
浮点数-p → p | P
符号 → + | -

字符串文字

字符串字面量是用引号括起来的字符序列。单行字符串字面量用双引号括起来,形式如下:

swift
"<#characters#>"

字符串文字不能包含未转义的双引号 (")、未转义的反斜杠 (\)、回车符或换行符。

多行字符串文字由三个双引号引起来,具有以下形式:

swift
"""
<#characters#>
"""

与单行字符串文字不同,多行字符串文字可以包含未转义的双引号 (")、回车符和换行符。它不能包含三个相邻的未转义的双引号。

多行字符串字面值以 """ 开头的换行符不属于字符串。多行字符串字面值以 """ 结尾的换行符也不属于字符串。要创建以换行符开头或结尾的多行字符串字面值,请将空行作为其首行或末行。

多行字符串字面量可以使用空格和制表符的任意组合进行缩进;此缩进不包含在字符串中。字面量结尾的 """ 决定了缩进:字面量中每个非空行的开头缩进必须与结尾 """ 之前的缩进完全相同;制表符和空格之间不存在转换。您可以在缩进后添加额外的空格和制表符;这些空格和制表符会显示在字符串中。

多行字符串字面量中的换行符会被规范化为使用换行符。即使源文件中混合了回车符和换行符,字符串中的所有换行符都将保持不变。

在多行字符串字面量中,在行尾写入反斜杠 (\) 会省略字符串中的换行符。反斜杠和换行符之间的任何空格也将被省略。您可以使用此语法在源代码中对多行字符串字面量进行硬换行,而不改变结果字符串的值。

可以使用以下转义序列将特殊字符包含在单行和多行形式的字符串文字中:

  • 空字符 (\0)
  • 反斜杠 (\\)
  • 水平制表符 (\t)
  • 换行符 (\n)
  • 回车符 (\r)
  • 双引号 (\")
  • 单引号 (\')
  • Unicode 标量 (\u{n}),其中 n 是一到八位十六进制数

可以将表达式的值插入到字符串文字中,方法是将表达式放在反斜杠 (\) 后的括号中。内插表达式可以包含字符串文字,但不能包含未转义的反斜杠、回车符或换行符。

例如,以下所有字符串文字都具有相同的值:

swift
"1 2 3"
"1 2 \("3")"
"1 2 \(3)"
"1 2 \(1 + 2)"
let x = 3; "1 2 \(x)"

由扩展分隔符分隔的字符串是由引号和一个或多个井号 (#) 组成的字符序列。由扩展分隔符分隔的字符串具有以下形式:

swift
#"<#characters#>"#

#"""
<#characters#>
"""#

使用扩展分隔符分隔的字符串中的特殊字符在结果字符串中显示为普通字符,而不是特殊字符。您可以使用扩展分隔符来创建包含通常具有特殊效果(例如生成字符串插值、启动转义序列或终止字符串)的字符的字符串。

以下示例显示了一个字符串文字和一个由扩展分隔符分隔的字符串,它们创建了等效的字符串值:

swift
let string = #"\(x) \ " \u{2603}"#
let escaped = "\\(x) \\ \" \\u{2603}"
print(string)
// 打印 "\(x) \ " \u{2603}"
print(string == escaped)
// 打印 "true"

如果使用多个数字符号来形成由扩展分隔符分隔的字符串,请不要在数字符号之间放置空格:

swift
print(###"Line 1\###nLine 2"###) // 正确
print(# # #"Line 1\# # #nLine 2"# # #) // 错误

使用扩展分隔符创建的多行字符串文字具有与常规多行字符串文字相同的缩进要求。

字符串字面量的默认推断类型为 String。有关 String 类型的更多信息,请参阅字符串和字符以及 String

使用 + 运算符连接的字符串字面量在编译时进行连接。例如,以下示例 textAtextB 的值相同——无需执行运行时连接。

swift
let textA = "Hello " + "world"
let textB = "Hello world"

字符串文字的语法

字符串文字 → 静态字符串文字 | 插值字符串文字

字符串文字开始分隔符 → 扩展字符串文字分隔符 ? "
字符串文字结束分隔符 → " 扩展字符串文字分隔符 ?

静态字符串文字 → 字符串文字开头分隔符引用文本 ? 字符串文字结尾分隔符
静态字符串文字 → 多行字符串文字开头分隔符多行引用文本 ? 多行字符串文字结尾分隔符

多行字符串文字开始分隔符 → 扩展字符串文字分隔符 ? """
多行字符串文字结束分隔符 → """ 扩展字符串文字分隔符 ?
扩展字符串文字分隔符 → # 扩展字符串文字分隔符 ?

引用文本 → 引用文本项引用文本 ?
引用文本项 → 转义字符
引用文本项 → 除 " 、 \ 、U+000A 或 U+000D 之外的任何 Unicode 标量值

多行引用文本 → 多行引用文本项多行引用文本 ?
多行引用文本项 → 转义字符
多行引用文本项 → 除 \ 之外的任何 Unicode 标量值
多行引用文本项 → 转义换行符

插值字符串文字 → 字符串文字开头分隔符插值文本 ? 字符串文字结尾分隔符
插值字符串文字 → 多行字符串文字开头分隔符多行插值文本 ? 多行字符串文字结尾分隔符

插值文本 → 插值文本项插值文本 ?
插值文本项 → \( 表达式 ) | 引用文本项

多行插值文本 → 多行插值文本项多行插值文本 ?
多行插值文本项 → \( 表达式 ) | 多行引用文本项

转义序列 → \ 扩展字符串文字分隔符
转义字符 → 转义序列 0 | 转义序列 \ | 转义序列 t | 转义序列 n | 转义序列 r | 转义序列 " | 转义序列 '
转义字符 → 转义序列 u { unicode 标量数字 }
unicode-scalar-digits → 一至八个十六进制数字

转义换行符 → 转义序列行内空格 ? 换行符

正则表达式文字

正则表达式文字是由斜杠(/)包围的字符序列,其形式如下:

swift
/<#regular expression#>/

正则表达式文字不能以未转义的制表符或空格开头,并且不能包含未转义的斜杠 (/)、回车符或换行符。

在正则表达式字面量中,反斜杠会被理解为该正则表达式的一部分,而不仅仅是像字符串字面量中那样被理解为转义符。它表示后面的特殊字符应该按字面意思解释,或者后面的非特殊字符应该以特殊方式解释。例如,/\(/ 匹配一个左括号,/\d/ 匹配一个数字。

由扩展分隔符分隔的正则表达式字面量是由斜杠 (/) 和一个或多个井号 (#) 组成的字符序列。由扩展分隔符分隔的正则表达式字面量具有以下形式:

swift
#/<#regular expression#>/#


#/
<#regular expression#>
/#

使用扩展分隔符的正则表达式字面值可以以未转义的空格或制表符开头,包含未转义的斜杠 (/),并且可以跨越多行。对于多行正则表达式字面值,开始分隔符必须位于行尾,结束分隔符必须独占一行。在多行正则表达式字面值中,扩展正则表达式语法默认启用——具体来说,空格会被忽略,注释可以输入。

如果使用多个数字符号来形成由扩展分隔符分隔的正则表达式文字,请不要在数字符号之间放置空格:

swift
let regex1 = ##/abc/##       // 正确
let regex2 = # #/abc/# #     // 错误

如果需要创建空的正则表达式文字,则必须使用扩展分隔符语法。

正则表达式文字的语法

正则表达式文字 → 正则表达式文字开始分隔符正则表达式正则表达式文字结束分隔符
正则表达式 → 任意正则表达式

正则表达式文字开始分隔符 → 扩展正则表达式文字分隔符 ? /
正则表达式文字结束分隔符 → / 扩展正则表达式文字分隔符 ?

扩展正则表达式文字分隔符 → # 扩展正则表达式文字分隔符 ?

运算符

Swift 标准库定义了许多运算符供您使用,其中许多运算符在基本运算符和高级运算符中进行了讨论。本节介绍哪些字符可用于定义自定义运算符。

自定义运算符可以以 ASCII 字符 /=-+!*%<>&|^?~ 开头,也可以以以下语法中定义的 Unicode 字符开头(其中包括来自数学运算符、杂项符号和 Dingbats Unicode 块的字符等)。在第一个字符之后,还可以组合 Unicode 字符。

您还可以定义以点 (.) 开头的自定义运算符。这些运算符可以包含其他点。例如,.+. 被视为单个运算符。如果运算符不是以点开头,则它不能在其他地方包含点。例如,+.+ 被视为 + 运算符后跟 .+ 运算符。

虽然您可以定义包含问号 (?) 的自定义运算符,但它们不能仅由一个问号字符组成。此外,虽然运算符可以包含感叹号 (!),但后缀运算符不能以问号或感叹号开头。

注意: 标记 =->///**/.,前缀运算符 <&?,中缀运算符 ?,以及后缀运算符 >!? 是保留的。这些标记不能被重载,也不能用作自定义运算符。

运算符周围的空格用于确定运算符是用作前缀运算符、后缀运算符还是中缀运算符。此行为具有以下规则:

  1. 如果运算符两侧都有空格,或者两侧都没有空格,则将其视为中缀运算符。例如,a+++ba +++ b 中的 +++ 运算符被视为中缀运算符。
  2. 如果运算符左侧只有空格,则将其视为前缀一元运算符。例如,a +++b 中的 +++ 运算符被视为前缀一元运算符。
  3. 如果运算符仅在右侧有空格,则将其视为后缀一元运算符。例如,a+++ b 中的 +++ 运算符被视为后缀一元运算符。
  4. 如果运算符左侧没有空格,但后面紧跟着一个点 (.),则该运算符将被视为后缀一元运算符。例如,a+++.b 中的 +++ 运算符将被视为后缀一元运算符(a+++ .b 而不是 a +++ .b)。

为了达到这些规则的目的,运算符前的字符 ([{ 运算符后的字符 )]},以及字符 ,;: 也被视为空格。

如果 !? 预定义运算符左侧没有空格,则无论其右侧是否有空格,都会被视为后缀运算符。要将 ? 用作可选链运算符,其左侧必须没有空格。要将其用作三元条件运算符 (? :),其两侧必须都有空格。

如果中缀运算符的参数之一是正则表达式文字,则该运算符两侧必须有空格。

在某些结构中,以 <> 开头的运算符可能会被拆分成两个或多个标记。其余部分将按相同方式处理,并可能再次拆分。因此,在类似 Dictionary<String, Array<Int>> 的结构中,无需添加空格来消除结尾 > 字符之间的歧义。在此示例中,结尾 > 字符不会被视为单个标记,否则可能会被误解为位移位 >> 运算符。

要了解如何定义新的自定义运算符,请参阅自定义运算符和运算符声明。要了解如何重载现有运算符,请参阅运算符方法。

运算符语法

运算符 → 运算符头运算符字符 ?
运算符 → 点运算符头点运算符字符

操作符头 → / | = | - | + | ! | * | % | < | > | & | | | ^ | ~ | ?
操作符头 → 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+3020
操作符头 → 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
操作符字符 → 操作符字符操作符字符 ?

点运算符头 → .
点运算符字符 → . | 运算符字符
点运算符字符 → 点运算符字符点运算符字符 ?

中缀运算符 → 运算符
前缀运算符 → 运算符
后缀运算符 → 运算符