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 }