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