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 }