root/trunk/dparse.d

Revision 14, 85.6 kB (checked in by Jaymz031602, 4 years ago)

--

Line 
1 // dparse - D module parser
2 // (C) Copyright 2004-2005 James Dunne
3
4 // Please feel free to distribute this module in any form you like.  I only ask that you
5 // give credit where credit is due.  You may make modifications to this module.  If you do
6 // so, you may provide your modifications publicly, but you are not required to.
7
8 // A minimal parser that skips over actual code.  Only concerned with parsing for declarations.
9
10 module  dparse;
11
12 import  std.stream;
13 import  std.string;
14 import  std.ctype;
15
16 import  dlexer;
17 import  dtypes;
18
19 const int TRUE = 1;
20 const int FALSE = 0;
21
22 class DParse : DLexer {
23     private:
24         // Check for a certain token:
25         void check(uint value) {
26             if (token.value != value)
27                 error(format("found '%s' when expecting '%s'", token.toString(), toktostr[value]));
28             nextToken();
29         }
30
31         void check(uint value, char[] string) {
32             if (token.value != value)
33                 error(format("found '%s' when expecting '%s' following '%s'", token.toString(), toktostr[value], string));
34             nextToken();
35         }
36
37         uint        linkage;
38
39     public:
40         ArrayT!(Identifier)     moduleident;
41
42         // Load up the module source code:
43         this(char[] filename, char[] src) {
44             // Load up the source for the lexer:
45             super(filename, src);
46             linkage = LINKd;
47             nextToken();            // start the scanner
48         }
49
50         Array parseModule() {
51             Array   decldefs;
52
53             // ModuleDeclation leads off
54             if (token.value == TOKmodule) {
55                 nextToken();
56                 if (token.value != TOKidentifier) {
57                     error("Identifier expected following module");
58                     goto Lerr;
59                 } else {
60                     ArrayT!(Identifier) a = null;
61                     Identifier id;
62
63                     id = token.ident;
64                     while (nextToken() == TOKdot) {
65                         if (!a)
66                             a = new ArrayT!(Identifier);
67                         a.push(id);
68                         nextToken();
69                         if (token.value != TOKidentifier) {
70                             error("Identifier expected following package");
71                             goto Lerr;
72                         }
73                         id = token.ident;
74                     }
75
76                     moduleident = a;
77
78                     if (token.value != TOKsemicolon)
79                         error(format("';' expected following module declaration instead of %s", token.toString()));
80                     nextToken();
81                 }
82             }
83
84             decldefs = parseDeclDefs(0);
85             if (token.value != TOKeof) {
86                 error("unrecognized declaration");
87                 goto Lerr;
88             }
89             return decldefs;
90
91           Lerr:
92             while (token.value != TOKsemicolon && token.value != TOKeof)
93                 nextToken();
94             nextToken();
95             return new Array;
96         }
97
98         Array parseDeclDefs(int once) {
99             Dsymbol s;
100             Array decldefs;
101             Array a;
102             uint prot;
103             uint stc;
104
105             //printf("parseDeclDefs()\n");
106             decldefs = new Array;
107             do {
108                 switch (token.value) {
109                     case TOKenum:
110                         s = parseEnum();
111                         break;
112
113                     case TOKstruct:
114                         s = parseAggregate();
115                         break;
116
117                     case TOKunion:
118                         s = parseAggregate();
119                         break;
120
121                     case TOKclass:
122                         s = parseAggregate();
123                         break;
124
125                     case TOKinterface:
126                         s = parseAggregate();
127                         break;
128
129                     case TOKimport:
130                         s = parseImport(decldefs);
131                         break;
132
133                     case TOKtemplate:
134                         s = cast(Dsymbol) parseTemplateDeclaration();
135                         break;
136
137                     case TOKmixin:
138                         s = parseMixin();
139                         break;
140
141                     case TOKinstance:   // Deprecated
142                         if (isDeclaration(token, 2, TOKreserved, null)) {
143                             //printf("it's a declaration\n");
144                             goto Ldeclaration;
145                         } else {
146                             // instance foo(bar) ident;
147
148                             TemplateInstance ti;
149
150                             //printf("it's an alias\n");
151                             ti = parseTemplateInstance();
152                             s = cast(Dsymbol) ti;
153                             if (ti) {
154                                 if (token.value == TOKidentifier) {
155                                     s = new AliasDeclaration(loc, token.ident, ti);
156
157                                     nextToken();
158                                 }
159                             }
160                             if (token.value != TOKsemicolon)
161                                 error("';' expected after template instance");
162                         }
163                         break;
164
165                     case TOKwchar: case TOKdchar:
166                     case TOKbit: case TOKchar:
167                     case TOKint8: case TOKuns8:
168                     case TOKint16: case TOKuns16:
169                     case TOKint32: case TOKuns32:
170                     case TOKint64: case TOKuns64:
171                     case TOKfloat32: case TOKfloat64: case TOKfloat80:
172                     case TOKimaginary32: case TOKimaginary64: case TOKimaginary80:
173                     case TOKcomplex32: case TOKcomplex64: case TOKcomplex80:
174                     case TOKvoid:
175
176                     case TOKalias:
177                     case TOKtypedef:
178                     case TOKidentifier:
179                     case TOKtypeof:
180                     case TOKdot:
181                       Ldeclaration:
182                         a = parseDeclaration();
183                         decldefs.append(a);
184                         continue;
185
186                     case TOKthis:
187                         s = parseCtor();
188                         break;
189
190                     case TOKtilde:
191                         s = parseDtor();
192                         break;
193
194                     case TOKinvariant:
195                         parseInvariant();
196                         s = null;
197                         break;
198
199                     case TOKunittest:
200                         parseUnitTest();
201                         s = null;
202                         break;
203
204                     case TOKnew:
205                         s = parseNew();
206                         break;
207
208                     case TOKdelete:
209                         s = parseDelete();
210                         break;
211
212                     case TOKeof:
213                     case TOKrcurly:
214                         return decldefs;
215
216                     case TOKstatic:
217                         nextToken();
218                         if (token.value == TOKthis)
219                             s = parseStaticCtor();
220                         else if (token.value == TOKtilde)
221                             s = parseStaticDtor();
222                         else if (token.value == TOKassert)
223                             s = parseStaticAssert();
224                         else {
225                             stc = STCstatic;
226                             goto Lstc2;
227                         }
228                         break;
229
230                     case TOKconst:
231                         stc = STCconst;
232                         goto Lstc;
233                     case TOKfinal:
234                         stc = STCfinal;
235                         goto Lstc;
236                     case TOKauto:
237                         stc = STCauto;
238                         goto Lstc;
239                     case TOKoverride:
240                         stc = STCoverride;
241                         goto Lstc;
242                     case TOKabstract:
243                         stc = STCabstract;
244                         goto Lstc;
245                     case TOKsynchronized:
246                         stc = STCsynchronized;
247                         goto Lstc;
248                     case TOKdeprecated:
249                         stc = STCdeprecated;
250                         goto Lstc;
251
252                       Lstc:
253                         nextToken();
254                       Lstc2:
255                         switch (token.value) {
256                             case TOKconst:
257                                 stc |= STCconst;
258                                 goto Lstc;
259                             case TOKfinal:
260                                 stc |= STCfinal;
261                                 goto Lstc;
262                             case TOKauto:
263                                 stc |= STCauto;
264                                 goto Lstc;
265                             case TOKoverride:
266                                 stc |= STCoverride;
267                                 goto Lstc;
268                             case TOKabstract:
269                                 stc |= STCabstract;
270                                 goto Lstc;
271                             case TOKsynchronized:
272                                 stc |= STCsynchronized;
273                                 goto Lstc;
274                             case TOKdeprecated:
275                                 stc |= STCdeprecated;
276                                 goto Lstc;
277                         }
278                         a = parseBlock();
279                         s = new StorageClassDeclaration(stc, a);
280                         break;
281
282                     case TOKprivate:
283                         prot = PROTprivate;
284                         goto Lprot;
285                     case TOKpackage:
286                         prot = PROTpackage;
287                         goto Lprot;
288                     case TOKprotected:
289                         prot = PROTprotected;
290                         goto Lprot;
291                     case TOKpublic:
292                         prot = PROTpublic;
293                         goto Lprot;
294                     case TOKexport:
295                         prot = PROTexport;
296                         goto Lprot;
297
298                       Lprot:
299                         nextToken();
300                         a = parseBlock();
301                         s = new ProtDeclaration(prot, a);
302                         break;
303
304                     case TOKalign:
305                         {
306                             uint n;
307
308                             s = null;
309                             nextToken();
310                             if (token.value == TOKlparen) {
311                                 nextToken();
312                                 if (token.value == TOKint32v)
313                                     n = cast(uint)token.uns64value;
314                                 else {
315                                     error("integer expected, not %s", token.toString());
316                                     n = 1;
317                                 }
318                                 nextToken();
319                                 check(TOKrparen);
320                             } else
321                                 n = 4;  //global.structalign;   // default
322
323                             a = parseBlock();
324                             s = new AlignDeclaration(n, a);
325                             break;
326                         }
327
328                     case TOKpragma:
329                         {
330                             Identifier ident;
331                             Array args = null;
332
333                             nextToken();
334                             check(TOKlparen);
335                             if (token.value != TOKidentifier) {
336                                 error("pragma(identifier expected");
337                                 goto Lerror;
338                             }
339                             ident = token.ident;
340                             nextToken();
341                             if (token.value == TOKcomma)
342                                 args = parseArguments();    // pragma(identifier, args...)
343                             else
344                                 check(TOKrparen);   // pragma(identifier)
345
346                             if (token.value == TOKsemicolon)
347                                 a = null;
348                             else
349                                 a = parseBlock();
350                             /+s = new PragmaDeclaration(ident, args, a);+/
351                             s = null;
352                             break;
353                         }
354
355                     case TOKextern:
356                         {
357                             uint link = LINKdefault;
358                             uint linksave;
359
360                             s = null;
361                             nextToken();
362                             if (token.value == TOKlparen) {
363                                 nextToken();
364                                 if (token.value == TOKidentifier) {
365                                     Identifier id = token.ident;
366
367                                     nextToken();
368                                     if (id == Id.Windows)
369                                         link = LINKwindows;
370                                     else if (id == Id.Pascal)
371                                         link = LINKpascal;
372                                     else if (id == Id.D)
373                                         link = LINKd;
374                                     else if (id == Id.C) {
375                                         link = LINKc;
376                                         if (token.value == TOKplusplus) {
377                                             link = LINKcpp;
378                                             nextToken();
379                                         }
380                                     } else {
381                                         error("valid linkage identifiers are D, C, C++, Pascal, Windows");
382                                         link = LINKd;
383                                         break;
384                                     }
385                                 } else {
386                                     link = LINKd;   // default
387                                 }
388                                 check(TOKrparen);
389                             } else {
390                                 stc = STCextern;
391                                 goto Lstc2;
392                             }
393                             linksave = linkage;
394                             linkage = link;
395                             a = parseBlock();
396                             linkage = linksave;
397                             s = new LinkDeclaration(link, a);
398                             break;
399                         }
400
401                     case TOKdebug:
402                         {
403                             DebugCondition condition;
404                             Array aelse;
405
406                             nextToken();
407                             if (token.value == TOKassign) {
408                                 nextToken();
409                                 if (token.value == TOKidentifier)
410                                     s = new DebugSymbol(token.ident);
411                                 else if (token.value == TOKint32v)
412                                     s = new DebugSymbol(cast(uint)token.uns64value);
413                                 else {
414                                     error("identifier or integer expected, not %s", token.toString());
415                                     s = null;
416                                 }
417                                 nextToken();
418                                 if (token.value != TOKsemicolon)
419                                     error("semicolon expected");
420                                 nextToken();
421                                 break;
422                             }
423
424                             if (token.value == TOKlparen) {
425                                 nextToken();
426                                 condition = parseDebugCondition();
427                                 check(TOKrparen);
428                             } else
429                                 condition = new DebugCondition(1, null);
430                             a = parseBlock();
431                             aelse = null;
432                             if (token.value == TOKelse) {
433                                 nextToken();
434                                 aelse = parseBlock();
435                             }
436                             s = new DebugDeclaration(condition, a, aelse);
437                             break;
438                         }
439
440                     case TOKversion:
441                         {
442                             VersionCondition condition;
443                             Array aelse;
444
445                             nextToken();
446                             if (token.value == TOKassign) {
447                                 nextToken();
448                                 if (token.value == TOKidentifier)
449                                     s = new VersionSymbol(token.ident);
450                                 else if (token.value == TOKint32v)
451                                     s = new VersionSymbol(cast(uint)token.uns64value);
452                                 else {
453                                     error("identifier or integer expected, not %s", token.toString());
454                                     s = null;
455                                 }
456                                 nextToken();
457                                 if (token.value != TOKsemicolon)
458                                     error("semicolon expected");
459                                 nextToken();
460                                 break;
461                             }
462
463                             if (token.value == TOKlparen) {
464                                 nextToken();
465                                 condition = parseVersionCondition();
466                                 check(TOKrparen);
467                             } else {
468                                 error("(condition) expected following version");
469                                 condition = null;
470                             }
471                             a = parseBlock();
472                             aelse = null;
473                             if (token.value == TOKelse) {
474                                 nextToken();
475                                 aelse = parseBlock();
476                             }
477                             s = new VersionDeclaration(condition, a, aelse);
478                             break;
479                         }
480
481                     case TOKsemicolon:  // empty declaration
482                         nextToken();
483                         continue;
484
485                     default:
486                         error("Declaration expected, not '%s'\n", token.toString());
487                       Lerror:
488                         while (token.value != TOKsemicolon && token.value != TOKeof)
489                             nextToken();
490                         nextToken();
491                         s = null;
492                         continue;
493                 }
494                 if (s)
495                     decldefs.push(s);
496             } while (!once);
497             return decldefs;
498         }
499
500         /********************************************
501          * Parse declarations after an align, protection, or extern decl.
502          */
503
504         Array parseBlock() {
505             Array a = null;
506             Dsymbol s;
507
508             //printf("parseBlock()\n");
509             switch (token.value) {
510                 case TOKsemicolon:
511                     error("declaration expected following attribute, not ';'");
512                     nextToken();
513                     break;
514
515                 case TOKlcurly:
516                     nextToken();
517                     a = parseDeclDefs(0);
518                     if (token.value != TOKrcurly) { /* { */
519                         error("matching '}' expected, not %s", token.toString());
520                     } else
521                         nextToken();
522                     break;
523
524                 case TOKcolon:
525                     nextToken();
526                     a = null;
527 /+      #else
528                     a = parseDeclDefs(0);   // grab declarations up to closing curly bracket
529         #endif+/
530                     break;
531
532                 default:
533                     a = parseDeclDefs(1);
534                     break;
535             }
536             return a;
537         }
538
539         /**********************************
540          * Parse a static assertion.
541          */
542
543         StaticAssert parseStaticAssert() {
544             Loc loc = this.loc;
545             Expression exp;
546
547             //printf("parseStaticAssert()\n");
548             nextToken();
549             check(TOKlparen);
550             exp = parseExpression