1 /** 2 * Compiler implementation of the 3 * $(LINK2 http://www.dlang.org, D programming language). 4 * 5 * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved 6 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 7 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 8 * Source: $(DMDSRC _identifier.d) 9 */ 10 11 module ddmd.identifier; 12 13 import core.stdc.ctype; 14 import core.stdc.stdio; 15 import core.stdc..string; 16 import ddmd.globals; 17 import ddmd.id; 18 import ddmd.root.outbuffer; 19 import ddmd.root.rootobject; 20 import ddmd.root.stringtable; 21 import ddmd.tokens; 22 import ddmd.utf; 23 24 /*********************************************************** 25 */ 26 extern (C++) final class Identifier : RootObject 27 { 28 private: 29 const int value; 30 const char* string; 31 const size_t len; 32 33 public: 34 35 extern (D) this(const(char)* string, size_t length, int value) 36 { 37 //printf("Identifier('%s', %d)\n", string, value); 38 this.string = string; 39 this.value = value; 40 this.len = length; 41 } 42 43 extern (D) this(const(char)* string) 44 { 45 //printf("Identifier('%s', %d)\n", string, value); 46 this(string, strlen(string), TOKidentifier); 47 } 48 49 static Identifier create(const(char)* string) 50 { 51 return new Identifier(string); 52 } 53 54 override bool equals(RootObject o) const 55 { 56 return this == o || strncmp(string, o.toChars(), len + 1) == 0; 57 } 58 59 override int compare(RootObject o) const 60 { 61 return strncmp(string, o.toChars(), len + 1); 62 } 63 64 override void print() const 65 { 66 fprintf(stderr, "%s", string); 67 } 68 69 override const(char)* toChars() const 70 { 71 return string; 72 } 73 74 extern (D) final const(char)[] toString() const 75 { 76 return string[0 .. len]; 77 } 78 79 final int getValue() const 80 { 81 return value; 82 } 83 84 const(char)* toHChars2() const 85 { 86 const(char)* p = null; 87 if (this == Id.ctor) 88 p = "this"; 89 else if (this == Id.dtor) 90 p = "~this"; 91 else if (this == Id.unitTest) 92 p = "unittest"; 93 else if (this == Id.dollar) 94 p = "$"; 95 else if (this == Id.withSym) 96 p = "with"; 97 else if (this == Id.result) 98 p = "result"; 99 else if (this == Id.returnLabel) 100 p = "return"; 101 else 102 { 103 p = toChars(); 104 if (*p == '_') 105 { 106 if (strncmp(p, "_staticCtor", 11) == 0) 107 p = "static this"; 108 else if (strncmp(p, "_staticDtor", 11) == 0) 109 p = "static ~this"; 110 else if (strncmp(p, "__invariant", 11) == 0) 111 p = "invariant"; 112 } 113 } 114 return p; 115 } 116 117 override int dyncast() const 118 { 119 return DYNCAST_IDENTIFIER; 120 } 121 122 extern (C++) static __gshared StringTable stringtable; 123 124 static Identifier generateId(const(char)* prefix) 125 { 126 static __gshared size_t i; 127 return generateId(prefix, ++i); 128 } 129 130 static Identifier generateId(const(char)* prefix, size_t i) 131 { 132 OutBuffer buf; 133 buf.writestring(prefix); 134 buf.printf("%llu", cast(ulong)i); 135 return idPool(buf.peekSlice()); 136 } 137 138 /******************************************** 139 * Create an identifier in the string table. 140 */ 141 extern (D) static Identifier idPool(const(char)[] s) 142 { 143 return idPool(s.ptr, s.length); 144 } 145 146 static Identifier idPool(const(char)* s, size_t len) 147 { 148 StringValue* sv = stringtable.update(s, len); 149 Identifier id = cast(Identifier)sv.ptrvalue; 150 if (!id) 151 { 152 id = new Identifier(sv.toDchars(), len, TOKidentifier); 153 sv.ptrvalue = cast(char*)id; 154 } 155 return id; 156 } 157 158 extern (D) static Identifier idPool(const(char)* s, size_t len, int value) 159 { 160 auto sv = stringtable.insert(s, len, null); 161 assert(sv); 162 auto id = new Identifier(sv.toDchars(), len, value); 163 sv.ptrvalue = cast(char*)id; 164 return id; 165 } 166 167 /********************************** 168 * Determine if string is a valid Identifier. 169 * Returns: 170 * 0 invalid 171 */ 172 static bool isValidIdentifier(const(char)* p) 173 { 174 size_t len; 175 size_t idx; 176 if (!p || !*p) 177 goto Linvalid; 178 if (*p >= '0' && *p <= '9') // beware of isdigit() on signed chars 179 goto Linvalid; 180 len = strlen(p); 181 idx = 0; 182 while (p[idx]) 183 { 184 dchar dc; 185 const q = utf_decodeChar(p, len, idx, dc); 186 if (q) 187 goto Linvalid; 188 if (!((dc >= 0x80 && isUniAlpha(dc)) || isalnum(dc) || dc == '_')) 189 goto Linvalid; 190 } 191 return true; 192 Linvalid: 193 return false; 194 } 195 196 static Identifier lookup(const(char)* s, size_t len) 197 { 198 auto sv = stringtable.lookup(s, len); 199 if (!sv) 200 return null; 201 return cast(Identifier)sv.ptrvalue; 202 } 203 204 static void initTable() 205 { 206 stringtable._init(28000); 207 } 208 }