1 module d.parser.type; 2 3 import d.ast.expression; 4 import d.ast.type; 5 6 import d.ir.expression; 7 8 import d.parser.ambiguous; 9 import d.parser.base; 10 import d.parser.expression; 11 import d.parser.identifier; 12 import source.parserutil; 13 14 AstType parseType(ParseMode mode = ParseMode.Greedy)(ref TokenRange trange) { 15 auto base = trange.parseBasicType(); 16 return trange.parseTypeSuffix!mode(base); 17 } 18 19 auto parseBasicType(ref TokenRange trange) { 20 auto processQualifier(TypeQualifier qualifier)() { 21 trange.popFront(); 22 23 if (trange.front.type == TokenType.OpenParen) { 24 trange.popFront(); 25 auto type = trange.parseType(); 26 trange.match(TokenType.CloseParen); 27 28 return type.qualify(qualifier); 29 } 30 31 return trange.parseType().qualify(qualifier); 32 } 33 34 switch (trange.front.type) with(TokenType) { 35 // Types qualifiers 36 case Const: 37 return processQualifier!(TypeQualifier.Const)(); 38 39 case Immutable: 40 return processQualifier!(TypeQualifier.Immutable)(); 41 42 case Inout: 43 return processQualifier!(TypeQualifier.Mutable)(); 44 45 case Shared: 46 return processQualifier!(TypeQualifier.Shared)(); 47 48 // Identified types 49 case Identifier: 50 return AstType.get(trange.parseIdentifier()); 51 52 case Dot: 53 return AstType.get(trange.parseDotIdentifier()); 54 55 case Typeof: 56 return trange.parseTypeof(); 57 58 case This: 59 Location location = trange.front.location; 60 auto thisExpression = new ThisExpression(location); 61 62 trange.popFront(); 63 trange.match(Dot); 64 65 return AstType.get(trange.parseQualifiedIdentifier( 66 location, 67 thisExpression, 68 )); 69 70 case Super: 71 Location location = trange.front.location; 72 auto superExpression = new SuperExpression(location); 73 74 trange.popFront(); 75 trange.match(TokenType.Dot); 76 77 return AstType.get(trange.parseQualifiedIdentifier( 78 location, 79 superExpression, 80 )); 81 82 // Basic types 83 case Void: 84 trange.popFront(); 85 return AstType.get(BuiltinType.Void); 86 87 case Bool: 88 trange.popFront(); 89 return AstType.get(BuiltinType.Bool); 90 91 case Char: 92 trange.popFront(); 93 return AstType.get(BuiltinType.Char); 94 95 case Wchar: 96 trange.popFront(); 97 return AstType.get(BuiltinType.Wchar); 98 99 case Dchar: 100 trange.popFront(); 101 return AstType.get(BuiltinType.Dchar); 102 103 case Ubyte: 104 trange.popFront(); 105 return AstType.get(BuiltinType.Ubyte); 106 107 case Ushort: 108 trange.popFront(); 109 return AstType.get(BuiltinType.Ushort); 110 111 case Uint: 112 trange.popFront(); 113 return AstType.get(BuiltinType.Uint); 114 115 case Ulong: 116 trange.popFront(); 117 return AstType.get(BuiltinType.Ulong); 118 119 case Ucent: 120 trange.popFront(); 121 return AstType.get(BuiltinType.Ucent); 122 123 case Byte: 124 trange.popFront(); 125 return AstType.get(BuiltinType.Byte); 126 127 case Short: 128 trange.popFront(); 129 return AstType.get(BuiltinType.Short); 130 131 case Int: 132 trange.popFront(); 133 return AstType.get(BuiltinType.Int); 134 135 case Long: 136 trange.popFront(); 137 return AstType.get(BuiltinType.Long); 138 139 case Cent: 140 trange.popFront(); 141 return AstType.get(BuiltinType.Cent); 142 143 case Float: 144 trange.popFront(); 145 return AstType.get(BuiltinType.Float); 146 147 case Double: 148 trange.popFront(); 149 return AstType.get(BuiltinType.Double); 150 151 case Real: 152 trange.popFront(); 153 return AstType.get(BuiltinType.Real); 154 155 default: 156 trange.match(Begin); 157 // TODO: handle. 158 // Erreur, basic type expected. 159 assert(0,"Expected BasicType"); 160 } 161 } 162 163 /** 164 * Parse typeof(...) 165 */ 166 private auto parseTypeof(ref TokenRange trange) { 167 trange.match(TokenType.Typeof); 168 trange.match(TokenType.OpenParen); 169 170 scope(success) trange.match(TokenType.CloseParen); 171 172 if (trange.front.type == TokenType.Return) { 173 trange.popFront(); 174 return AstType.getTypeOfReturn(); 175 } 176 177 return AstType.getTypeOf(trange.parseExpression()); 178 } 179 180 /** 181 * Parse *, [ ... ] and function/delegate types. 182 */ 183 AstType parseTypeSuffix(ParseMode mode)(ref TokenRange trange, AstType type) { 184 while (true) { 185 switch (trange.front.type) with(TokenType) { 186 case Star: 187 trange.popFront(); 188 type = type.getPointer(); 189 break; 190 191 case OpenBracket: 192 type = trange.parseBracket(type); 193 break; 194 195 case Function: { 196 trange.popFront(); 197 198 import d.parser.declaration; 199 import std.algorithm, std.array; 200 bool isVariadic; 201 auto params = trange 202 .parseParameters(isVariadic) 203 .map!(d => d.type) 204 .array(); 205 206 // TODO: parse postfix attributes. 207 // TODO: ref return. 208 type = FunctionAstType( 209 Linkage.D, 210 type.getParamType(ParamKind.Regular), 211 params, 212 isVariadic, 213 ).getType(); 214 215 break; 216 } 217 case Delegate: { 218 trange.popFront(); 219 220 import d.parser.declaration; 221 import std.algorithm, std.array; 222 bool isVariadic; 223 auto params = trange 224 .parseParameters(isVariadic) 225 .map!(d => d.type).array(); 226 227 // TODO: fully typed delegates. 228 auto ctx = AstType.get(BuiltinType.Void) 229 .getPointer() 230 .getParamType(ParamKind.Regular); 231 232 // TODO: parse postfix attributes and storage class. 233 // TODO: ref return. 234 type = FunctionAstType( 235 Linkage.D, 236 type.getParamType(ParamKind.Regular), 237 ctx, 238 params, 239 isVariadic, 240 ).getType(); 241 242 break; 243 } 244 static if (mode == ParseMode.Greedy) { 245 case Dot: 246 trange.popFront(); 247 248 // TODO: Duplicate function and pass location explicitely. 249 type = AstType.get(trange.parseQualifiedIdentifier( 250 trange.front.location, 251 type, 252 )); 253 break; 254 } 255 256 default: 257 return type; 258 } 259 } 260 } 261 262 private: 263 AstType parseBracket(ref TokenRange trange, AstType type) { 264 trange.match(TokenType.OpenBracket); 265 if (trange.front.type == TokenType.CloseBracket) { 266 trange.popFront(); 267 return type.getSlice(); 268 } 269 270 return trange.parseAmbiguous!((parsed) { 271 trange.match(TokenType.CloseBracket); 272 273 alias T = typeof(parsed); 274 static if (is(T : AstType)) { 275 return type.getMap(parsed); 276 } else static if (is(T : AstExpression)) { 277 return type.getArray(parsed); 278 } else { 279 return type.getBracket(parsed); 280 } 281 })(); 282 }