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