/* Compiler implementation of the D programming language * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved * written by Walter Bright * http://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. * http://www.boost.org/LICENSE_1_0.txt * https://github.com/D-Programming-Language/dmd/blob/master/src/lexer.c */ #include "root/dsystem.h" #include "tokens.h" #include "root/rmem.h" #include "root/outbuffer.h" #include "id.h" #include "identifier.h" #include "utf.h" /************************* Token **********************************************/ Token *Token::freelist = NULL; const char *Token::tochars[TOKMAX]; Token *Token::alloc() { if (Token::freelist) { Token *t = freelist; freelist = t->next; t->next = NULL; return t; } return new Token(); } void Token::free() { next = freelist; freelist = this; } const char *Token::toChars() const { static char buffer[3 + 3 * sizeof(floatvalue) + 1]; const char *p = &buffer[0]; switch (value) { case TOKint32v: sprintf(&buffer[0],"%d",(d_int32)int64value); break; case TOKuns32v: case TOKcharv: case TOKwcharv: case TOKdcharv: sprintf(&buffer[0],"%uU",(d_uns32)uns64value); break; case TOKint64v: sprintf(&buffer[0],"%lldL",(longlong)int64value); break; case TOKuns64v: sprintf(&buffer[0],"%lluUL",(ulonglong)uns64value); break; case TOKfloat32v: CTFloat::sprint(&buffer[0], 'g', floatvalue); strcat(&buffer[0], "f"); break; case TOKfloat64v: CTFloat::sprint(&buffer[0], 'g', floatvalue); break; case TOKfloat80v: CTFloat::sprint(&buffer[0], 'g', floatvalue); strcat(&buffer[0], "L"); break; case TOKimaginary32v: CTFloat::sprint(&buffer[0], 'g', floatvalue); strcat(&buffer[0], "fi"); break; case TOKimaginary64v: CTFloat::sprint(&buffer[0], 'g', floatvalue); strcat(&buffer[0], "i"); break; case TOKimaginary80v: CTFloat::sprint(&buffer[0], 'g', floatvalue); strcat(&buffer[0], "Li"); break; case TOKstring: { OutBuffer buf; buf.writeByte('"'); for (size_t i = 0; i < len; ) { unsigned c; utf_decodeChar((utf8_t *)ustring, len, &i, &c); switch (c) { case 0: break; case '"': case '\\': buf.writeByte('\\'); /* fall through */ default: if (c <= 0x7F) { if (isprint(c)) buf.writeByte(c); else buf.printf("\\x%02x", c); } else if (c <= 0xFFFF) buf.printf("\\u%04x", c); else buf.printf("\\U%08x", c); continue; } break; } buf.writeByte('"'); if (postfix) buf.writeByte(postfix); p = buf.extractString(); } break; case TOKxstring: { OutBuffer buf; buf.writeByte('x'); buf.writeByte('"'); for (size_t i = 0; i < len; i++) { if (i) buf.writeByte(' '); buf.printf("%02x", ustring[i]); } buf.writeByte('"'); if (postfix) buf.writeByte(postfix); buf.writeByte(0); p = (char *)buf.extractData(); break; } case TOKidentifier: case TOKenum: case TOKstruct: case TOKimport: case TOKwchar: case TOKdchar: case TOKbool: case TOKchar: case TOKint8: case TOKuns8: case TOKint16: case TOKuns16: case TOKint32: case TOKuns32: case TOKint64: case TOKuns64: case TOKint128: case TOKuns128: case TOKfloat32: case TOKfloat64: case TOKfloat80: case TOKimaginary32: case TOKimaginary64: case TOKimaginary80: case TOKcomplex32: case TOKcomplex64: case TOKcomplex80: case TOKvoid: p = ident->toChars(); break; default: p = toChars(value); break; } return p; } const char *Token::toChars(TOK value) { static char buffer[3 + 3 * sizeof(value) + 1]; const char *p = tochars[value]; if (!p) { sprintf(&buffer[0],"TOK%d",value); p = &buffer[0]; } return p; } /**************************************** */ struct Keyword { const char *name; TOK value; }; static size_t nkeywords; static Keyword keywords[] = { { "this", TOKthis }, { "super", TOKsuper }, { "assert", TOKassert }, { "null", TOKnull }, { "true", TOKtrue }, { "false", TOKfalse }, { "cast", TOKcast }, { "new", TOKnew }, { "delete", TOKdelete }, { "throw", TOKthrow }, { "module", TOKmodule }, { "pragma", TOKpragma }, { "typeof", TOKtypeof }, { "typeid", TOKtypeid }, { "template", TOKtemplate }, { "void", TOKvoid }, { "byte", TOKint8 }, { "ubyte", TOKuns8 }, { "short", TOKint16 }, { "ushort", TOKuns16 }, { "int", TOKint32 }, { "uint", TOKuns32 }, { "long", TOKint64 }, { "ulong", TOKuns64 }, { "cent", TOKint128, }, { "ucent", TOKuns128, }, { "float", TOKfloat32 }, { "double", TOKfloat64 }, { "real", TOKfloat80 }, { "bool", TOKbool }, { "char", TOKchar }, { "wchar", TOKwchar }, { "dchar", TOKdchar }, { "ifloat", TOKimaginary32 }, { "idouble", TOKimaginary64 }, { "ireal", TOKimaginary80 }, { "cfloat", TOKcomplex32 }, { "cdouble", TOKcomplex64 }, { "creal", TOKcomplex80 }, { "delegate", TOKdelegate }, { "function", TOKfunction }, { "is", TOKis }, { "if", TOKif }, { "else", TOKelse }, { "while", TOKwhile }, { "for", TOKfor }, { "do", TOKdo }, { "switch", TOKswitch }, { "case", TOKcase }, { "default", TOKdefault }, { "break", TOKbreak }, { "continue", TOKcontinue }, { "synchronized", TOKsynchronized }, { "return", TOKreturn }, { "goto", TOKgoto }, { "try", TOKtry }, { "catch", TOKcatch }, { "finally", TOKfinally }, { "with", TOKwith }, { "asm", TOKasm }, { "foreach", TOKforeach }, { "foreach_reverse", TOKforeach_reverse }, { "scope", TOKscope }, { "struct", TOKstruct }, { "class", TOKclass }, { "interface", TOKinterface }, { "union", TOKunion }, { "enum", TOKenum }, { "import", TOKimport }, { "mixin", TOKmixin }, { "static", TOKstatic }, { "final", TOKfinal }, { "const", TOKconst }, { "alias", TOKalias }, { "override", TOKoverride }, { "abstract", TOKabstract }, { "debug", TOKdebug }, { "deprecated", TOKdeprecated }, { "in", TOKin }, { "out", TOKout }, { "inout", TOKinout }, { "lazy", TOKlazy }, { "auto", TOKauto }, { "align", TOKalign }, { "extern", TOKextern }, { "private", TOKprivate }, { "package", TOKpackage }, { "protected", TOKprotected }, { "public", TOKpublic }, { "export", TOKexport }, { "invariant", TOKinvariant }, { "unittest", TOKunittest }, { "version", TOKversion }, { "__argTypes", TOKargTypes }, { "__parameters", TOKparameters }, { "ref", TOKref }, { "macro", TOKmacro }, { "pure", TOKpure }, { "nothrow", TOKnothrow }, { "__gshared", TOKgshared }, { "__traits", TOKtraits }, { "__vector", TOKvector }, { "__overloadset", TOKoverloadset }, { "__FILE__", TOKfile }, { "__FILE_FULL_PATH__", TOKfilefullpath }, { "__LINE__", TOKline }, { "__MODULE__", TOKmodulestring }, { "__FUNCTION__", TOKfuncstring }, { "__PRETTY_FUNCTION__", TOKprettyfunc }, { "shared", TOKshared }, { "immutable", TOKimmutable }, { NULL, TOKreserved } }; int Token::isKeyword() { for (size_t u = 0; u < nkeywords; u++) { if (keywords[u].value == value) return 1; } return 0; } struct TokenInitializer { TokenInitializer(); }; static TokenInitializer tokeninitializer; TokenInitializer::TokenInitializer() { Identifier::initTable(); for (nkeywords = 0; keywords[nkeywords].name; nkeywords++) { //printf("keyword[%d] = '%s'\n",u, keywords[u].name); const char *s = keywords[nkeywords].name; size_t len = strlen(s); TOK v = keywords[nkeywords].value; Identifier::idPool(s, len, v); //printf("tochars[%d] = '%s'\n",v, s); Token::tochars[v] = s; } Token::tochars[TOKeof] = "EOF"; Token::tochars[TOKlcurly] = "{"; Token::tochars[TOKrcurly] = "}"; Token::tochars[TOKlparen] = "("; Token::tochars[TOKrparen] = ")"; Token::tochars[TOKlbracket] = "["; Token::tochars[TOKrbracket] = "]"; Token::tochars[TOKsemicolon] = ";"; Token::tochars[TOKcolon] = ":"; Token::tochars[TOKcomma] = ","; Token::tochars[TOKdot] = "."; Token::tochars[TOKxor] = "^"; Token::tochars[TOKxorass] = "^="; Token::tochars[TOKassign] = "="; Token::tochars[TOKconstruct] = "="; Token::tochars[TOKblit] = "="; Token::tochars[TOKlt] = "<"; Token::tochars[TOKgt] = ">"; Token::tochars[TOKle] = "<="; Token::tochars[TOKge] = ">="; Token::tochars[TOKequal] = "=="; Token::tochars[TOKnotequal] = "!="; Token::tochars[TOKnotidentity] = "!is"; Token::tochars[TOKunord] = "!<>="; Token::tochars[TOKue] = "!<>"; Token::tochars[TOKlg] = "<>"; Token::tochars[TOKleg] = "<>="; Token::tochars[TOKule] = "!>"; Token::tochars[TOKul] = "!>="; Token::tochars[TOKuge] = "!<"; Token::tochars[TOKug] = "!<="; Token::tochars[TOKnot] = "!"; Token::tochars[TOKshl] = "<<"; Token::tochars[TOKshr] = ">>"; Token::tochars[TOKushr] = ">>>"; Token::tochars[TOKadd] = "+"; Token::tochars[TOKmin] = "-"; Token::tochars[TOKmul] = "*"; Token::tochars[TOKdiv] = "/"; Token::tochars[TOKmod] = "%"; Token::tochars[TOKslice] = ".."; Token::tochars[TOKdotdotdot] = "..."; Token::tochars[TOKand] = "&"; Token::tochars[TOKandand] = "&&"; Token::tochars[TOKor] = "|"; Token::tochars[TOKoror] = "||"; Token::tochars[TOKarray] = "[]"; Token::tochars[TOKindex] = "[i]"; Token::tochars[TOKaddress] = "&"; Token::tochars[TOKstar] = "*"; Token::tochars[TOKtilde] = "~"; Token::tochars[TOKdollar] = "$"; Token::tochars[TOKcast] = "cast"; Token::tochars[TOKplusplus] = "++"; Token::tochars[TOKminusminus] = "--"; Token::tochars[TOKpreplusplus] = "++"; Token::tochars[TOKpreminusminus] = "--"; Token::tochars[TOKtype] = "type"; Token::tochars[TOKquestion] = "?"; Token::tochars[TOKneg] = "-"; Token::tochars[TOKuadd] = "+"; Token::tochars[TOKvar] = "var"; Token::tochars[TOKaddass] = "+="; Token::tochars[TOKminass] = "-="; Token::tochars[TOKmulass] = "*="; Token::tochars[TOKdivass] = "/="; Token::tochars[TOKmodass] = "%="; Token::tochars[TOKshlass] = "<<="; Token::tochars[TOKshrass] = ">>="; Token::tochars[TOKushrass] = ">>>="; Token::tochars[TOKandass] = "&="; Token::tochars[TOKorass] = "|="; Token::tochars[TOKcatass] = "~="; Token::tochars[TOKcat] = "~"; Token::tochars[TOKcall] = "call"; Token::tochars[TOKidentity] = "is"; Token::tochars[TOKnotidentity] = "!is"; Token::tochars[TOKorass] = "|="; Token::tochars[TOKidentifier] = "identifier"; Token::tochars[TOKat] = "@"; Token::tochars[TOKpow] = "^^"; Token::tochars[TOKpowass] = "^^="; Token::tochars[TOKgoesto] = "=>"; Token::tochars[TOKpound] = "#"; // For debugging Token::tochars[TOKerror] = "error"; Token::tochars[TOKdotid] = "dotid"; Token::tochars[TOKdottd] = "dottd"; Token::tochars[TOKdotti] = "dotti"; Token::tochars[TOKdotvar] = "dotvar"; Token::tochars[TOKdottype] = "dottype"; Token::tochars[TOKsymoff] = "symoff"; Token::tochars[TOKarraylength] = "arraylength"; Token::tochars[TOKarrayliteral] = "arrayliteral"; Token::tochars[TOKassocarrayliteral] = "assocarrayliteral"; Token::tochars[TOKstructliteral] = "structliteral"; Token::tochars[TOKstring] = "string"; Token::tochars[TOKdsymbol] = "symbol"; Token::tochars[TOKtuple] = "tuple"; Token::tochars[TOKdeclaration] = "declaration"; Token::tochars[TOKon_scope_exit] = "scope(exit)"; Token::tochars[TOKon_scope_success] = "scope(success)"; Token::tochars[TOKon_scope_failure] = "scope(failure)"; Token::tochars[TOKdelegateptr] = "delegateptr"; Token::tochars[TOKvectorarray] = "vectorarray"; }