1 /// Author: Aziz Köksal
2 /// License: GPL3
3 /// $(Maturity high)
4 module dil.parser.ImportParser;
5
6 import dil.parser.Parser;
7 import dil.lexer.Tables;
8 import dil.ast.Node,
9 dil.ast.Declarations,
10 dil.ast.Statements;
11 import dil.SourceText,
12 dil.Enums;
13 import common;
14
15 /// A light-weight parser which looks only for import statements
16 /// in the source text.
17 class ImportParser : Parser
18 {
19 this(SourceText srcText, LexerTables tables)
20 {
21 super(srcText, tables);
22 }
23
24 override CompoundDecl start()
25 {
26 auto decls = new CompoundDecl;
27 super.init();
28 if (token.kind == T!"module")
29 decls ~= parseModuleDecl();
30 while (token.kind != T!"EOF")
31 parseDeclarationDefinition(Protection.None);
32 return decls;
33 }
34
35 void parseDeclarationDefinitionsBlock(Protection prot)
36 {
37 skip(T!"{");
38 while (token.kind != T!"}" && token.kind != T!"EOF")
39 parseDeclarationDefinition(prot);
40 skip(T!"}");
41 }
42
43 void parseDeclarationsBlock(Protection prot)
44 {
45 switch (token.kind)
46 {
47 case T!"{":
48 parseDeclarationDefinitionsBlock(prot);
49 break;
50 case T!":":
51 nT();
52 while (token.kind != T!"}" && token.kind != T!"EOF")
53 parseDeclarationDefinition(prot);
54 break;
55 default:
56 parseDeclarationDefinition(prot);
57 }
58 }
59
60 bool skipToClosing(TOK opening, TOK closing)
61 {
62 alias next = token;
63 uint level = 1;
64 while (1)
65 {
66 lexer.peek(next);
67 if (next.kind == opening)
68 ++level;
69 else if (next.kind == closing && --level == 0)
70 return true;
71 else if (next.kind == T!"EOF")
72 break;
73 }
74 return false;
75 }
76
77 void skipToTokenAfterClosingParen()
78 {
79 skipToClosing(T!"(", T!")");
80 nT();
81 }
82
83 void skipToTokenAfterClosingBrace()
84 {
85 skipToClosing(T!"{", T!"}");
86 nT();
87 }
88
89 void skip(TOK tok)
90 {
91 token.kind == tok && nT();
92 }
93
94 void parseProtectionAttribute()
95 {
96 Protection prot;
97 switch (token.kind)
98 {
99 case T!"private":
100 prot = Protection.Private; break;
101 case T!"package":
102 prot = Protection.Package; break;
103 case T!"protected":
104 prot = Protection.Protected; break;
105 case T!"public":
106 prot = Protection.Public; break;
107 case T!"export":
108 prot = Protection.Export; break;
109 default:
110 assert(0);
111 }
112 nT();
113 parseDeclarationsBlock(prot);
114 }
115
116 void parseDeclarationDefinition(Protection prot)
117 {
118 switch (token.kind)
119 {
120 case T!"align":
121 nT();
122 if (token.kind == T!"(")
123 nT(), nT(), nT(); // ( Integer )
124 parseDeclarationsBlock(prot);
125 break;
126 case T!"pragma":
127 nT();
128 skipToTokenAfterClosingParen();
129 parseDeclarationsBlock(prot);
130 break;
131 case T!"export",
132 T!"private",
133 T!"package",
134 T!"protected",
135 T!"public":
136 parseProtectionAttribute();
137 break;
138 // Storage classes
139 case T!"extern":
140 nT();
141 token.kind == T!"(" && skipToTokenAfterClosingParen();
142 parseDeclarationsBlock(prot);
143 break;
144 case T!"const":
145 version(D2)
146 {
147 if (peekNext() == T!"(")
148 goto case_Declaration;
149 }
150 goto case;
151 case T!"override",
152 T!"deprecated",
153 T!"abstract",
154 T!"synchronized",
155 // T!"static",
156 T!"final",
157 T!"auto",
158 T!"scope":
159 case_StaticAttribute:
160 case_InvariantAttribute:
161 nT();
162 parseDeclarationsBlock(prot);
163 break;
164 // End of storage classes.
165 case T!"alias", T!"typedef":
166 nT();
167 goto case_Declaration;
168 case T!"static":
169 switch (peekNext())
170 {
171 case T!"import":
172 goto case_Import;
173 case T!"this":
174 nT(), nT(); // static this
175 skipToTokenAfterClosingParen();
176 skipFunctionBody();
177 break;
178 case T!"~":
179 nT(), nT(), nT(), nT(), nT(); // static ~ this ( )
180 skipFunctionBody();
181 break;
182 case T!"if":
183 nT(), nT();
184 skipToTokenAfterClosingParen();
185 parseDeclarationsBlock(prot);
186 if (token.kind == T!"else")
187 nT(), parseDeclarationsBlock(prot);
188 break;
189 case T!"assert":
190 nT(), nT(); // static assert
191 skipToTokenAfterClosingParen();
192 skip(T!";");
193 break;
194 default:
195 goto case_StaticAttribute;
196 }
197 break;
198 case T!"import":
199 case_Import:
200 auto decl = parseImportDecl();
201 decl.setProtection(prot); // Set the protection attribute.
202 imports ~= decl.to!(ImportDecl);
203 break;
204 case T!"enum":
205 nT();
206 token.kind == T!"Identifier" && nT();
207 if (token.kind == T!":")
208 {
209 nT();
210 while (token.kind != T!"{" && token.kind != T!"EOF")
211 nT();
212 }
213 if (token.kind == T!";")
214 nT();
215 else
216 skipToTokenAfterClosingBrace();
217 break;
218 case T!"class", T!"interface":
219 nT(), skip(T!"Identifier"); // class Identifier
220 token.kind == T!"(" && skipToTokenAfterClosingParen(); // Skip template params.
221 if (token.kind == T!":")
222 { // BaseClasses
223 nT();
224 while (token.kind != T!"{" && token.kind != T!"EOF")
225 if (token.kind == T!"(") // Skip ( tokens... )
226 skipToTokenAfterClosingParen();
227 else
228 nT();
229 }
230 if (token.kind == T!";")
231 nT();
232 else
233 parseDeclarationDefinitionsBlock(Protection.None);
234 break;
235 case T!"struct", T!"union":
236 nT(); skip(T!"Identifier");
237 token.kind == T!"(" && skipToTokenAfterClosingParen();
238 if (token.kind == T!";")
239 nT();
240 else
241 parseDeclarationDefinitionsBlock(Protection.None);
242 break;
243 case T!"~":
244 nT();
245 goto case;
246 case T!"this":
247 nT(); nT(); nT(); // this ( )
248 skipFunctionBody();
249 break;
250 case T!"invariant":
251 version(D2)
252 {
253 auto next = peekAfter(token);
254 if (next.kind == T!"(")
255 {
256 if (peekAfter(next).kind != T!")")
257 goto case_Declaration;
258 }
259 else
260 goto case_InvariantAttribute;
261 }
262 nT();
263 token.kind == T!"(" && skipToTokenAfterClosingParen();
264 skipFunctionBody();
265 break;
266 case T!"unittest":
267 nT();
268 skipFunctionBody();
269 break;
270 case T!"debug":
271 nT();
272 if (token.kind == T!"=")
273 {
274 nT(), nT(), nT(); // = Condition ;
275 break;
276 }
277 if (token.kind == T!"(")
278 nT(), nT(), nT(); // ( Condition )
279 parseDeclarationsBlock(prot);
280 if (token.kind == T!"else")
281 nT(), parseDeclarationsBlock(prot);
282 break;
283 case T!"version":
284 nT();
285 if (token.kind == T!"=")
286 {
287 nT(), nT(), nT(); // = Condition ;
288 break;
289 }
290 nT(), nT(), nT(); // ( Condition )
291 parseDeclarationsBlock(prot);
292 if (token.kind == T!"else")
293 nT(), parseDeclarationsBlock(prot);
294 break;
295 case T!"template":
296 nT();
297 skip(T!"Identifier");
298 skipToTokenAfterClosingParen();
299 parseDeclarationDefinitionsBlock(Protection.None);
300 break;
301 case T!"new":
302 nT();
303 skipToTokenAfterClosingParen();
304 skipFunctionBody();
305 break;
306 case T!"delete":
307 nT();
308 skipToTokenAfterClosingParen();
309 skipFunctionBody();
310 break;
311 case T!"mixin":
312 while (token.kind != T!";" && token.kind != T!"EOF")
313 if (token.kind == T!"(")
314 skipToTokenAfterClosingParen();
315 else
316 nT();
317 skip(T!";");
318 break;
319 case T!";":
320 nT();
321 break;
322 // Declaration
323 case T!"Identifier", T!".", T!"typeof":
324 case_Declaration:
325 while (token.kind != T!";" && token.kind != T!"EOF")
326 if (token.kind == T!"(")
327 skipToTokenAfterClosingParen();
328 else if (token.kind == T!"{")
329 skipToTokenAfterClosingBrace();
330 else
331 nT();
332 skip(T!";");
333 break;
334 default:
335 if (token.isIntegralType)
336 goto case_Declaration;
337 nT();
338 }
339 }
340
341 void skipFunctionBody()
342 {
343 while (1)
344 {
345 switch (token.kind)
346 {
347 case T!"{":
348 skipToTokenAfterClosingBrace();
349 break;
350 case T!";":
351 nT();
352 break;
353 case T!"in":
354 nT();
355 skipToTokenAfterClosingBrace();
356 continue;
357 case T!"out":
358 nT();
359 if (token.kind == T!"(")
360 nT(), nT(), nT(); // ( Identifier )
361 skipToTokenAfterClosingBrace();
362 continue;
363 case T!"body":
364 nT();
365 goto case T!"{";
366 default:
367 }
368 break; // Exit loop.
369 }
370 }
371 }