1 /// Author: Aziz Köksal 2 /// License: GPL3 3 /// $(Maturity high) 4 module dil.lexer.Tables; 5 6 import dil.lexer.Token, 7 dil.lexer.IdTable; 8 import dil.Float; 9 import dil.String; 10 import common; 11 12 /// Tables used by the $(MODLINK2 dil.lexer.Lexer, Lexer). 13 /// 14 /// The purpose is to keep common Token values 15 /// stored in a single place, with the added benefit of saving memory. 16 /// Most importantly, it provides access to unique Identifiers. 17 /// TODO: Inserting and reading needs to be thread-safe. 18 class LexerTables 19 { 20 alias StringValue = Token.StringValue; 21 alias IntegerValue = Token.IntegerValue; 22 alias NewlineValue = Token.NewlineValue; 23 24 IdTable idents; /// Maps id strings to unique Identifier objects. 25 cbinstr[hash_t] strings; /// Maps hashes to binary string values. 26 StringValue*[hash_t] strvals; /// Maps string+postfix to StringValues. 27 Float[hash_t] floats; /// Maps float strings to Float values. 28 IntegerValue*[ulong] ulongs; /// Maps a ulong to an IntegerValue. 29 /// A list of newline values. 30 /// Only instances where the 'hlinfo' member is null are kept here. 31 NewlineValue*[] newlines; 32 33 /// Contructs a LexerTables object. 34 this() 35 { 36 idents = new IdTable(); 37 } 38 39 /// Looks up a StringValue in the table. 40 /// Params: 41 /// str = The string to be looked up. 42 /// pf = The postfix character. 43 /// dup = True if str should be copied. 44 /// Returns: A stored or new StringValue. 45 StringValue* lookupString(cstring str, char postfix, bool dup = true) 46 { 47 auto hash = hashOf(str); 48 if (auto psv = (hash + postfix) in strvals) 49 return *psv; 50 // Insert a new StringValue into the table. 51 auto sv = new StringValue; 52 sv.str = lookupString(hash, str, dup); 53 sv.pf = postfix; 54 strvals[hash + postfix] = sv; 55 return sv; 56 } 57 58 /// Looks up a string in the table. 59 /// Params: 60 /// hash = The hash of str. 61 /// str = The string to be looked up. 62 /// dup = True if str should be copied. 63 /// Returns: A stored or new string. 64 cbinstr lookupString(hash_t hash, cstring str, bool dup = true) 65 { 66 assert(hash == hashOf(str)); 67 auto bstr = cast(cbinstr)str; 68 if (auto pstr = hash in strings) 69 bstr = *pstr; 70 else // Insert a new string into the table. 71 bstr = strings[hash] = dup ? bstr.dup : bstr; 72 return bstr; 73 } 74 75 /// Looks up an identifier. 76 Identifier* lookupIdentifier(cstring str) 77 { 78 return idents.lookup(str); 79 } 80 81 /// Looks up a ulong in the table. 82 /// Params: 83 /// num = The number value. 84 IntegerValue* lookupUlong(ulong num) 85 { 86 if (auto pintval = num in ulongs) 87 return *pintval; 88 // Insert a new IntegerValue into the table. 89 auto iv = new IntegerValue; 90 iv.ulong_ = num; 91 ulongs[num] = iv; 92 return iv; 93 } 94 95 /// Looks up a newline value that can be shared among Lexer instances. 96 NewlineValue* lookupNewline(uint_t lineNum) 97 { 98 assert(lineNum != 0); 99 auto i = lineNum - 1; 100 if (i >= newlines.length) 101 newlines.length = lineNum; 102 auto nl = newlines[i]; 103 if (!nl) 104 { // Insert a new NewlineValue. 105 newlines[i] = nl = new NewlineValue; 106 nl.lineNum = lineNum; 107 } 108 return nl; 109 } 110 }