1 /**
2  * Defines lexical tokens.
3  *
4  * Specification: $(LINK2 https://dlang.org/spec/lex.html#tokens, Tokens)
5  *
6  * Copyright:   Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
7  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
8  * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
9  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/tokens.d, _tokens.d)
10  * Documentation:  https://dlang.org/phobos/dmd_tokens.html
11  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/tokens.d
12  */
13 
14 module dmd.tokens;
15 
16 import core.stdc.ctype;
17 import core.stdc.stdio;
18 import core.stdc.string;
19 import dmd.globals;
20 import dmd.identifier;
21 import dmd.root.ctfloat;
22 import dmd.root.outbuffer;
23 import dmd.root.rmem;
24 import dmd.utf;
25 
26 enum TOK : ubyte
27 {
28     reserved,
29 
30     // Other
31     leftParentheses,
32     rightParentheses,
33     leftBracket,
34     rightBracket,
35     leftCurly,
36     rightCurly,
37     colon,
38     negate,
39     semicolon,
40     dotDotDot,
41     endOfFile,
42     cast_,
43     null_,
44     assert_,
45     true_,
46     false_,
47     array,
48     call,
49     address,
50     type,
51     throw_,
52     new_,
53     delete_,
54     star,
55     symbolOffset,
56     variable,
57     dotVariable,
58     dotIdentifier,
59     dotTemplateInstance,
60     dotType,
61     slice,
62     arrayLength,
63     version_,
64     module_,
65     dollar,
66     template_,
67     dotTemplateDeclaration,
68     declaration,
69     typeof_,
70     pragma_,
71     dSymbol,
72     typeid_,
73     uadd,
74     remove,
75     newAnonymousClass,
76     comment,
77     arrayLiteral,
78     assocArrayLiteral,
79     structLiteral,
80     classReference,
81     thrownException,
82     delegatePointer,
83     delegateFunctionPointer,
84 
85     // Operators
86     lessThan = 54,
87     greaterThan,
88     lessOrEqual,
89     greaterOrEqual,
90     equal,
91     notEqual,
92     identity,
93     notIdentity,
94     index,
95     is_,
96 
97     leftShift = 64,
98     rightShift,
99     leftShiftAssign,
100     rightShiftAssign,
101     unsignedRightShift,
102     unsignedRightShiftAssign,
103     concatenate,
104     concatenateAssign, // ~=
105     concatenateElemAssign,
106     concatenateDcharAssign,
107     add,
108     min,
109     addAssign,
110     minAssign,
111     mul,
112     div,
113     mod,
114     mulAssign,
115     divAssign,
116     modAssign,
117     and,
118     or,
119     xor,
120     andAssign,
121     orAssign,
122     xorAssign,
123     assign,
124     not,
125     tilde,
126     plusPlus,
127     minusMinus,
128     construct,
129     blit,
130     dot,
131     comma,
132     question,
133     andAnd,
134     orOr,
135     prePlusPlus,
136     preMinusMinus,
137 
138     // Numeric literals
139     int32Literal = 104,
140     uns32Literal,
141     int64Literal,
142     uns64Literal,
143     int128Literal,
144     uns128Literal,
145     float32Literal,
146     float64Literal,
147     float80Literal,
148     imaginary32Literal,
149     imaginary64Literal,
150     imaginary80Literal,
151 
152     // Char constants
153     charLiteral = 116,
154     wcharLiteral,
155     dcharLiteral,
156 
157     // Leaf operators
158     identifier = 119,
159     string_,
160     hexadecimalString,
161     this_,
162     super_,
163     halt,
164     tuple,
165     error,
166 
167     // Basic types
168     void_ = 127,
169     int8,
170     uns8,
171     int16,
172     uns16,
173     int32,
174     uns32,
175     int64,
176     uns64,
177     int128,
178     uns128,
179     float32,
180     float64,
181     float80,
182     imaginary32,
183     imaginary64,
184     imaginary80,
185     complex32,
186     complex64,
187     complex80,
188     char_,
189     wchar_,
190     dchar_,
191     bool_,
192 
193     // Aggregates
194     struct_ = 151,
195     class_,
196     interface_,
197     union_,
198     enum_,
199     import_,
200     alias_,
201     override_,
202     delegate_,
203     function_,
204     mixin_,
205     align_,
206     extern_,
207     private_,
208     protected_,
209     public_,
210     export_,
211     static_,
212     final_,
213     const_,
214     abstract_,
215     debug_,
216     deprecated_,
217     in_,
218     out_,
219     inout_,
220     lazy_,
221     auto_,
222     package_,
223     immutable_,
224 
225     // Statements
226     if_ = 181,
227     else_,
228     while_,
229     for_,
230     do_,
231     switch_,
232     case_,
233     default_,
234     break_,
235     continue_,
236     with_,
237     synchronized_,
238     return_,
239     goto_,
240     try_,
241     catch_,
242     finally_,
243     asm_,
244     foreach_,
245     foreach_reverse_,
246     scope_,
247     onScopeExit,
248     onScopeFailure,
249     onScopeSuccess,
250 
251     // Contracts
252     invariant_ = 205,
253 
254     // Testing
255     unittest_,
256 
257     // Added after 1.0
258     argumentTypes,
259     ref_,
260     macro_,
261 
262     parameters = 210,
263     traits,
264     overloadSet,
265     pure_,
266     nothrow_,
267     gshared,
268     line,
269     file,
270     fileFullPath,
271     moduleString,
272     functionString,
273     prettyFunction,
274     shared_,
275     at,
276     pow,
277     powAssign,
278     goesTo,
279     vector,
280     pound,
281 
282     interval = 229,
283     voidExpression,
284     cantExpression,
285     showCtfeContext,
286 
287     objcClassReference,
288     vectorArray,
289 
290     max_,
291 }
292 
293 // Assert that all token enum members have consecutive values and
294 // that none of them overlap
295 static assert(() {
296     foreach (idx, enumName; __traits(allMembers, TOK)) {
297        static if (idx != __traits(getMember, TOK, enumName)) {
298            pragma(msg, "Error: Expected TOK.", enumName, " to be ", idx, " but is ", __traits(getMember, TOK, enumName));
299            static assert(0);
300        }
301     }
302     return true;
303 }());
304 
305 
306 /****************************************
307  */
308 
309 private immutable TOK[] keywords =
310 [
311     TOK.this_,
312     TOK.super_,
313     TOK.assert_,
314     TOK.null_,
315     TOK.true_,
316     TOK.false_,
317     TOK.cast_,
318     TOK.new_,
319     TOK.delete_,
320     TOK.throw_,
321     TOK.module_,
322     TOK.pragma_,
323     TOK.typeof_,
324     TOK.typeid_,
325     TOK.template_,
326     TOK.void_,
327     TOK.int8,
328     TOK.uns8,
329     TOK.int16,
330     TOK.uns16,
331     TOK.int32,
332     TOK.uns32,
333     TOK.int64,
334     TOK.uns64,
335     TOK.int128,
336     TOK.uns128,
337     TOK.float32,
338     TOK.float64,
339     TOK.float80,
340     TOK.bool_,
341     TOK.char_,
342     TOK.wchar_,
343     TOK.dchar_,
344     TOK.imaginary32,
345     TOK.imaginary64,
346     TOK.imaginary80,
347     TOK.complex32,
348     TOK.complex64,
349     TOK.complex80,
350     TOK.delegate_,
351     TOK.function_,
352     TOK.is_,
353     TOK.if_,
354     TOK.else_,
355     TOK.while_,
356     TOK.for_,
357     TOK.do_,
358     TOK.switch_,
359     TOK.case_,
360     TOK.default_,
361     TOK.break_,
362     TOK.continue_,
363     TOK.synchronized_,
364     TOK.return_,
365     TOK.goto_,
366     TOK.try_,
367     TOK.catch_,
368     TOK.finally_,
369     TOK.with_,
370     TOK.asm_,
371     TOK.foreach_,
372     TOK.foreach_reverse_,
373     TOK.scope_,
374     TOK.struct_,
375     TOK.class_,
376     TOK.interface_,
377     TOK.union_,
378     TOK.enum_,
379     TOK.import_,
380     TOK.mixin_,
381     TOK.static_,
382     TOK.final_,
383     TOK.const_,
384     TOK.alias_,
385     TOK.override_,
386     TOK.abstract_,
387     TOK.debug_,
388     TOK.deprecated_,
389     TOK.in_,
390     TOK.out_,
391     TOK.inout_,
392     TOK.lazy_,
393     TOK.auto_,
394     TOK.align_,
395     TOK.extern_,
396     TOK.private_,
397     TOK.package_,
398     TOK.protected_,
399     TOK.public_,
400     TOK.export_,
401     TOK.invariant_,
402     TOK.unittest_,
403     TOK.version_,
404     TOK.argumentTypes,
405     TOK.parameters,
406     TOK.ref_,
407     TOK.macro_,
408     TOK.pure_,
409     TOK.nothrow_,
410     TOK.gshared,
411     TOK.traits,
412     TOK.vector,
413     TOK.overloadSet,
414     TOK.file,
415     TOK.fileFullPath,
416     TOK.line,
417     TOK.moduleString,
418     TOK.functionString,
419     TOK.prettyFunction,
420     TOK.shared_,
421     TOK.immutable_,
422 ];
423 
424 // Initialize the identifier pool
425 shared static this() nothrow
426 {
427     Identifier.initTable();
428     foreach (kw; keywords)
429     {
430         //printf("keyword[%d] = '%s'\n",kw, tochars[kw].ptr);
431         Identifier.idPool(Token.tochars[kw].ptr, Token.tochars[kw].length, cast(uint)kw);
432     }
433 }
434 
435 /***********************************************************
436  */
437 extern (C++) struct Token
438 {
439     Token* next;
440     Loc loc;
441     const(char)* ptr; // pointer to first character of this token within buffer
442     TOK value;
443     const(char)[] blockComment; // doc comment string prior to this token
444     const(char)[] lineComment; // doc comment for previous token
445 
446     union
447     {
448         // Integers
449         sinteger_t intvalue;
450         uinteger_t unsvalue;
451         // Floats
452         real_t floatvalue;
453 
454         struct
455         {
456             const(char)* ustring; // UTF8 string
457             uint len;
458             ubyte postfix; // 'c', 'w', 'd'
459         }
460 
461         Identifier ident;
462     }
463 
464     extern (D) private static immutable string[TOK.max_] tochars =
465     [
466         // Keywords
467         TOK.this_: "this",
468         TOK.super_: "super",
469         TOK.assert_: "assert",
470         TOK.null_: "null",
471         TOK.true_: "true",
472         TOK.false_: "false",
473         TOK.cast_: "cast",
474         TOK.new_: "new",
475         TOK.delete_: "delete",
476         TOK.throw_: "throw",
477         TOK.module_: "module",
478         TOK.pragma_: "pragma",
479         TOK.typeof_: "typeof",
480         TOK.typeid_: "typeid",
481         TOK.template_: "template",
482         TOK.void_: "void",
483         TOK.int8: "byte",
484         TOK.uns8: "ubyte",
485         TOK.int16: "short",
486         TOK.uns16: "ushort",
487         TOK.int32: "int",
488         TOK.uns32: "uint",
489         TOK.int64: "long",
490         TOK.uns64: "ulong",
491         TOK.int128: "cent",
492         TOK.uns128: "ucent",
493         TOK.float32: "float",
494         TOK.float64: "double",
495         TOK.float80: "real",
496         TOK.bool_: "bool",
497         TOK.char_: "char",
498         TOK.wchar_: "wchar",
499         TOK.dchar_: "dchar",
500         TOK.imaginary32: "ifloat",
501         TOK.imaginary64: "idouble",
502         TOK.imaginary80: "ireal",
503         TOK.complex32: "cfloat",
504         TOK.complex64: "cdouble",
505         TOK.complex80: "creal",
506         TOK.delegate_: "delegate",
507         TOK.function_: "function",
508         TOK.is_: "is",
509         TOK.if_: "if",
510         TOK.else_: "else",
511         TOK.while_: "while",
512         TOK.for_: "for",
513         TOK.do_: "do",
514         TOK.switch_: "switch",
515         TOK.case_: "case",
516         TOK.default_: "default",
517         TOK.break_: "break",
518         TOK.continue_: "continue",
519         TOK.synchronized_: "synchronized",
520         TOK.return_: "return",
521         TOK.goto_: "goto",
522         TOK.try_: "try",
523         TOK.catch_: "catch",
524         TOK.finally_: "finally",
525         TOK.with_: "with",
526         TOK.asm_: "asm",
527         TOK.foreach_: "foreach",
528         TOK.foreach_reverse_: "foreach_reverse",
529         TOK.scope_: "scope",
530         TOK.struct_: "struct",
531         TOK.class_: "class",
532         TOK.interface_: "interface",
533         TOK.union_: "union",
534         TOK.enum_: "enum",
535         TOK.import_: "import",
536         TOK.mixin_: "mixin",
537         TOK.static_: "static",
538         TOK.final_: "final",
539         TOK.const_: "const",
540         TOK.alias_: "alias",
541         TOK.override_: "override",
542         TOK.abstract_: "abstract",
543         TOK.debug_: "debug",
544         TOK.deprecated_: "deprecated",
545         TOK.in_: "in",
546         TOK.out_: "out",
547         TOK.inout_: "inout",
548         TOK.lazy_: "lazy",
549         TOK.auto_: "auto",
550         TOK.align_: "align",
551         TOK.extern_: "extern",
552         TOK.private_: "private",
553         TOK.package_: "package",
554         TOK.protected_: "protected",
555         TOK.public_: "public",
556         TOK.export_: "export",
557         TOK.invariant_: "invariant",
558         TOK.unittest_: "unittest",
559         TOK.version_: "version",
560         TOK.argumentTypes: "__argTypes",
561         TOK.parameters: "__parameters",
562         TOK.ref_: "ref",
563         TOK.macro_: "macro",
564         TOK.pure_: "pure",
565         TOK.nothrow_: "nothrow",
566         TOK.gshared: "__gshared",
567         TOK.traits: "__traits",
568         TOK.vector: "__vector",
569         TOK.overloadSet: "__overloadset",
570         TOK.file: "__FILE__",
571         TOK.fileFullPath: "__FILE_FULL_PATH__",
572         TOK.line: "__LINE__",
573         TOK.moduleString: "__MODULE__",
574         TOK.functionString: "__FUNCTION__",
575         TOK.prettyFunction: "__PRETTY_FUNCTION__",
576         TOK.shared_: "shared",
577         TOK.immutable_: "immutable",
578 
579         TOK.endOfFile: "End of File",
580         TOK.leftCurly: "{",
581         TOK.rightCurly: "}",
582         TOK.leftParentheses: "(",
583         TOK.rightParentheses: ")",
584         TOK.leftBracket: "[",
585         TOK.rightBracket: "]",
586         TOK.semicolon: ";",
587         TOK.colon: ":",
588         TOK.comma: ",",
589         TOK.dot: ".",
590         TOK.xor: "^",
591         TOK.xorAssign: "^=",
592         TOK.assign: "=",
593         TOK.construct: "=",
594         TOK.blit: "=",
595         TOK.lessThan: "<",
596         TOK.greaterThan: ">",
597         TOK.lessOrEqual: "<=",
598         TOK.greaterOrEqual: ">=",
599         TOK.equal: "==",
600         TOK.notEqual: "!=",
601         TOK.not: "!",
602         TOK.leftShift: "<<",
603         TOK.rightShift: ">>",
604         TOK.unsignedRightShift: ">>>",
605         TOK.add: "+",
606         TOK.min: "-",
607         TOK.mul: "*",
608         TOK.div: "/",
609         TOK.mod: "%",
610         TOK.slice: "..",
611         TOK.dotDotDot: "...",
612         TOK.and: "&",
613         TOK.andAnd: "&&",
614         TOK.or: "|",
615         TOK.orOr: "||",
616         TOK.array: "[]",
617         TOK.index: "[i]",
618         TOK.address: "&",
619         TOK.star: "*",
620         TOK.tilde: "~",
621         TOK.dollar: "$",
622         TOK.plusPlus: "++",
623         TOK.minusMinus: "--",
624         TOK.prePlusPlus: "++",
625         TOK.preMinusMinus: "--",
626         TOK.type: "type",
627         TOK.question: "?",
628         TOK.negate: "-",
629         TOK.uadd: "+",
630         TOK.variable: "var",
631         TOK.addAssign: "+=",
632         TOK.minAssign: "-=",
633         TOK.mulAssign: "*=",
634         TOK.divAssign: "/=",
635         TOK.modAssign: "%=",
636         TOK.leftShiftAssign: "<<=",
637         TOK.rightShiftAssign: ">>=",
638         TOK.unsignedRightShiftAssign: ">>>=",
639         TOK.andAssign: "&=",
640         TOK.orAssign: "|=",
641         TOK.concatenateAssign: "~=",
642         TOK.concatenateElemAssign: "~=",
643         TOK.concatenateDcharAssign: "~=",
644         TOK.concatenate: "~",
645         TOK.call: "call",
646         TOK.identity: "is",
647         TOK.notIdentity: "!is",
648         TOK.identifier: "identifier",
649         TOK.at: "@",
650         TOK.pow: "^^",
651         TOK.powAssign: "^^=",
652         TOK.goesTo: "=>",
653         TOK.pound: "#",
654 
655         // For debugging
656         TOK.error: "error",
657         TOK.dotIdentifier: "dotid",
658         TOK.dotTemplateDeclaration: "dottd",
659         TOK.dotTemplateInstance: "dotti",
660         TOK.dotVariable: "dotvar",
661         TOK.dotType: "dottype",
662         TOK.symbolOffset: "symoff",
663         TOK.arrayLength: "arraylength",
664         TOK.arrayLiteral: "arrayliteral",
665         TOK.assocArrayLiteral: "assocarrayliteral",
666         TOK.structLiteral: "structliteral",
667         TOK.string_: "string",
668         TOK.dSymbol: "symbol",
669         TOK.tuple: "tuple",
670         TOK.declaration: "declaration",
671         TOK.onScopeExit: "scope(exit)",
672         TOK.onScopeSuccess: "scope(success)",
673         TOK.onScopeFailure: "scope(failure)",
674         TOK.delegatePointer: "delegateptr",
675 
676         // Finish up
677         TOK.reserved: "reserved",
678         TOK.remove: "remove",
679         TOK.newAnonymousClass: "newanonclass",
680         TOK.comment: "comment",
681         TOK.classReference: "classreference",
682         TOK.thrownException: "thrownexception",
683         TOK.delegateFunctionPointer: "delegatefuncptr",
684         TOK.int32Literal: "int32v",
685         TOK.uns32Literal: "uns32v",
686         TOK.int64Literal: "int64v",
687         TOK.uns64Literal: "uns64v",
688         TOK.int128Literal: "int128v",
689         TOK.uns128Literal: "uns128v",
690         TOK.float32Literal: "float32v",
691         TOK.float64Literal: "float64v",
692         TOK.float80Literal: "float80v",
693         TOK.imaginary32Literal: "imaginary32v",
694         TOK.imaginary64Literal: "imaginary64v",
695         TOK.imaginary80Literal: "imaginary80v",
696         TOK.charLiteral: "charv",
697         TOK.wcharLiteral: "wcharv",
698         TOK.dcharLiteral: "dcharv",
699 
700         TOK.halt: "halt",
701         TOK.hexadecimalString: "xstring",
702 
703         TOK.interval: "interval",
704         TOK.voidExpression: "voidexp",
705         TOK.cantExpression: "cantexp",
706         TOK.showCtfeContext : "showCtfeContext",
707 
708         TOK.objcClassReference: "class",
709         TOK.vectorArray: "vectorarray",
710     ];
711 
712     static assert(() {
713         foreach (s; tochars)
714             assert(s.length);
715         return true;
716     }());
717 
718 nothrow:
719 
720     int isKeyword() const
721     {
722         foreach (kw; keywords)
723         {
724             if (kw == value)
725                 return 1;
726         }
727         return 0;
728     }
729 
730     /****
731      * Set to contents of ptr[0..length]
732      * Params:
733      *  ptr = pointer to string
734      *  length = length of string
735      */
736     void setString(const(char)* ptr, size_t length)
737     {
738         auto s = cast(char*)mem.xmalloc_noscan(length + 1);
739         memcpy(s, ptr, length);
740         s[length] = 0;
741         ustring = s;
742         len = cast(uint)length;
743         postfix = 0;
744     }
745 
746     /****
747      * Set to contents of buf
748      * Params:
749      *  buf = string (not zero terminated)
750      */
751     void setString(const ref OutBuffer buf)
752     {
753         setString(cast(const(char)*)buf[].ptr, buf.length);
754     }
755 
756     /****
757      * Set to empty string
758      */
759     void setString()
760     {
761         ustring = "";
762         len = 0;
763         postfix = 0;
764     }
765 
766     extern (C++) const(char)* toChars() const
767     {
768         __gshared char[3 + 3 * floatvalue.sizeof + 1] buffer;
769         const(char)* p = &buffer[0];
770         switch (value)
771         {
772         case TOK.int32Literal:
773             sprintf(&buffer[0], "%d", cast(d_int32)intvalue);
774             break;
775         case TOK.uns32Literal:
776         case TOK.charLiteral:
777         case TOK.wcharLiteral:
778         case TOK.dcharLiteral:
779             sprintf(&buffer[0], "%uU", cast(d_uns32)unsvalue);
780             break;
781         case TOK.int64Literal:
782             sprintf(&buffer[0], "%lldL", cast(long)intvalue);
783             break;
784         case TOK.uns64Literal:
785             sprintf(&buffer[0], "%lluUL", cast(ulong)unsvalue);
786             break;
787         case TOK.float32Literal:
788             CTFloat.sprint(&buffer[0], 'g', floatvalue);
789             strcat(&buffer[0], "f");
790             break;
791         case TOK.float64Literal:
792             CTFloat.sprint(&buffer[0], 'g', floatvalue);
793             break;
794         case TOK.float80Literal:
795             CTFloat.sprint(&buffer[0], 'g', floatvalue);
796             strcat(&buffer[0], "L");
797             break;
798         case TOK.imaginary32Literal:
799             CTFloat.sprint(&buffer[0], 'g', floatvalue);
800             strcat(&buffer[0], "fi");
801             break;
802         case TOK.imaginary64Literal:
803             CTFloat.sprint(&buffer[0], 'g', floatvalue);
804             strcat(&buffer[0], "i");
805             break;
806         case TOK.imaginary80Literal:
807             CTFloat.sprint(&buffer[0], 'g', floatvalue);
808             strcat(&buffer[0], "Li");
809             break;
810         case TOK.string_:
811             {
812                 OutBuffer buf;
813                 buf.writeByte('"');
814                 for (size_t i = 0; i < len;)
815                 {
816                     dchar c;
817                     utf_decodeChar(ustring[0 .. len], i, c);
818                     switch (c)
819                     {
820                     case 0:
821                         break;
822                     case '"':
823                     case '\\':
824                         buf.writeByte('\\');
825                         goto default;
826                     default:
827                         if (c <= 0x7F)
828                         {
829                             if (isprint(c))
830                                 buf.writeByte(c);
831                             else
832                                 buf.printf("\\x%02x", c);
833                         }
834                         else if (c <= 0xFFFF)
835                             buf.printf("\\u%04x", c);
836                         else
837                             buf.printf("\\U%08x", c);
838                         continue;
839                     }
840                     break;
841                 }
842                 buf.writeByte('"');
843                 if (postfix)
844                     buf.writeByte(postfix);
845                 buf.writeByte(0);
846                 p = buf.extractSlice().ptr;
847             }
848             break;
849         case TOK.hexadecimalString:
850             {
851                 OutBuffer buf;
852                 buf.writeByte('x');
853                 buf.writeByte('"');
854                 foreach (size_t i; 0 .. len)
855                 {
856                     if (i)
857                         buf.writeByte(' ');
858                     buf.printf("%02x", ustring[i]);
859                 }
860                 buf.writeByte('"');
861                 if (postfix)
862                     buf.writeByte(postfix);
863                 buf.writeByte(0);
864                 p = buf.extractSlice().ptr;
865                 break;
866             }
867         case TOK.identifier:
868         case TOK.enum_:
869         case TOK.struct_:
870         case TOK.import_:
871         case TOK.wchar_:
872         case TOK.dchar_:
873         case TOK.bool_:
874         case TOK.char_:
875         case TOK.int8:
876         case TOK.uns8:
877         case TOK.int16:
878         case TOK.uns16:
879         case TOK.int32:
880         case TOK.uns32:
881         case TOK.int64:
882         case TOK.uns64:
883         case TOK.int128:
884         case TOK.uns128:
885         case TOK.float32:
886         case TOK.float64:
887         case TOK.float80:
888         case TOK.imaginary32:
889         case TOK.imaginary64:
890         case TOK.imaginary80:
891         case TOK.complex32:
892         case TOK.complex64:
893         case TOK.complex80:
894         case TOK.void_:
895             p = ident.toChars();
896             break;
897         default:
898             p = toChars(value);
899             break;
900         }
901         return p;
902     }
903 
904     static const(char)* toChars(ubyte value)
905     {
906         return toString(value).ptr;
907     }
908 
909     extern (D) static string toString(ubyte value) pure nothrow @nogc @safe
910     {
911         return tochars[value];
912     }
913 }