1 2 // Copyright Tim Schendekehl 2023. 3 // Distributed under the Boost Software License, Version 1.0. 4 // (See accompanying file LICENSE_1_0.txt or copy at 5 // https://www.boost.org/LICENSE_1_0.txt) 6 7 module dparsergen.generator.ids; 8 import std.algorithm; 9 import std.bitmanip; 10 import std.conv; 11 import std.range; 12 13 struct IDMap(I, T, string idMember = "name") 14 { 15 T[] vals; 16 alias IdType = typeof(__traits(getMember, T, idMember)); 17 typeof(I.init.id)[IdType] ids; 18 19 I id(IdType val) 20 { 21 if (val in ids) 22 return I(ids[val]); 23 typeof(I.init.id) newID = vals.length.to!(typeof(I.init.id)); 24 T x; 25 __traits(getMember, x, idMember) = val; 26 vals ~= x; 27 ids[val] = newID; 28 return I(newID); 29 } 30 31 I getID(IdType val) const 32 { 33 assert(val in ids); 34 return I(ids[val]); 35 } 36 37 const(T) opIndex(I i) const 38 { 39 return vals[i.id]; 40 } 41 42 ref T opIndex(I i) 43 { 44 return vals[i.id]; 45 } 46 47 const(T) get(IdType val) const 48 { 49 return vals[getID(val).id]; 50 } 51 52 auto allIDs() const 53 { 54 return iota(0, vals.length).map!(i => I(i.to!(typeof(I.init.id)))); 55 } 56 57 IDMap dup() const 58 { 59 IDMap r; 60 r.vals = vals.dup; 61 foreach (k, v; ids) 62 r.ids[k] = v; 63 return r; 64 } 65 } 66 67 struct BitSet(I) 68 { 69 BitArray arr; 70 this(size_t l) 71 { 72 assert(l < typeof(I.init.id).max); 73 arr.length = l; 74 } 75 76 private this(BitArray arr) 77 { 78 assert(arr.length < typeof(I.init.id).max); 79 this.arr = arr; 80 } 81 82 bool opIndex(I i) const 83 { 84 assert(i.id < typeof(I.init.id).max); 85 if (i.id >= arr.length) 86 return false; 87 return arr[i.id]; 88 } 89 90 void opIndexAssign(bool value, I i) 91 { 92 assert(i.id < typeof(I.init.id).max); 93 if (i.id >= arr.length) 94 arr.length = i.id + 1; 95 arr[i.id] = value; 96 } 97 98 void opOpAssign(string op)(const BitSet!I rhs) 99 { 100 static if (op == "|") 101 { 102 if (arr.length == 0) 103 { 104 arr = rhs.arr.dup; 105 return; 106 } 107 if (rhs.arr.length == 0) 108 { 109 return; 110 } 111 } 112 mixin("arr " ~ op ~ "= rhs.arr;"); 113 } 114 115 BitSet!I opBinary(string op)(const BitSet!I rhs) const 116 { 117 mixin("return BitSet!I(arr " ~ op ~ " rhs.arr);"); 118 } 119 120 BitSet!I dup() const 121 { 122 BitSet!I r; 123 r.arr = arr.dup; 124 return r; 125 } 126 127 auto bitsSet() const 128 { 129 return arr.bitsSet.map!(x => I(x.to!(typeof(I.init.id)))); 130 } 131 132 void length(size_t l) 133 { 134 arr.length = l; 135 } 136 137 size_t length() const 138 { 139 return arr.length; 140 } 141 142 bool addOnce(I)(BitSet!I src) 143 { 144 bool r = false; 145 foreach (s; src.bitsSet) 146 { 147 if (!this[s]) 148 { 149 this[s] = true; 150 r = true; 151 } 152 } 153 return r; 154 } 155 156 bool addOnce(I i) 157 { 158 assert(i.id < typeof(I.init.id).max); 159 bool r = false; 160 if (!this[i]) 161 { 162 this[i] = true; 163 r = true; 164 } 165 return r; 166 } 167 }