-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlex.tex
460 lines (358 loc) · 15.9 KB
/
lex.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
%!TEX root = x.tex
\rSec0[lex]{词法约定}
\begin{bnf}{Token}
Identifier \br
Keyword \br
Punctuator \br
Literal \br
ClosureArgument \br
MacroInvocation
\end{bnf}
\begin{bnf}{TokenDelimited}
\terminal{(} TokenList\bnfq \terminal{)} \br
\terminal{[} TokenList\bnfq \terminal{]} \br
\terminal{\{} TokenList\bnfq \terminal{\}}
\end{bnf}
\begin{bnf}{TokenList}
TokenListItem\bnfp
\end{bnf}
\begin{bnf}{TokenListItem}
Token \textnormal{但不是} \terminal{( ) [ ] \{ \}} \br
TokenDelimited
\end{bnf}
\pnum
\term{程序文本}指将被翻译为\X{}程序的文本的整体或者一部分。它存储在\term{源文件}中,并以UTF-8编码读取。
\pnum
程序文本将被分割为\term{标记}的序列。标记是程序文本中的最小单元,包括标识符、关键字、标点符号、字面量、闭包参数。
除了少数地方,标记之间包含的空白字符或注释会被忽略。它们不影响程序含义。
\pnum
宏调用是特殊的标记,它将在编译时展开为标记序列。
\rSec1[lex.comment]{注释}
\pnum
有两种形式的\term{注释}:以\tcode{/*} 开始,\tcode{*/}结束的\term{块注释}和以\tcode{//} 开始,到行末结束的\term{行注释}。注释可以嵌套。在将程序文本分割为标记以后,注释和空白一起被删除。
\rSec1[lex.identifier]{标识符}
\begin{bnf}{Identifier}
NormalIdentifier \br
RawIdentifier
\end{bnf}
\begin{bnf}{NormalIdentifier}
IdentifierHead IdentifierTail\bnfs
\end{bnf}
\begin{bnf}{IdentifierHead}
Unicode(XID_Start) \br
\terminal{_}
\end{bnf}
\begin{bnf}{IdentifierTail}
IdentifierHead \br
Unicode(XID_Continue)
\end{bnf}
\begin{bnf}{RawIdentifier}
\terminal{`} RIchar\bnfp \terminal{`}
\end{bnf}
\begin{bnf}{RIchar}
\textnormal{除了\terminal{`}以外的非空白可打印字符} \br
\textnormal{空格}
\end{bnf}
\pnum
\term{标识符}以具有Unicode XID_Start属性的字符或\tcode{_}开始,后跟零个或数个具有Unicode XID_Continue属性的字符,但不能与关键字相同。标识符区分大小写。
\pnum
使用反引号包围的字符序列称为\term{原始标识符}。原始标识符可以用于将无法作为普通标识符的字符序列作为标识符使用。
\pnum
如果原始标识符中的字符序列是普通标识符的字符系列,则它与不带反引号的形式完全相同,但它不会被认为是关键字。
\pnum
原始标识符中不能包含空格以外的空白字符以及\tcode{`}。原始标识符不能以\tcode{\$}开头。
\rSec1[lex.keyword]{关键字}
\pnum
\begin{floattable}{关键字}{tab:keyword}{lllll}
\topline
\tcode{_} & \tcode{any} & \tcode{as} & \tcode{assert} & \tcode{async} \\
\tcode{await} & \tcode{auto} & \tcode{bool} & \tcode{borrow} & \tcode{break} \\
\tcode{catch} & \tcode{char} & \tcode{class} & \tcode{cmp} & \tcode{const} \\
\tcode{continue} & \tcode{defer} & \tcode{do} & \tcode{dyn} & \tcode{else} \\
\tcode{enum} & \tcode{extern} & \tcode{false} & \tcode{float} & \tcode{for} \\
\tcode{func} & \tcode{if} & \tcode{impl} & \tcode{import} & \tcode{in} \\
\tcode{infer} & \tcode{init} & \tcode{int} & \tcode{internal} & \tcode{is} \\
\tcode{let} & \tcode{macro} & \tcode{match} & \tcode{module} & \tcode{mut} \\
\tcode{never} & \tcode{nil} & \tcode{operator} & \tcode{partial} & \tcode{private} \\
\tcode{public} & \tcode{ref} & \tcode{return} & \tcode{self} & \tcode{shl} \\
\tcode{shl_eq} & \tcode{shr} & \tcode{shr_eq} & \tcode{some} & \tcode{static} \\
\tcode{string} & \tcode{this} & \tcode{throw} & \tcode{trait} & \tcode{true} \\
\tcode{try} & \tcode{type} & \tcode{typeof} & \tcode{uint} & \tcode{unsafe} \\
\tcode{void} & \tcode{while} & & & \\
\end{floattable}
\pnum
表~\ref{tab:context-keyword}~中的标识符称为\term{上下文关键字}。在特定的语法结构中它将被解析为关键字,在其他位置可以当作一般标识符使用。
\begin{floattable}{上下文关键字}{tab:context-keyword}{lllll}
\topline
\tcode{didSet} & \tcode{get} & \tcode{infix} & \tcode{lazy} & \tcode{once} \\
\tcode{prefix} & \tcode{root} & \tcode{set} & \tcode{suffix} & \tcode{super} \\
\tcode{then} & \tcode{willSet} & & & \\
\end{floattable}
\rSec1[lex.punc]{标点符号}
\indextext{标点符号}
\begin{bnf}{Punctuator}
PunctuatorPart\bnfp
\end{bnf}
\begin{bnf}{PunctuatorPart}[\oneof]
\terminal{\~ ! @ \# \$ \% \textasciicircum \& * ( ) - + = [ ] \{ \} | ; : ' < > , . ? /}
\end{bnf}
\pnum
\term{标点符号}由一个或数个符号组成,其中的一部分称为\term{运算符},参见~\ref{op}。
\pnum
除了多字符标点符号外,标点符号都由单个字符组成。表~\ref{tab:multichar-punc}~列出了内建的多字符标点,但不包含运算符。解析标点符号时,应尽可能长地匹配多字符标点符号。用户也可以自定义多字符运算符。
\begin{floattable}{多字符标点符号}{tab:multichar-punc}{lllll}
\topline
\tcode{'(} &
\tcode{->} &
\tcode{=>} &
\tcode{!!} &\\
\tcode{::} &
\tcode{...} &&&\\
\end{floattable}
\rSec1[lex.literal]{字面量}
\begin{bnf}{Literal}
IntegerLiteral \br
FloatingLiteral \br
StringLiteral \br
CharacterLiteral \br
SymbolLiteral \br
BooleanLiteral
\end{bnf}
\rSec2[literal.integer]{整数字面量}
\begin{bnf}{IntegerLiteral}
DecimalLiteral Suffix\bnfq \br
BinaryLiteral Suffix\bnfq \br
HexadecimalLiteral Suffix\bnfq
\end{bnf}
\begin{bnf}{DecimalLiteral}
Digits
\end{bnf}
\begin{bnf}{Digits}
Digit \br
Digits \terminal{'}\bnfq Digit
\end{bnf}
\begin{bnf}{Digit}[\oneof]
\terminal{0 1 2 3 4 5 6 7 8 9}
\end{bnf}
\begin{bnf}{BinaryLiteral}
\terminal{0b} BinaryDigit \bnflp\terminal{'}\bnfq BinaryDigit\bnfrp\bnfs
\end{bnf}
\begin{bnf}{BinaryDigit}
\terminal{0} \br
\terminal{1}
\end{bnf}
\begin{bnf}{HexadecimalLiteral}
\terminal{0x} HexadecimalDigits
\end{bnf}
\begin{bnf}{HexadecimalDigits}
HexadecimalDigit \br
HexadecimalDigits \terminal{'}\bnfs HexadecimalDigit
\end{bnf}
\begin{bnf}{HexadecimalDigit}[\oneof]
\terminal{0 1 2 3 4 5 6 7 8 9} \br
\terminal{A B C D E F} \br
\terminal{a b c d e f}
\end{bnf}
\pnum
整数字面量由一系列数字构成。可以使用单引号作分隔并且不影响字面量的值。字面量的前缀用于指示它的进制。\term{十进制字面量}由若干十进制数字构成;\term{十六进制字面量}由前缀\tcode{0x}后跟若干十六进制数字构成;\term{二进制字面量}前缀\tcode{0b}后跟若干二进制数字构成。\X 不支持八进制字面量。
\pnum
整数字面量的值为其数字序列表示的值,依不同前缀分别为十进制、十六进制或二进制。最左侧的数字为最高位。字面量的类型参见表格~\ref{tab:integer-suffix},其中$i$为其字面值:
\begin{floattable}{整数字面量后缀}{tab:integer-suffix}{c|c||c|c}
\topline
后缀 & 对应的类型 & 后缀 & 对应的类型 \\
\capsep
无 & $\tcode{int}_i$ & \tcode{u} & $\tcode{uint}_i$ \\
\tcode{i8} & $\tcode{int<8>}_i$ & \tcode{u8} & $\tcode{uint<8>}_i$ \\
\tcode{i16} & $\tcode{int<16>}_i$ & \tcode{u16} & $\tcode{uint<16>}_i$ \\
\tcode{i32} & $\tcode{int<32>}_i$ & \tcode{u32} & $\tcode{uint<32>}_i$ \\
\tcode{i64} & $\tcode{int<64>}_i$ & \tcode{u64} & $\tcode{uint<64>}_i$ \\
\tcode{i128} & $\tcode{int<128>}_i$ & \tcode{u128} & $\tcode{uint<128>}_i$ \\
\tcode{f16} & \tcode{float<16>} &
\tcode{f32} & \tcode{float<32>} \\
\tcode{f} 或 \tcode{f64} & \tcode{float<64>} &
\tcode{f128} & \tcode{float<128>} \\
\end{floattable}
如果字面量的字面值超出了其类型的约束范围,则这是一个编译错误。
\rSec2[literal.floating]{浮点字面量}
\begin{bnf}{FloatingLiteral}
DecimalFloatingLiteral Suffix\bnfq \br
HexadecimalFloatingLiteral Suffix\bnfq
\end{bnf}
\begin{bnf}{DecimalFloatingLiteral}
Digits \terminal{.} Digits ExponentPart\bnfq \br
Digits ExponentPart
\end{bnf}
\begin{bnf}{HexadecimalFloatingLiteral}
HexadecimalPrefix HexadecimalDigits \terminal{.} HexadecimalDigits BinaryExponentPart\bnfq \br
HexadecimalPrefix HexadecimalDigits BinaryExponentPart
\end{bnf}
\begin{bnf}{ExponentPart}
\terminal{e} Sign\bnfq Digit\bnfp \br
\terminal{E} Sign\bnfq Digit\bnfp
\end{bnf}
\begin{bnf}{BinaryExponentPart}
\terminal{p} Sign\bnfq Digit\bnfp \br
\terminal{P} Sign\bnfq Digit\bnfp
\end{bnf}
\begin{bnf}{Sign}[\oneof]
\terminal{+ -}
\end{bnf}
\pnum
浮点字面量用于表示浮点数,其中的单引号用作分隔并且不影响字面量的值。浮点字面量的小数点前后不允许省略数字。
\pnum
浮点字面量的类型按表~\ref{tab:floating-suffix}~确定。其值依如下方式确定:如果它包含指数部分,则命$e$为指数部分按十进制数字解析得到的数;否则,$e$为0。对十进制浮点字面量而言,命$s$为除去指数的部分按十进制数字解析得到的数,则令$f=s\times 10^e$。对十六进制浮点字面量而言,命$s$为除去指数的部分按十六进制数字解析得到的数,则令$f=s\times 2^e$。浮点字面量的值为其类型中最接近$f$的值。如果$f$太大,则值为对应的正无限大;如果$f$太小,则值为0。
\begin{floattable}{浮点字面量后缀}{tab:floating-suffix}{c|c}
\topline
后缀 & 对应的类型 \\
\capsep
\tcode{f16} & \tcode{float<16>} \\
\tcode{f32} & \tcode{float<32>} \\
无或\tcode{f64} & \tcode{float<64>} \\
\tcode{f128} & \tcode{float<128>} \\
\end{floattable}
\rSec2[literal.string]{字符串字面量}
\begin{bnf}{StringLiteral}
\terminal{"} Schar\bnfs \terminal{"} Suffix\bnfq \br
\terminal{@}\bnfp \terminal{"} Rchar\bnfs \terminal{"} \terminal{@}\bnfp Suffix\bnfq
\end{bnf}
\begin{bnf}{Schar}
\textnormal{除了\terminal{\textbackslash}和\terminal{"}以外的可打印字符} \br
EscapeSeq \br
TextInterpolation
\end{bnf}
\begin{bnf}{EscapeSeq}
\terminal{\textbackslash} SimpleEscape \br
\terminal{\textbackslash{}u\{} HexadecimalDigit\bnfp \terminal{\}}
\end{bnf}
\begin{bnf}{TextInterpolation}
\terminal{\textbackslash{}(} Expression \terminal{)}
\end{bnf}
\begin{bnf}{SimpleEscape}[\oneof]
\terminal{0 ' " \textbackslash{} a b f n r t v}
\end{bnf}
\begin{bnf}{Rchar}
\textnormal{可打印字符} \br
RawTextInterpolation
\end{bnf}
\begin{bnf}{RawTextInterpolation}
\terminal{\textbackslash} \terminal{@}\bnfp \terminal{(} Expression \terminal{)}
\end{bnf}
\pnum
字符串字面量表示UTF-8字符串,其类型为\tcode{string}。
普通字符串字面量被双引号包围。其中可以使用反斜杠开始的转义序列表示其他字符。
普通字符串字面量也可以前后加上等量的\tcode{@},此时它被称为\term{原始字符串字面量}。原始字符串字面量中的反斜杠不会被解释为转义序列,而是字符本身。
\pnum
字符串字面量可以横跨多行,但其开头引号必须为其所在行的最后一个字符,且结尾的引号必须为其所在行的第一个非空白字符。
结尾引号之前的所有空白字符将作为这个字符串字面量的\term{行前缀}。
开头引号到结尾引号之间的所有字符(包括换行符)按顺序成为该字符串字面量的内容,但除了以下字符:
\begin{itemize}
\item 开头引号之后紧邻的换行;
\item 每一行的行前缀;
\item 结尾引号前一行的换行符;
\item 如果一行末尾有反斜杠,这个反斜杠和其后的换行符。
\end{itemize}
换行符会变成\tcode{'\textbackslash{}n'}。
如果开始引号后不是换行符,或者结束引号前有非空白字符,这是一个编译错误。
如果行前缀不是某一行的前缀,这是一个编译错误。
\enterexample
表~\ref{tab:multiline-string}~是一些多行字符串字面量及其等价的单行表示:
\begin{floattable}{多行字符串字面量示例}{tab:multiline-string}{l|l}
\topline
\begin{codeblock}
"
abc
"
\end{codeblock}
&\tcode{"abc"}\\
\hline
\begin{codeblock}
"
abc\
def
"
\end{codeblock}
&\tcode{"abcdef"}\\
\hline
\begin{codeblock}
"
abc
"
\end{codeblock}
&编译错误,空格不是公共前缀\\
\hline
\begin{codeblock}
"
abc
"
\end{codeblock}
&\tcode{"\textbackslash{}nabc\textbackslash{}n"}\\
\hline
\end{floattable}
\exitexample
\pnum
字符串字面量可以包含字符串插值,其形式为\tcode{\textbackslash($e$)},其中$e$为表达式。字符串插值会被求值后转换为字符串插入当前位置。对原始字符串字面量而言,反斜杠和括号之间需要插入等量的\tcode{@},否则仍然会被解释为字面符号。
\rSec2[literal.char]{字符字面量}
\begin{bnf}{CharacterLiteral}
\terminal{'} Character \terminal{'}
\end{bnf}
\begin{bnf}{Character}
\textnormal{除了\terminal{\textbackslash}和\terminal{'}以外的非换行可打印字符} \br
EscapeSeq
\end{bnf}
\pnum
字符字面量表示单个字符,其类型为\tcode{char}。字符字面量由单引号包围,其中的字符可以是除了单引号和反斜杠以外的任意字符,或者转义序列。
\rSec2[literal.symbol]{符号字面量}
\begin{bnf}{SymbolLiteral}
\terminal{'} Identifier
\end{bnf}
\pnum
符号字面量用于标识成员名称,其类型和其值为其标识符的值。
\rSec2[literal.boolean]{布尔字面量}
\begin{bnf}{BooleanLiteral}
\terminal{true} \br
\terminal{false}
\end{bnf}
$$ \tcode{true} \coloneqq \langle \mathrm{true}, \tcode{bool} \rangle $$
$$ \tcode{false} \coloneqq \langle \mathrm{false}, \tcode{bool} \rangle $$
\pnum
布尔字面量的类型为\tcode{bool}。\tcode{true}和\tcode{false}分别对应其真值与假值。
\rSec2[literal.suffix]{字面量后缀}
\begin{bnf}{Suffix}
\terminal{_}\bnfq SuffixIdentifier
\end{bnf}
\begin{bnf}{SuffixIdentifier}
SuffixIdentifierHead SuffixIdentifierTail\bnfs
\end{bnf}
\begin{bnf}{SuffixIdentifierHead}
Unicode(XID_Start)
\end{bnf}
\begin{bnf}{SuffixIdentifierTail}
SuffixIdentifierHead \br
Unicode(XID_Continue)
\end{bnf}
\pnum
整数、浮点数与字符串能带有内建或用户自定义的后缀。后缀由字母开始,后跟任意数量的字母或数字,字面量与后缀之间可以添加\tcode{_}分隔。用户自定义的后缀不能与内建后缀相同,否则这是一个编译错误。
\pnum
自定义后缀的规则与标识符相同,但会自动去除前导的\tcode{_}。如果前导的下划线多于一个,这是一个编译错误。
自定义后缀不能与内建后缀相同。
\enterexample
\begin{codeblock}
IntegerLiteral<'s>; // 后缀为\tcode{s}
IntegerLiteral<'_s>; // 错误,后缀不能包含前导下划线
0x0123ABC; // 没有后缀
0x0123_ABC; // 后缀为\tcode{ABC},下划线用作区分
\end{codeblock}
\exitexample
\pnum
特征\tcode{IntegerLiteral}、\tcode{FloatingLiteral}、\tcode{StringLiteral}、\tcode{CharacterLiteral}用于实现具有特定后缀的字面量。
如果有多于一个类型实现了相同的后缀或者提供了非法的后缀,这是一个编译错误。
\rSec1[lex.closure-args]{闭包参数}
\begin{bnf}{ClosureArgument}
\terminal{\$} Digit\bnfp \br
\terminal{\$} Identifier
\end{bnf}
\pnum
闭包参数只能在闭包作用域(\ref{scope.closure})中使用,用于引用匿名参数。其类型是待推导的。
不在闭包作用域中使用闭包参数,或在显式指定参数的闭包表达式中使用闭包参数,是一个编译错误。
\pnum
\tcode{\$}后跟数字$i$指代第$i$个参数。\tcode{\$}后跟标识符$n$指代具名参数$n$。它们只能出现在不含参数列表的闭包表达式中,且\tcode{\$}与后续的数字或标识符之间不能有空白。