2 * Defines lexical tokens.
4 * Specification: $(LINK2 https://dlang.org/spec/lex.html#tokens, Tokens)
6 * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved
7 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
8 * License: $(LINK2 https://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
16 import core
.stdc
.ctype
;
17 import core
.stdc
.stdio
;
18 import core
.stdc
.string
;
19 import dmd
.identifier
;
21 import dmd
.root
.ctfloat
;
22 import dmd
.common
.outbuffer
;
76 unsignedRightShiftAssign
,
77 concatenateAssign
, // ~=
235 moduleString
, // __MODULE__
236 functionString
, // __FUNCTION__
237 prettyFunction
, // __PRETTY_FUNCTION__
249 endOfLine
, // \n, \r, \u2028, \u2029
272 // C only extended keywords
312 dotTemplateDeclaration
,
325 delegateFunctionPointer
,
344 unsignedRightShiftAssign
,
346 concatenateAssign
, // ~=
347 concatenateElemAssign
,
348 concatenateDcharAssign
,
409 moduleString
, // __MODULE__
410 functionString
, // __FUNCTION__
411 prettyFunction
, // __PRETTY_FUNCTION__
421 compoundLiteral
, // ( type-name ) { initializer-list }
428 enum FirstCKeyword
= TOK
.inline
;
430 // Assert that all token enum members have consecutive values and
431 // that none of them overlap
433 foreach (idx
, enumName
; __traits(allMembers
, TOK
)) {
434 static if (idx
!= __traits(getMember
, TOK
, enumName
)) {
435 pragma(msg
, "Error: Expected TOK.", enumName
, " to be ", idx
, " but is ", __traits(getMember
, TOK
, enumName
));
442 /****************************************
445 private immutable TOK
[] keywords
=
508 TOK
.foreach_reverse_
,
578 // C only extended keywords
590 // Initialize the identifier pool
591 shared static this() nothrow
593 Identifier
.initTable();
594 foreach (kw
; keywords
)
596 //printf("keyword[%d] = '%s'\n",kw, Token.tochars[kw].ptr);
597 Identifier
.idPool(Token
.tochars
[kw
], kw
);
601 /************************************
602 * This is used to pick the C keywords out of the tokens.
603 * If it's not a C keyword, then it's an identifier.
605 static immutable TOK
[TOK
.max
+ 1] Ckeywords
=
609 TOK
[TOK
.max
+ 1] tab
= identifier
; // default to identifier
610 enum Ckwds
= [ auto_
, break_
, case_
, char_
, const_
, continue_
, default_
, do_
, float64
, else_
,
611 enum_
, extern_
, float32
, for_
, goto_
, if_
, inline
, int32
, int64
, register
,
612 restrict
, return_
, int16
, signed
, sizeof_
, static_
, struct_
, switch_
, typedef_
,
613 union_
, unsigned
, void_
, volatile, while_
, asm_
, typeof_
,
614 _Alignas
, _Alignof
, _Atomic
, _Bool
, _Complex
, _Generic
, _Imaginary
, _Noreturn
,
615 _Static_assert
, _Thread_local
,
616 _import
, __cdecl
, __declspec
, __stdcall
, __thread
, __pragma
, __int128
, __attribute__
,
620 tab
[kw
] = cast(TOK
) kw
;
627 /***********************************************************
629 extern (C
++) struct Token
633 const(char)* ptr
; // pointer to first character of this token within buffer
635 const(char)[] blockComment
; // doc comment string prior to this token
636 const(char)[] lineComment
; // doc comment for previous token
648 const(char)* ustring
; // UTF8 string
650 ubyte postfix
; // 'c', 'w', 'd'
656 extern (D
) private static immutable string
[TOK
.max
+ 1] tochars
=
661 TOK
.assert_
: "assert",
667 TOK
.delete_
: "delete",
669 TOK
.module_
: "module",
670 TOK
.pragma_
: "pragma",
671 TOK
.typeof_
: "typeof",
672 TOK
.typeid_
: "typeid",
673 TOK
.template_
: "template",
685 TOK
.float32
: "float",
686 TOK
.float64
: "double",
692 TOK
.imaginary32
: "ifloat",
693 TOK
.imaginary64
: "idouble",
694 TOK
.imaginary80
: "ireal",
695 TOK
.complex32
: "cfloat",
696 TOK
.complex64
: "cdouble",
697 TOK
.complex80
: "creal",
698 TOK
.delegate_
: "delegate",
699 TOK
.function_
: "function",
706 TOK
.switch_
: "switch",
708 TOK
.default_
: "default",
710 TOK
.continue_
: "continue",
711 TOK
.synchronized_
: "synchronized",
712 TOK
.return_
: "return",
716 TOK
.finally_
: "finally",
719 TOK
.foreach_
: "foreach",
720 TOK
.foreach_reverse_
: "foreach_reverse",
722 TOK
.struct_
: "struct",
724 TOK
.interface_
: "interface",
727 TOK
.import_
: "import",
729 TOK
.static_
: "static",
733 TOK
.override_
: "override",
734 TOK
.abstract_
: "abstract",
736 TOK
.deprecated_
: "deprecated",
743 TOK
.extern_
: "extern",
744 TOK
.private_
: "private",
745 TOK
.package_
: "package",
746 TOK
.protected_
: "protected",
747 TOK
.public_
: "public",
748 TOK
.export_
: "export",
749 TOK
.invariant_
: "invariant",
750 TOK
.unittest_
: "unittest",
751 TOK
.version_
: "version",
752 TOK
.argumentTypes
: "__argTypes",
753 TOK
.parameters
: "__parameters",
757 TOK
.nothrow_
: "nothrow",
758 TOK
.gshared
: "__gshared",
759 TOK
.traits
: "__traits",
760 TOK
.vector
: "__vector",
761 TOK
.file
: "__FILE__",
762 TOK
.fileFullPath
: "__FILE_FULL_PATH__",
763 TOK
.line
: "__LINE__",
764 TOK
.moduleString
: "__MODULE__",
765 TOK
.functionString
: "__FUNCTION__",
766 TOK
.prettyFunction
: "__PRETTY_FUNCTION__",
767 TOK
.shared_
: "shared",
768 TOK
.immutable_
: "immutable",
770 TOK
.endOfFile
: "End of File",
773 TOK
.leftParenthesis
: "(",
774 TOK
.rightParenthesis
: ")",
775 TOK
.leftBracket
: "[",
776 TOK
.rightBracket
: "]",
785 TOK
.greaterThan
: ">",
786 TOK
.lessOrEqual
: "<=",
787 TOK
.greaterOrEqual
: ">=",
792 TOK
.rightShift
: ">>",
793 TOK
.unsignedRightShift
: ">>>",
800 TOK
.dotDotDot
: "...",
808 TOK
.minusMinus
: "--",
816 TOK
.leftShiftAssign
: "<<=",
817 TOK
.rightShiftAssign
: ">>=",
818 TOK
.unsignedRightShiftAssign
: ">>>=",
821 TOK
.concatenateAssign
: "~=",
823 TOK
.notIdentity
: "!is",
824 TOK
.identifier
: "identifier",
827 TOK
.powAssign
: "^^=",
831 TOK
.colonColon
: "::",
835 TOK
.string_
: "string",
836 TOK
.onScopeExit
: "scope(exit)",
837 TOK
.onScopeSuccess
: "scope(success)",
838 TOK
.onScopeFailure
: "scope(failure)",
841 TOK
.reserved
: "reserved",
842 TOK
.comment
: "comment",
843 TOK
.int32Literal
: "int32v",
844 TOK
.uns32Literal
: "uns32v",
845 TOK
.int64Literal
: "int64v",
846 TOK
.uns64Literal
: "uns64v",
847 TOK
.int128Literal
: "int128v",
848 TOK
.uns128Literal
: "uns128v",
849 TOK
.float32Literal
: "float32v",
850 TOK
.float64Literal
: "float64v",
851 TOK
.float80Literal
: "float80v",
852 TOK
.imaginary32Literal
: "imaginary32v",
853 TOK
.imaginary64Literal
: "imaginary64v",
854 TOK
.imaginary80Literal
: "imaginary80v",
855 TOK
.charLiteral
: "charv",
856 TOK
.wcharLiteral
: "wcharv",
857 TOK
.dcharLiteral
: "dcharv",
858 TOK
.wchar_tLiteral
: "wchar_tv",
859 TOK
.hexadecimalString
: "xstring",
860 TOK
.endOfLine
: "\\n",
861 TOK
.whitespace
: "whitespace",
864 TOK
.inline
: "inline",
865 TOK
.register
: "register",
866 TOK
.restrict
: "restrict",
867 TOK
.signed
: "signed",
868 TOK
.sizeof_
: "sizeof",
869 TOK
.typedef_
: "typedef",
870 TOK
.unsigned
: "unsigned",
871 TOK
.volatile : "volatile",
872 TOK
._Alignas
: "_Alignas",
873 TOK
._Alignof
: "_Alignof",
874 TOK
._Atomic
: "_Atomic",
876 TOK
._Complex
: "_Complex",
877 TOK
._Generic
: "_Generic",
878 TOK
._Imaginary
: "_Imaginary",
879 TOK
._Noreturn
: "_Noreturn",
880 TOK
._Static_assert
: "_Static_assert",
881 TOK
._Thread_local
: "_Thread_local",
883 // C only extended keywords
884 TOK
._assert
: "__check",
885 TOK
._import
: "__import",
886 TOK
.__cdecl
: "__cdecl",
887 TOK
.__declspec
: "__declspec",
888 TOK
.__stdcall
: "__stdcall",
889 TOK
.__thread
: "__thread",
890 TOK
.__pragma
: "__pragma",
891 TOK
.__int128
: "__int128",
892 TOK
.__attribute__
: "__attribute__",
903 extern (D
) int isKeyword() pure const @safe @nogc
905 foreach (kw
; keywords
)
914 * Set to contents of ptr[0..length]
916 * ptr = pointer to string
917 * length = length of string
919 void setString(const(char)* ptr
, size_t length
)
921 auto s
= cast(char*)mem
.xmalloc_noscan(length
+ 1);
922 memcpy(s
, ptr
, length
);
925 len
= cast(uint)length
;
930 * Set to contents of buf
932 * buf = string (not zero terminated)
934 void setString(const ref OutBuffer buf
)
936 setString(cast(const(char)*)buf
[].ptr
, buf
.length
);
940 * Set to empty string
949 extern (C
++) const(char)* toChars() const
951 return toString().ptr
;
954 /*********************************
956 * a zero-terminated string representation of the token,
957 * sometimes reusing a static buffer, sometimes leaking memory
959 extern (D
) const(char)[] toString() const
961 const bufflen
= 3 + 3 * floatvalue
.sizeof
+ 1;
962 __gshared
char[bufflen
+ 2] buffer
; // extra 2 for suffixes
963 char* p
= &buffer
[0];
966 case TOK
.int32Literal
:
967 const length
= snprintf(p
, bufflen
, "%d", cast(int)intvalue
);
968 return p
[0 .. length
];
970 case TOK
.uns32Literal
:
971 case TOK
.wchar_tLiteral
:
972 const length
= snprintf(p
, bufflen
, "%uU", cast(uint)unsvalue
);
973 return p
[0 .. length
];
975 case TOK
.wcharLiteral
:
976 case TOK
.dcharLiteral
:
977 case TOK
.charLiteral
:
979 buf
.writeSingleCharLiteral(cast(dchar) intvalue
);
980 return buf
.extractSlice(true);
982 case TOK
.int64Literal
:
983 const length
= snprintf(p
, bufflen
, "%lldL", cast(long)intvalue
);
984 return p
[0 .. length
];
986 case TOK
.uns64Literal
:
987 const length
= snprintf(p
, bufflen
, "%lluUL", cast(ulong)unsvalue
);
988 return p
[0 .. length
];
990 case TOK
.float32Literal
:
991 const length
= CTFloat
.sprint(p
, bufflen
, 'g', floatvalue
);
994 return p
[0 .. length
+ 1];
996 case TOK
.float64Literal
:
997 const length
= CTFloat
.sprint(p
, bufflen
, 'g', floatvalue
);
998 return p
[0 .. length
];
1000 case TOK
.float80Literal
:
1001 const length
= CTFloat
.sprint(p
, bufflen
, 'g', floatvalue
);
1004 return p
[0 .. length
+ 1];
1006 case TOK
.imaginary32Literal
:
1007 const length
= CTFloat
.sprint(p
, bufflen
, 'g', floatvalue
);
1009 p
[length
+ 1] = 'i';
1011 return p
[0 .. length
+ 2];
1013 case TOK
.imaginary64Literal
:
1014 const length
= CTFloat
.sprint(p
, bufflen
, 'g', floatvalue
);
1017 return p
[0 .. length
+ 1];
1019 case TOK
.imaginary80Literal
:
1020 const length
= CTFloat
.sprint(p
, bufflen
, 'g', floatvalue
);
1022 p
[length
+ 1] = 'i';
1024 return p
[0 .. length
+ 2];
1029 for (size_t i
= 0; i
< len
;)
1032 utf_decodeChar(ustring
[0 .. len
], i
, c
);
1033 writeCharLiteral(buf
, c
);
1037 buf
.writeByte(postfix
);
1038 return buf
.extractSlice(true);
1040 case TOK
.hexadecimalString
:
1044 foreach (size_t i
; 0 .. len
)
1048 buf
.printf("%02x", ustring
[i
]);
1052 buf
.writeByte(postfix
);
1053 return buf
.extractSlice(true);
1055 case TOK
.identifier
:
1076 case TOK
.imaginary32
:
1077 case TOK
.imaginary64
:
1078 case TOK
.imaginary80
:
1083 return ident
.toString();
1086 return tochars
[value
];
1090 static const(char)* toChars(TOK value
)
1092 return toString(value
).ptr
;
1095 extern (D
) static string
toString(TOK value
) pure nothrow @nogc @safe
1097 return tochars
[value
];
1102 * Write a character, using a readable escape sequence if needed
1104 * Useful for printing "" string literals in e.g. error messages, ddoc, or the `.stringof` property
1107 * buf = buffer to append character in
1108 * c = code point to write
1111 void writeCharLiteral(ref OutBuffer buf
, dchar c
)
1116 buf
.writestring("\\0");
1119 buf
.writestring("\\n");
1122 buf
.writestring("\\r");
1125 buf
.writestring("\\t");
1128 buf
.writestring("\\b");
1131 buf
.writestring("\\f");
1135 buf
.writeByte('\\');
1143 buf
.printf("\\x%02x", c
);
1145 else if (c
<= 0xFFFF)
1146 buf
.printf("\\u%04x", c
);
1148 buf
.printf("\\U%08x", c
);
1156 foreach(dchar d
; "a\n\r\t\b\f\0\x11\u7233\U00017233"d
)
1158 writeCharLiteral(buf
, d
);
1160 assert(buf
[] == `a\n\r\t\b\f\0\x11\u7233\U00017233`);
1164 * Write a single-quoted character literal
1166 * Useful for printing '' char literals in e.g. error messages, ddoc, or the `.stringof` property
1169 * buf = buffer to append character in
1170 * c = code point to write
1173 void writeSingleCharLiteral(ref OutBuffer buf
, dchar c
)
1175 buf
.writeByte('\'');
1177 buf
.writeByte('\\');
1182 writeCharLiteral(buf
, c
);
1184 buf
.writeByte('\'');
1190 writeSingleCharLiteral(buf
, '\'');
1191 assert(buf
[] == `'\''`);
1193 writeSingleCharLiteral(buf
, '"');
1194 assert(buf
[] == `'"'`);
1196 writeSingleCharLiteral(buf
, '\n');
1197 assert(buf
[] == `'\n'`);