1// Copyright 2017 The Wuffs Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//    https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package token
16
17// MaxIntBits is the largest size (in bits) of the i8, u8, i16, u16, etc.
18// integer types.
19const MaxIntBits = 64
20
21// ID is a token type. Every identifier (in the programming language sense),
22// keyword, operator and literal has its own ID.
23//
24// Some IDs are built-in: the "func" keyword always has the same numerical ID
25// value. Others are mapped at runtime. For example, the ID value for the
26// "foobar" identifier (e.g. a variable name) is looked up in a Map.
27type ID uint32
28
29// Str returns a string form of x.
30func (x ID) Str(m *Map) string { return m.ByID(x) }
31
32func (x ID) AmbiguousForm() ID {
33	if x >= ID(len(ambiguousForms)) {
34		return 0
35	}
36	return ambiguousForms[x]
37}
38
39func (x ID) UnaryForm() ID {
40	if x >= ID(len(unaryForms)) {
41		return 0
42	}
43	return unaryForms[x]
44}
45
46func (x ID) BinaryForm() ID {
47	if x >= ID(len(binaryForms)) {
48		return 0
49	}
50	return binaryForms[x]
51}
52
53func (x ID) AssociativeForm() ID {
54	if x >= ID(len(associativeForms)) {
55		return 0
56	}
57	return associativeForms[x]
58}
59
60func (x ID) IsBuiltIn() bool { return x < nBuiltInIDs }
61
62func (x ID) IsUnaryOp() bool       { return minOp <= x && x <= maxOp && unaryForms[x] != 0 }
63func (x ID) IsBinaryOp() bool      { return minOp <= x && x <= maxOp && binaryForms[x] != 0 }
64func (x ID) IsAssociativeOp() bool { return minOp <= x && x <= maxOp && associativeForms[x] != 0 }
65
66func (x ID) IsLiteral(m *Map) bool {
67	if x < nBuiltInIDs {
68		return minBuiltInLiteral <= x && x <= maxBuiltInLiteral
69	} else if s := m.ByID(x); s != "" {
70		return !alpha(s[0])
71	}
72	return false
73}
74
75func (x ID) IsNumLiteral(m *Map) bool {
76	if x < nBuiltInIDs {
77		return minBuiltInNumLiteral <= x && x <= maxBuiltInNumLiteral
78	} else if s := m.ByID(x); s != "" {
79		return numeric(s[0])
80	}
81	return false
82}
83
84func (x ID) IsStrLiteral(m *Map) bool {
85	if x < nBuiltInIDs {
86		return false
87	} else if s := m.ByID(x); s != "" {
88		return s[0] == '"'
89	}
90	return false
91}
92
93func (x ID) IsIdent(m *Map) bool {
94	if x < nBuiltInIDs {
95		return minBuiltInIdent <= x && x <= maxBuiltInIdent
96	} else if s := m.ByID(x); s != "" {
97		return alpha(s[0])
98	}
99	return false
100}
101
102func (x ID) IsTightLeft() bool  { return x < ID(len(isTightLeft)) && isTightLeft[x] }
103func (x ID) IsTightRight() bool { return x < ID(len(isTightRight)) && isTightRight[x] }
104
105func (x ID) IsAssign() bool         { return minAssign <= x && x <= maxAssign }
106func (x ID) IsCannotAssignTo() bool { return minCannotAssignTo <= x && x <= maxCannotAssignTo }
107func (x ID) IsClose() bool          { return minClose <= x && x <= maxClose }
108func (x ID) IsKeyword() bool        { return minKeyword <= x && x <= maxKeyword }
109func (x ID) IsNumType() bool        { return minNumType <= x && x <= maxNumType }
110func (x ID) IsNumTypeOrIdeal() bool { return minNumTypeOrIdeal <= x && x <= maxNumTypeOrIdeal }
111func (x ID) IsOpen() bool           { return minOpen <= x && x <= maxOpen }
112
113func (x ID) IsImplicitSemicolon(m *Map) bool {
114	return x.IsClose() || x.IsKeyword() || x.IsIdent(m) || x.IsLiteral(m)
115}
116
117func (x ID) IsXOp() bool            { return minXOp <= x && x <= maxXOp }
118func (x ID) IsXUnaryOp() bool       { return minXOp <= x && x <= maxXOp && unaryForms[x] != 0 }
119func (x ID) IsXBinaryOp() bool      { return minXOp <= x && x <= maxXOp && binaryForms[x] != 0 }
120func (x ID) IsXAssociativeOp() bool { return minXOp <= x && x <= maxXOp && associativeForms[x] != 0 }
121
122func (x ID) SmallPowerOf2Value() int {
123	switch x {
124	case ID1:
125		return 1
126	case ID2:
127		return 2
128	case ID4:
129		return 4
130	case ID8:
131		return 8
132	case ID16:
133		return 16
134	case ID32:
135		return 32
136	case ID64:
137		return 64
138	case ID128:
139		return 128
140	case ID256:
141		return 256
142	}
143	return 0
144}
145
146// QID is a qualified ID, such as "foo.bar". QID[0] is "foo"'s ID and QID[1] is
147// "bar"'s. QID[0] may be 0 for a plain "bar".
148type QID [2]ID
149
150func (x QID) IsZero() bool { return x == QID{} }
151
152// Str returns a string form of x.
153func (x QID) Str(m *Map) string {
154	if x[0] != 0 {
155		return m.ByID(x[0]) + "." + m.ByID(x[1])
156	}
157	return m.ByID(x[1])
158}
159
160// QQID is a double-qualified ID, such as "receiverPkg.receiverName.funcName".
161type QQID [3]ID
162
163func (x QQID) IsZero() bool { return x == QQID{} }
164
165// Str returns a string form of x.
166func (x QQID) Str(m *Map) string {
167	if x[0] != 0 {
168		return m.ByID(x[0]) + "." + m.ByID(x[1]) + "." + m.ByID(x[2])
169	}
170	if x[1] != 0 {
171		return m.ByID(x[1]) + "." + m.ByID(x[2])
172	}
173	return m.ByID(x[2])
174}
175
176// Token combines an ID and the line number it was seen.
177type Token struct {
178	ID   ID
179	Line uint32
180}
181
182// nBuiltInIDs is the number of built-in IDs. The packing is:
183//  - Zero is invalid.
184//  - [ 0x01,  0x0F] are squiggly punctuation, such as "(", ")" and ";".
185//  - [ 0x10,  0x2F] are squiggly assignments, such as "=" and "+=".
186//  - [ 0x30,  0x4F] are operators, such as "+", "==" and "not".
187//  - [ 0x50,  0x7F] are x-ops (disambiguation forms): unary vs binary "+".
188//  - [ 0x80,  0x9F] are keywords, such as "if" and "return".
189//  - [ 0xA0,  0xAF] are type modifiers, such as "ptr" and "slice".
190//  - [ 0xB0,  0xBF] are literals, such as "false" and "true".
191//  - [ 0xC0,  0xFF] are reserved.
192//  - [0x100, 0x3FF] are identifiers, such as "bool", "u32" and "read_u8".
193//
194// "Squiggly" means a sequence of non-alpha-numeric characters, such as "+" and
195// "&=". Roughly speaking, their IDs range in [0x01, 0x4F], or disambiguation
196// forms range in [0x50, 0x7F], but vice versa does not necessarily hold. For
197// example, the "and" operator is not "squiggly" but it is within [0x01, 0x4F].
198const (
199	nBuiltInSymbolicIDs = ID(0x80)  // 128
200	nBuiltInIDs         = ID(0x400) // 1024
201)
202
203const (
204	IDInvalid   = ID(0)
205	IDSemicolon = ID(0x01)
206
207	minOpen = 0x02
208	maxOpen = 0x04
209
210	IDOpenParen   = ID(0x02)
211	IDOpenBracket = ID(0x03)
212	IDOpenCurly   = ID(0x04)
213
214	minClose = 0x05
215	maxClose = 0x07
216
217	IDCloseParen   = ID(0x05)
218	IDCloseBracket = ID(0x06)
219	IDCloseCurly   = ID(0x07)
220
221	IDDot      = ID(0x08)
222	IDDotDot   = ID(0x09)
223	IDDotDotEq = ID(0x0A)
224	IDComma    = ID(0x0B)
225	IDExclam   = ID(0x0C)
226	IDQuestion = ID(0x0D)
227	IDColon    = ID(0x0E)
228)
229
230const (
231	minAssign = 0x10
232	maxAssign = 0x2F
233
234	IDPlusEq           = ID(0x10)
235	IDMinusEq          = ID(0x11)
236	IDStarEq           = ID(0x12)
237	IDSlashEq          = ID(0x13)
238	IDShiftLEq         = ID(0x14)
239	IDShiftREq         = ID(0x15)
240	IDAmpEq            = ID(0x16)
241	IDPipeEq           = ID(0x17)
242	IDHatEq            = ID(0x18)
243	IDPercentEq        = ID(0x19)
244	IDTildeModShiftLEq = ID(0x1A)
245	IDTildeModPlusEq   = ID(0x1B)
246	IDTildeModMinusEq  = ID(0x1C)
247	IDTildeSatPlusEq   = ID(0x1D)
248	IDTildeSatMinusEq  = ID(0x1E)
249
250	IDEq         = ID(0x20)
251	IDEqQuestion = ID(0x21)
252)
253
254const (
255	minOp          = 0x30
256	minAmbiguousOp = 0x30
257	maxAmbiguousOp = 0x4F
258	minXOp         = 0x50
259	maxXOp         = 0x7F
260	maxOp          = 0x7F
261
262	IDPlus           = ID(0x30)
263	IDMinus          = ID(0x31)
264	IDStar           = ID(0x32)
265	IDSlash          = ID(0x33)
266	IDShiftL         = ID(0x34)
267	IDShiftR         = ID(0x35)
268	IDAmp            = ID(0x36)
269	IDPipe           = ID(0x37)
270	IDHat            = ID(0x38)
271	IDPercent        = ID(0x39)
272	IDTildeModShiftL = ID(0x3A)
273	IDTildeModPlus   = ID(0x3B)
274	IDTildeModMinus  = ID(0x3C)
275	IDTildeSatPlus   = ID(0x3D)
276	IDTildeSatMinus  = ID(0x3E)
277
278	IDNotEq       = ID(0x40)
279	IDLessThan    = ID(0x41)
280	IDLessEq      = ID(0x42)
281	IDEqEq        = ID(0x43)
282	IDGreaterEq   = ID(0x44)
283	IDGreaterThan = ID(0x45)
284
285	IDAnd = ID(0x48)
286	IDOr  = ID(0x49)
287	IDNot = ID(0x4A)
288	IDAs  = ID(0x4B)
289
290	// The IDXFoo IDs are not returned by the tokenizer. They are used by the
291	// ast.Node ID-typed fields to disambiguate e.g. unary vs binary plus.
292
293	IDXUnaryPlus  = ID(0x50)
294	IDXUnaryMinus = ID(0x51)
295	IDXUnaryNot   = ID(0x52)
296
297	IDXBinaryPlus           = ID(0x58)
298	IDXBinaryMinus          = ID(0x59)
299	IDXBinaryStar           = ID(0x5A)
300	IDXBinarySlash          = ID(0x5B)
301	IDXBinaryShiftL         = ID(0x5C)
302	IDXBinaryShiftR         = ID(0x5D)
303	IDXBinaryAmp            = ID(0x5E)
304	IDXBinaryPipe           = ID(0x5F)
305	IDXBinaryHat            = ID(0x60)
306	IDXBinaryPercent        = ID(0x61)
307	IDXBinaryTildeModShiftL = ID(0x62)
308	IDXBinaryTildeModPlus   = ID(0x63)
309	IDXBinaryTildeModMinus  = ID(0x64)
310	IDXBinaryTildeSatPlus   = ID(0x65)
311	IDXBinaryTildeSatMinus  = ID(0x66)
312	IDXBinaryNotEq          = ID(0x67)
313	IDXBinaryLessThan       = ID(0x68)
314	IDXBinaryLessEq         = ID(0x69)
315	IDXBinaryEqEq           = ID(0x6A)
316	IDXBinaryGreaterEq      = ID(0x6B)
317	IDXBinaryGreaterThan    = ID(0x6C)
318	IDXBinaryAnd            = ID(0x6D)
319	IDXBinaryOr             = ID(0x6E)
320	IDXBinaryAs             = ID(0x6F)
321
322	IDXAssociativePlus = ID(0x70)
323	IDXAssociativeStar = ID(0x71)
324	IDXAssociativeAmp  = ID(0x72)
325	IDXAssociativePipe = ID(0x73)
326	IDXAssociativeHat  = ID(0x74)
327	IDXAssociativeAnd  = ID(0x75)
328	IDXAssociativeOr   = ID(0x76)
329)
330
331const (
332	minKeyword = 0x80
333	maxKeyword = 0x9F
334
335	// TODO: sort these by name, when the list has stabilized.
336	IDFunc     = ID(0x80)
337	IDAssert   = ID(0x81)
338	IDWhile    = ID(0x82)
339	IDIf       = ID(0x83)
340	IDElse     = ID(0x84)
341	IDReturn   = ID(0x85)
342	IDBreak    = ID(0x86)
343	IDContinue = ID(0x87)
344	IDStruct   = ID(0x88)
345	IDUse      = ID(0x89)
346	IDVar      = ID(0x8A)
347	IDPre      = ID(0x8B)
348	IDInv      = ID(0x8C)
349	IDPost     = ID(0x8D)
350	IDVia      = ID(0x8E)
351	IDPub      = ID(0x8F)
352	IDPri      = ID(0x90)
353	IDConst    = ID(0x91)
354	IDIterate  = ID(0x92)
355	IDYield    = ID(0x93)
356	IDIOBind   = ID(0x94)
357	IDIOLimit  = ID(0x95)
358)
359
360const (
361	minTypeModifier = 0xA0
362	maxTypeModifier = 0xAF
363
364	IDArray = ID(0xA0)
365	IDNptr  = ID(0xA1)
366	IDPtr   = ID(0xA2)
367	IDSlice = ID(0xA3)
368	IDTable = ID(0xA4)
369)
370
371const (
372	minBuiltInLiteral    = 0xB0
373	minBuiltInNumLiteral = 0xC0
374	maxBuiltInNumLiteral = 0xCF
375	maxBuiltInLiteral    = 0xCF
376
377	IDFalse   = ID(0xB0)
378	IDTrue    = ID(0xB1)
379	IDNothing = ID(0xB2)
380	IDNullptr = ID(0xB3)
381	IDOk      = ID(0xB4)
382
383	ID0   = ID(0xC0)
384	ID1   = ID(0xC1)
385	ID2   = ID(0xC2)
386	ID4   = ID(0xC3)
387	ID8   = ID(0xC4)
388	ID16  = ID(0xC5)
389	ID32  = ID(0xC6)
390	ID64  = ID(0xC7)
391	ID128 = ID(0xC8)
392	ID256 = ID(0xC9)
393)
394
395const (
396	minBuiltInIdent   = 0x100
397	minCannotAssignTo = 0x100
398	maxCannotAssignTo = 0x102
399	minNumTypeOrIdeal = 0x10F
400	minNumType        = 0x110
401	maxNumType        = 0x117
402	maxNumTypeOrIdeal = 0x117
403	maxBuiltInIdent   = 0x3FF
404
405	// -------- 0x100 block.
406
407	IDArgs             = ID(0x100)
408	IDCoroutineResumed = ID(0x101)
409	IDThis             = ID(0x102)
410
411	IDT1      = ID(0x108)
412	IDT2      = ID(0x109)
413	IDDagger1 = ID(0x10A)
414	IDDagger2 = ID(0x10B)
415
416	IDQNullptr     = ID(0x10C)
417	IDQPlaceholder = ID(0x10D)
418	IDQTypeExpr    = ID(0x10E)
419
420	// It is important that IDQIdeal is right next to the IDI8..IDU64 block.
421	// See the ID.IsNumTypeOrIdeal method.
422	IDQIdeal = ID(0x10F)
423
424	IDI8  = ID(0x110)
425	IDI16 = ID(0x111)
426	IDI32 = ID(0x112)
427	IDI64 = ID(0x113)
428	IDU8  = ID(0x114)
429	IDU16 = ID(0x115)
430	IDU32 = ID(0x116)
431	IDU64 = ID(0x117)
432
433	IDBase          = ID(0x120)
434	IDBool          = ID(0x121)
435	IDEmptyIOReader = ID(0x122)
436	IDEmptyIOWriter = ID(0x123)
437	IDEmptyStruct   = ID(0x124)
438	IDIOReader      = ID(0x125)
439	IDIOWriter      = ID(0x126)
440	IDStatus        = ID(0x127)
441	IDUtility       = ID(0x128)
442
443	IDRangeIEU32 = ID(0x130)
444	IDRangeIIU32 = ID(0x131)
445	IDRangeIEU64 = ID(0x132)
446	IDRangeIIU64 = ID(0x133)
447	IDRectIEU32  = ID(0x134)
448	IDRectIIU32  = ID(0x135)
449
450	IDFrameConfig   = ID(0x150)
451	IDImageConfig   = ID(0x151)
452	IDPixelBuffer   = ID(0x152)
453	IDPixelConfig   = ID(0x153)
454	IDPixelSwizzler = ID(0x154)
455
456	IDDecodeFrameOptions = ID(0x158)
457
458	IDCanUndoByte      = ID(0x160)
459	IDCountSince       = ID(0x161)
460	IDHistoryAvailable = ID(0x162)
461	IDMark             = ID(0x163)
462	IDPosition         = ID(0x164)
463	IDSince            = ID(0x165)
464	IDSkip             = ID(0x166)
465	IDSkipFast         = ID(0x167)
466	IDTake             = ID(0x168)
467
468	IDCopyFromSlice        = ID(0x170)
469	IDCopyNFromHistory     = ID(0x171)
470	IDCopyNFromHistoryFast = ID(0x172)
471	IDCopyNFromReader      = ID(0x173)
472	IDCopyNFromSlice       = ID(0x174)
473
474	// -------- 0x180 block.
475
476	IDUndoByte = ID(0x180)
477	IDReadU8   = ID(0x181)
478
479	IDReadU16BE = ID(0x182)
480	IDReadU16LE = ID(0x183)
481
482	IDReadU8AsU32    = ID(0x189)
483	IDReadU16BEAsU32 = ID(0x18A)
484	IDReadU16LEAsU32 = ID(0x18B)
485	IDReadU24BEAsU32 = ID(0x18C)
486	IDReadU24LEAsU32 = ID(0x18D)
487	IDReadU32BE      = ID(0x18E)
488	IDReadU32LE      = ID(0x18F)
489
490	IDReadU8AsU64    = ID(0x191)
491	IDReadU16BEAsU64 = ID(0x192)
492	IDReadU16LEAsU64 = ID(0x193)
493	IDReadU24BEAsU64 = ID(0x194)
494	IDReadU24LEAsU64 = ID(0x195)
495	IDReadU32BEAsU64 = ID(0x196)
496	IDReadU32LEAsU64 = ID(0x197)
497	IDReadU40BEAsU64 = ID(0x198)
498	IDReadU40LEAsU64 = ID(0x199)
499	IDReadU48BEAsU64 = ID(0x19A)
500	IDReadU48LEAsU64 = ID(0x19B)
501	IDReadU56BEAsU64 = ID(0x19C)
502	IDReadU56LEAsU64 = ID(0x19D)
503	IDReadU64BE      = ID(0x19E)
504	IDReadU64LE      = ID(0x19F)
505
506	// --------
507
508	IDPeekU8 = ID(0x1A1)
509
510	IDPeekU16BE = ID(0x1A2)
511	IDPeekU16LE = ID(0x1A3)
512
513	IDPeekU8AsU32    = ID(0x1A9)
514	IDPeekU16BEAsU32 = ID(0x1AA)
515	IDPeekU16LEAsU32 = ID(0x1AB)
516	IDPeekU24BEAsU32 = ID(0x1AC)
517	IDPeekU24LEAsU32 = ID(0x1AD)
518	IDPeekU32BE      = ID(0x1AE)
519	IDPeekU32LE      = ID(0x1AF)
520
521	IDPeekU8AsU64    = ID(0x1B1)
522	IDPeekU16BEAsU64 = ID(0x1B2)
523	IDPeekU16LEAsU64 = ID(0x1B3)
524	IDPeekU24BEAsU64 = ID(0x1B4)
525	IDPeekU24LEAsU64 = ID(0x1B5)
526	IDPeekU32BEAsU64 = ID(0x1B6)
527	IDPeekU32LEAsU64 = ID(0x1B7)
528	IDPeekU40BEAsU64 = ID(0x1B8)
529	IDPeekU40LEAsU64 = ID(0x1B9)
530	IDPeekU48BEAsU64 = ID(0x1BA)
531	IDPeekU48LEAsU64 = ID(0x1BB)
532	IDPeekU56BEAsU64 = ID(0x1BC)
533	IDPeekU56LEAsU64 = ID(0x1BD)
534	IDPeekU64BE      = ID(0x1BE)
535	IDPeekU64LE      = ID(0x1BF)
536
537	// --------
538
539	// TODO: IDUnwriteU8?
540
541	IDWriteU8    = ID(0x1C1)
542	IDWriteU16BE = ID(0x1C2)
543	IDWriteU16LE = ID(0x1C3)
544	IDWriteU24BE = ID(0x1C4)
545	IDWriteU24LE = ID(0x1C5)
546	IDWriteU32BE = ID(0x1C6)
547	IDWriteU32LE = ID(0x1C7)
548	IDWriteU40BE = ID(0x1C8)
549	IDWriteU40LE = ID(0x1C9)
550	IDWriteU48BE = ID(0x1CA)
551	IDWriteU48LE = ID(0x1CB)
552	IDWriteU56BE = ID(0x1CC)
553	IDWriteU56LE = ID(0x1CD)
554	IDWriteU64BE = ID(0x1CE)
555	IDWriteU64LE = ID(0x1CF)
556
557	// --------
558
559	IDWriteFastU8    = ID(0x1E1)
560	IDWriteFastU16BE = ID(0x1E2)
561	IDWriteFastU16LE = ID(0x1E3)
562	IDWriteFastU24BE = ID(0x1E4)
563	IDWriteFastU24LE = ID(0x1E5)
564	IDWriteFastU32BE = ID(0x1E6)
565	IDWriteFastU32LE = ID(0x1E7)
566	IDWriteFastU40BE = ID(0x1E8)
567	IDWriteFastU40LE = ID(0x1E9)
568	IDWriteFastU48BE = ID(0x1EA)
569	IDWriteFastU48LE = ID(0x1EB)
570	IDWriteFastU56BE = ID(0x1EC)
571	IDWriteFastU56LE = ID(0x1ED)
572	IDWriteFastU64BE = ID(0x1EE)
573	IDWriteFastU64LE = ID(0x1EF)
574
575	// -------- 0x200 block.
576
577	IDInitialize = ID(0x200)
578	IDReset      = ID(0x201)
579	IDSet        = ID(0x202)
580	IDUnroll     = ID(0x203)
581	IDUpdate     = ID(0x204)
582
583	// TODO: range/rect methods like intersection and contains?
584
585	IDHighBits = ID(0x220)
586	IDLowBits  = ID(0x221)
587	IDMax      = ID(0x222)
588	IDMin      = ID(0x223)
589
590	IDIsError      = ID(0x230)
591	IDIsOK         = ID(0x231)
592	IDIsSuspension = ID(0x232)
593
594	IDAvailable = ID(0x240)
595	IDHeight    = ID(0x241)
596	IDLength    = ID(0x242)
597	IDPrefix    = ID(0x243)
598	IDRow       = ID(0x244)
599	IDStride    = ID(0x245)
600	IDSuffix    = ID(0x246)
601	IDWidth     = ID(0x247)
602	IDIO        = ID(0x248)
603	IDLimit     = ID(0x249)
604	IDData      = ID(0x24A)
605)
606
607var builtInsByID = [nBuiltInIDs]string{
608	IDOpenParen:    "(",
609	IDCloseParen:   ")",
610	IDOpenBracket:  "[",
611	IDCloseBracket: "]",
612	IDOpenCurly:    "{",
613	IDCloseCurly:   "}",
614
615	IDDot:       ".",
616	IDDotDot:    "..",
617	IDDotDotEq:  "..=",
618	IDComma:     ",",
619	IDExclam:    "!",
620	IDQuestion:  "?",
621	IDColon:     ":",
622	IDSemicolon: ";",
623
624	IDPlusEq:           "+=",
625	IDMinusEq:          "-=",
626	IDStarEq:           "*=",
627	IDSlashEq:          "/=",
628	IDShiftLEq:         "<<=",
629	IDShiftREq:         ">>=",
630	IDAmpEq:            "&=",
631	IDPipeEq:           "|=",
632	IDHatEq:            "^=",
633	IDPercentEq:        "%=",
634	IDTildeModShiftLEq: "~mod<<=",
635	IDTildeModPlusEq:   "~mod+=",
636	IDTildeModMinusEq:  "~mod-=",
637	IDTildeSatPlusEq:   "~sat+=",
638	IDTildeSatMinusEq:  "~sat-=",
639
640	IDEq:         "=",
641	IDEqQuestion: "=?",
642
643	IDPlus:           "+",
644	IDMinus:          "-",
645	IDStar:           "*",
646	IDSlash:          "/",
647	IDShiftL:         "<<",
648	IDShiftR:         ">>",
649	IDAmp:            "&",
650	IDPipe:           "|",
651	IDHat:            "^",
652	IDPercent:        "%",
653	IDTildeModShiftL: "~mod<<",
654	IDTildeModPlus:   "~mod+",
655	IDTildeModMinus:  "~mod-",
656	IDTildeSatPlus:   "~sat+",
657	IDTildeSatMinus:  "~sat-",
658
659	IDNotEq:       "<>",
660	IDLessThan:    "<",
661	IDLessEq:      "<=",
662	IDEqEq:        "==",
663	IDGreaterEq:   ">=",
664	IDGreaterThan: ">",
665
666	IDAnd: "and",
667	IDOr:  "or",
668	IDNot: "not",
669	IDAs:  "as",
670
671	IDFunc:     "func",
672	IDAssert:   "assert",
673	IDWhile:    "while",
674	IDIf:       "if",
675	IDElse:     "else",
676	IDReturn:   "return",
677	IDBreak:    "break",
678	IDContinue: "continue",
679	IDStruct:   "struct",
680	IDUse:      "use",
681	IDVar:      "var",
682	IDPre:      "pre",
683	IDInv:      "inv",
684	IDPost:     "post",
685	IDVia:      "via",
686	IDPub:      "pub",
687	IDPri:      "pri",
688	IDConst:    "const",
689	IDIterate:  "iterate",
690	IDYield:    "yield",
691	IDIOBind:   "io_bind",
692	IDIOLimit:  "io_limit",
693
694	IDArray: "array",
695	IDNptr:  "nptr",
696	IDPtr:   "ptr",
697	IDSlice: "slice",
698	IDTable: "table",
699
700	IDFalse:   "false",
701	IDTrue:    "true",
702	IDNothing: "nothing",
703	IDNullptr: "nullptr",
704	IDOk:      "ok",
705
706	ID0:   "0",
707	ID1:   "1",
708	ID2:   "2",
709	ID4:   "4",
710	ID8:   "8",
711	ID16:  "16",
712	ID32:  "32",
713	ID64:  "64",
714	ID128: "128",
715	ID256: "256",
716
717	// -------- 0x100 block.
718
719	IDArgs:             "args",
720	IDCoroutineResumed: "coroutine_resumed",
721	IDThis:             "this",
722
723	// Some of the next few IDs are never returned by the tokenizer, as it
724	// rejects non-ASCII input. The string representations "¶", "ℤ" etc. are
725	// specifically non-ASCII so that no user-defined (non built-in) identifier
726	// will conflict with them.
727
728	// IDDaggerN is used by the type checker as a dummy-valued built-in ID to
729	// represent a generic type.
730	IDT1:      "T1",
731	IDT2:      "T2",
732	IDDagger1: "†", // U+2020 DAGGER
733	IDDagger2: "‡", // U+2021 DOUBLE DAGGER
734
735	// IDQNullptr is used by the type checker to build an artificial MType for
736	// the nullptr literal.
737	IDQNullptr: "«Nullptr»",
738
739	// IDQPlaceholder is used by the type checker to build an artificial MType
740	// for AST nodes that aren't expression nodes or type expression nodes,
741	// such as struct definition nodes and statement nodes. Its presence means
742	// that the node is type checked.
743	IDQPlaceholder: "«Placeholder»",
744
745	// IDQTypeExpr is used by the type checker to build an artificial MType for
746	// type expression AST nodes.
747	IDQTypeExpr: "«TypeExpr»",
748
749	// IDQIdeal is used by the type checker to build an artificial MType for
750	// ideal integers (in mathematical terms, the integer ring ℤ), as opposed
751	// to a realized integer type whose range is restricted. For example, the
752	// base.u16 type is restricted to [0x0000, 0xFFFF].
753	IDQIdeal: "«Ideal»",
754
755	// Change MaxIntBits if a future update adds an i128 or u128 type.
756	IDI8:  "i8",
757	IDI16: "i16",
758	IDI32: "i32",
759	IDI64: "i64",
760	IDU8:  "u8",
761	IDU16: "u16",
762	IDU32: "u32",
763	IDU64: "u64",
764
765	IDBase:          "base",
766	IDBool:          "bool",
767	IDEmptyIOReader: "empty_io_reader",
768	IDEmptyIOWriter: "empty_io_writer",
769	IDEmptyStruct:   "empty_struct",
770	IDIOReader:      "io_reader",
771	IDIOWriter:      "io_writer",
772	IDStatus:        "status",
773	IDUtility:       "utility",
774
775	IDRangeIEU32: "range_ie_u32",
776	IDRangeIIU32: "range_ii_u32",
777	IDRangeIEU64: "range_ie_u64",
778	IDRangeIIU64: "range_ii_u64",
779	IDRectIEU32:  "rect_ie_u32",
780	IDRectIIU32:  "rect_ii_u32",
781
782	IDFrameConfig:   "frame_config",
783	IDImageConfig:   "image_config",
784	IDPixelBuffer:   "pixel_buffer",
785	IDPixelConfig:   "pixel_config",
786	IDPixelSwizzler: "pixel_swizzler",
787
788	IDDecodeFrameOptions: "decode_frame_options",
789
790	IDCanUndoByte:      "can_undo_byte",
791	IDCountSince:       "count_since",
792	IDHistoryAvailable: "history_available",
793	IDMark:             "mark",
794	IDPosition:         "position",
795	IDSince:            "since",
796	IDSkip:             "skip",
797	IDSkipFast:         "skip_fast",
798	IDTake:             "take",
799
800	IDCopyFromSlice:        "copy_from_slice",
801	IDCopyNFromHistory:     "copy_n_from_history",
802	IDCopyNFromHistoryFast: "copy_n_from_history_fast",
803	IDCopyNFromReader:      "copy_n_from_reader",
804	IDCopyNFromSlice:       "copy_n_from_slice",
805
806	// -------- 0x180 block.
807
808	IDUndoByte: "undo_byte",
809	IDReadU8:   "read_u8",
810
811	IDReadU16BE: "read_u16be",
812	IDReadU16LE: "read_u16le",
813
814	IDReadU8AsU32:    "read_u8_as_u32",
815	IDReadU16BEAsU32: "read_u16be_as_u32",
816	IDReadU16LEAsU32: "read_u16le_as_u32",
817	IDReadU24BEAsU32: "read_u24be_as_u32",
818	IDReadU24LEAsU32: "read_u24le_as_u32",
819	IDReadU32BE:      "read_u32be",
820	IDReadU32LE:      "read_u32le",
821
822	IDReadU8AsU64:    "read_u8_as_u64",
823	IDReadU16BEAsU64: "read_u16be_as_u64",
824	IDReadU16LEAsU64: "read_u16le_as_u64",
825	IDReadU24BEAsU64: "read_u24be_as_u64",
826	IDReadU24LEAsU64: "read_u24le_as_u64",
827	IDReadU32BEAsU64: "read_u32be_as_u64",
828	IDReadU32LEAsU64: "read_u32le_as_u64",
829	IDReadU40BEAsU64: "read_u40be_as_u64",
830	IDReadU40LEAsU64: "read_u40le_as_u64",
831	IDReadU48BEAsU64: "read_u48be_as_u64",
832	IDReadU48LEAsU64: "read_u48le_as_u64",
833	IDReadU56BEAsU64: "read_u56be_as_u64",
834	IDReadU56LEAsU64: "read_u56le_as_u64",
835	IDReadU64BE:      "read_u64be",
836	IDReadU64LE:      "read_u64le",
837
838	// --------
839
840	IDPeekU8: "peek_u8",
841
842	IDPeekU16BE: "peek_u16be",
843	IDPeekU16LE: "peek_u16le",
844
845	IDPeekU8AsU32:    "peek_u8_as_u32",
846	IDPeekU16BEAsU32: "peek_u16be_as_u32",
847	IDPeekU16LEAsU32: "peek_u16le_as_u32",
848	IDPeekU24BEAsU32: "peek_u24be_as_u32",
849	IDPeekU24LEAsU32: "peek_u24le_as_u32",
850	IDPeekU32BE:      "peek_u32be",
851	IDPeekU32LE:      "peek_u32le",
852
853	IDPeekU8AsU64:    "peek_u8_as_u64",
854	IDPeekU16BEAsU64: "peek_u16be_as_u64",
855	IDPeekU16LEAsU64: "peek_u16le_as_u64",
856	IDPeekU24BEAsU64: "peek_u24be_as_u64",
857	IDPeekU24LEAsU64: "peek_u24le_as_u64",
858	IDPeekU32BEAsU64: "peek_u32be_as_u64",
859	IDPeekU32LEAsU64: "peek_u32le_as_u64",
860	IDPeekU40BEAsU64: "peek_u40be_as_u64",
861	IDPeekU40LEAsU64: "peek_u40le_as_u64",
862	IDPeekU48BEAsU64: "peek_u48be_as_u64",
863	IDPeekU48LEAsU64: "peek_u48le_as_u64",
864	IDPeekU56BEAsU64: "peek_u56be_as_u64",
865	IDPeekU56LEAsU64: "peek_u56le_as_u64",
866	IDPeekU64BE:      "peek_u64be",
867	IDPeekU64LE:      "peek_u64le",
868
869	// --------
870
871	IDWriteU8:    "write_u8",
872	IDWriteU16BE: "write_u16be",
873	IDWriteU16LE: "write_u16le",
874	IDWriteU24BE: "write_u24be",
875	IDWriteU24LE: "write_u24le",
876	IDWriteU32BE: "write_u32be",
877	IDWriteU32LE: "write_u32le",
878	IDWriteU40BE: "write_u40be",
879	IDWriteU40LE: "write_u40le",
880	IDWriteU48BE: "write_u48be",
881	IDWriteU48LE: "write_u48le",
882	IDWriteU56BE: "write_u56be",
883	IDWriteU56LE: "write_u56le",
884	IDWriteU64BE: "write_u64be",
885	IDWriteU64LE: "write_u64le",
886
887	// --------
888
889	IDWriteFastU8:    "write_fast_u8",
890	IDWriteFastU16BE: "write_fast_u16be",
891	IDWriteFastU16LE: "write_fast_u16le",
892	IDWriteFastU24BE: "write_fast_u24be",
893	IDWriteFastU24LE: "write_fast_u24le",
894	IDWriteFastU32BE: "write_fast_u32be",
895	IDWriteFastU32LE: "write_fast_u32le",
896	IDWriteFastU40BE: "write_fast_u40be",
897	IDWriteFastU40LE: "write_fast_u40le",
898	IDWriteFastU48BE: "write_fast_u48be",
899	IDWriteFastU48LE: "write_fast_u48le",
900	IDWriteFastU56BE: "write_fast_u56be",
901	IDWriteFastU56LE: "write_fast_u56le",
902	IDWriteFastU64BE: "write_fast_u64be",
903	IDWriteFastU64LE: "write_fast_u64le",
904
905	// -------- 0x200 block.
906
907	IDInitialize: "initialize",
908	IDReset:      "reset",
909	IDSet:        "set",
910	IDUnroll:     "unroll",
911	IDUpdate:     "update",
912
913	IDHighBits: "high_bits",
914	IDLowBits:  "low_bits",
915	IDMax:      "max",
916	IDMin:      "min",
917
918	IDIsError:      "is_error",
919	IDIsOK:         "is_ok",
920	IDIsSuspension: "is_suspension",
921
922	IDAvailable: "available",
923	IDHeight:    "height",
924	IDLength:    "length",
925	IDPrefix:    "prefix",
926	IDRow:       "row",
927	IDStride:    "stride",
928	IDSuffix:    "suffix",
929	IDWidth:     "width",
930	IDIO:        "io",
931	IDLimit:     "limit",
932	IDData:      "data",
933}
934
935var builtInsByName = map[string]ID{}
936
937func init() {
938	for i, name := range builtInsByID {
939		if name != "" {
940			builtInsByName[name] = ID(i)
941		}
942	}
943}
944
945// squiggles are built-in IDs that aren't alpha-numeric.
946var squiggles = [256]ID{
947	'(': IDOpenParen,
948	')': IDCloseParen,
949	'[': IDOpenBracket,
950	']': IDCloseBracket,
951	'{': IDOpenCurly,
952	'}': IDCloseCurly,
953
954	',': IDComma,
955	'!': IDExclam,
956	'?': IDQuestion,
957	':': IDColon,
958	';': IDSemicolon,
959}
960
961type suffixLexer struct {
962	suffix string
963	id     ID
964}
965
966// lexers lex ambiguous 1-byte squiggles. For example, "&" might be the start
967// of "&^" or "&=".
968//
969// The order of the []suffixLexer elements matters. The first match wins. Since
970// we want to lex greedily, longer suffixes should be earlier in the slice.
971var lexers = [256][]suffixLexer{
972	'.': {
973		{".=", IDDotDotEq},
974		{".", IDDotDot},
975		{"", IDDot},
976	},
977	'&': {
978		{"=", IDAmpEq},
979		{"", IDAmp},
980	},
981	'|': {
982		{"=", IDPipeEq},
983		{"", IDPipe},
984	},
985	'^': {
986		{"=", IDHatEq},
987		{"", IDHat},
988	},
989	'+': {
990		{"=", IDPlusEq},
991		{"", IDPlus},
992	},
993	'-': {
994		{"=", IDMinusEq},
995		{"", IDMinus},
996	},
997	'*': {
998		{"=", IDStarEq},
999		{"", IDStar},
1000	},
1001	'/': {
1002		{"=", IDSlashEq},
1003		{"", IDSlash},
1004	},
1005	'%': {
1006		{"=", IDPercentEq},
1007		{"", IDPercent},
1008	},
1009	'=': {
1010		{"=", IDEqEq},
1011		{"?", IDEqQuestion},
1012		{"", IDEq},
1013	},
1014	'<': {
1015		{"<=", IDShiftLEq},
1016		{"<", IDShiftL},
1017		{"=", IDLessEq},
1018		{">", IDNotEq},
1019		{"", IDLessThan},
1020	},
1021	'>': {
1022		{">=", IDShiftREq},
1023		{">", IDShiftR},
1024		{"=", IDGreaterEq},
1025		{"", IDGreaterThan},
1026	},
1027	'~': {
1028		{"mod<<=", IDTildeModShiftLEq},
1029		{"mod<<", IDTildeModShiftL},
1030		{"mod+=", IDTildeModPlusEq},
1031		{"mod+", IDTildeModPlus},
1032		{"mod-=", IDTildeModMinusEq},
1033		{"mod-", IDTildeModMinus},
1034		{"sat+=", IDTildeSatPlusEq},
1035		{"sat+", IDTildeSatPlus},
1036		{"sat-=", IDTildeSatMinusEq},
1037		{"sat-", IDTildeSatMinus},
1038	},
1039}
1040
1041var ambiguousForms = [nBuiltInSymbolicIDs]ID{
1042	IDXUnaryPlus:  IDPlus,
1043	IDXUnaryMinus: IDMinus,
1044	IDXUnaryNot:   IDNot,
1045
1046	IDXBinaryPlus:           IDPlus,
1047	IDXBinaryMinus:          IDMinus,
1048	IDXBinaryStar:           IDStar,
1049	IDXBinarySlash:          IDSlash,
1050	IDXBinaryShiftL:         IDShiftL,
1051	IDXBinaryShiftR:         IDShiftR,
1052	IDXBinaryAmp:            IDAmp,
1053	IDXBinaryPipe:           IDPipe,
1054	IDXBinaryHat:            IDHat,
1055	IDXBinaryPercent:        IDPercent,
1056	IDXBinaryTildeModShiftL: IDTildeModShiftL,
1057	IDXBinaryTildeModPlus:   IDTildeModPlus,
1058	IDXBinaryTildeModMinus:  IDTildeModMinus,
1059	IDXBinaryTildeSatPlus:   IDTildeSatPlus,
1060	IDXBinaryTildeSatMinus:  IDTildeSatMinus,
1061	IDXBinaryNotEq:          IDNotEq,
1062	IDXBinaryLessThan:       IDLessThan,
1063	IDXBinaryLessEq:         IDLessEq,
1064	IDXBinaryEqEq:           IDEqEq,
1065	IDXBinaryGreaterEq:      IDGreaterEq,
1066	IDXBinaryGreaterThan:    IDGreaterThan,
1067	IDXBinaryAnd:            IDAnd,
1068	IDXBinaryOr:             IDOr,
1069	IDXBinaryAs:             IDAs,
1070
1071	IDXAssociativePlus: IDPlus,
1072	IDXAssociativeStar: IDStar,
1073	IDXAssociativeAmp:  IDAmp,
1074	IDXAssociativePipe: IDPipe,
1075	IDXAssociativeHat:  IDHat,
1076	IDXAssociativeAnd:  IDAnd,
1077	IDXAssociativeOr:   IDOr,
1078}
1079
1080func init() {
1081	addXForms(&unaryForms)
1082	addXForms(&binaryForms)
1083	addXForms(&associativeForms)
1084}
1085
1086// addXForms modifies table so that, if table[x] == y, then table[y] = y.
1087//
1088// For example, for the unaryForms table, the explicit entries are like:
1089//  IDPlus:        IDXUnaryPlus,
1090// and this function implicitly addes entries like:
1091//  IDXUnaryPlus:  IDXUnaryPlus,
1092func addXForms(table *[nBuiltInSymbolicIDs]ID) {
1093	implicitEntries := [nBuiltInSymbolicIDs]bool{}
1094	for _, y := range table {
1095		if y != 0 {
1096			implicitEntries[y] = true
1097		}
1098	}
1099	for y, implicit := range implicitEntries {
1100		if implicit {
1101			table[y] = ID(y)
1102		}
1103	}
1104}
1105
1106var unaryForms = [nBuiltInSymbolicIDs]ID{
1107	IDPlus:  IDXUnaryPlus,
1108	IDMinus: IDXUnaryMinus,
1109	IDNot:   IDXUnaryNot,
1110}
1111
1112var binaryForms = [nBuiltInSymbolicIDs]ID{
1113	IDPlusEq:           IDXBinaryPlus,
1114	IDMinusEq:          IDXBinaryMinus,
1115	IDStarEq:           IDXBinaryStar,
1116	IDSlashEq:          IDXBinarySlash,
1117	IDShiftLEq:         IDXBinaryShiftL,
1118	IDShiftREq:         IDXBinaryShiftR,
1119	IDAmpEq:            IDXBinaryAmp,
1120	IDPipeEq:           IDXBinaryPipe,
1121	IDHatEq:            IDXBinaryHat,
1122	IDPercentEq:        IDXBinaryPercent,
1123	IDTildeModShiftLEq: IDXBinaryTildeModShiftL,
1124	IDTildeModPlusEq:   IDXBinaryTildeModPlus,
1125	IDTildeModMinusEq:  IDXBinaryTildeModMinus,
1126	IDTildeSatPlusEq:   IDXBinaryTildeSatPlus,
1127	IDTildeSatMinusEq:  IDXBinaryTildeSatMinus,
1128
1129	IDPlus:           IDXBinaryPlus,
1130	IDMinus:          IDXBinaryMinus,
1131	IDStar:           IDXBinaryStar,
1132	IDSlash:          IDXBinarySlash,
1133	IDShiftL:         IDXBinaryShiftL,
1134	IDShiftR:         IDXBinaryShiftR,
1135	IDAmp:            IDXBinaryAmp,
1136	IDPipe:           IDXBinaryPipe,
1137	IDHat:            IDXBinaryHat,
1138	IDPercent:        IDXBinaryPercent,
1139	IDTildeModShiftL: IDXBinaryTildeModShiftL,
1140	IDTildeModPlus:   IDXBinaryTildeModPlus,
1141	IDTildeModMinus:  IDXBinaryTildeModMinus,
1142	IDTildeSatPlus:   IDXBinaryTildeSatPlus,
1143	IDTildeSatMinus:  IDXBinaryTildeSatMinus,
1144
1145	IDNotEq:       IDXBinaryNotEq,
1146	IDLessThan:    IDXBinaryLessThan,
1147	IDLessEq:      IDXBinaryLessEq,
1148	IDEqEq:        IDXBinaryEqEq,
1149	IDGreaterEq:   IDXBinaryGreaterEq,
1150	IDGreaterThan: IDXBinaryGreaterThan,
1151	IDAnd:         IDXBinaryAnd,
1152	IDOr:          IDXBinaryOr,
1153	IDAs:          IDXBinaryAs,
1154}
1155
1156var associativeForms = [nBuiltInSymbolicIDs]ID{
1157	IDPlus: IDXAssociativePlus,
1158	IDStar: IDXAssociativeStar,
1159	IDAmp:  IDXAssociativeAmp,
1160	IDPipe: IDXAssociativePipe,
1161	IDHat:  IDXAssociativeHat,
1162	// TODO: IDTildeModPlus, IDTildeSatPlus?
1163	IDAnd: IDXAssociativeAnd,
1164	IDOr:  IDXAssociativeOr,
1165}
1166
1167var isTightLeft = [...]bool{
1168	IDSemicolon: true,
1169
1170	IDCloseParen:   true,
1171	IDOpenBracket:  true,
1172	IDCloseBracket: true,
1173
1174	IDDot:      true,
1175	IDComma:    true,
1176	IDExclam:   true,
1177	IDQuestion: true,
1178	IDColon:    true,
1179}
1180
1181var isTightRight = [...]bool{
1182	IDOpenParen:   true,
1183	IDOpenBracket: true,
1184
1185	IDDot:      true,
1186	IDExclam:   true,
1187	IDQuestion: true,
1188}
1189