root/trunk/dsymextract.d

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

--

Line 
1 // Demangles a mangled D identifier and produces the result in
2 // inherited container classes such as DType and DSymbol.
3
4 // Ideally used to extract code-completion info from a compiled D library
5 // using the library's symbol table.
6
7 // by James Dunne
8 // Jan. 6 2005
9
10 module  dsymextract;
11
12 import  std.ctype;
13 import  std.string;
14
15 //version = destructors;                    // include destructor code (for explicit memory management)
16 version = error_extrachars;             // check for extra characters after end of mangled string
17 version(linux) {
18     version = ansi_color;               // use ANSI color strings for cheap syntax highlighting
19 }
20 //debug = destruct;                     // dump destructor calls
21
22 // A D symbol (inherited usually)
23 class DSymbol {
24     public:
25         char[]  name;       // name for the symbol
26         DType   type;       // type of the symbol
27
28         this() {
29            
30         }
31
32         char[] toANSIString() {
33             return "\033[0;37m" ~ name;
34         }
35
36         char[] toString() {
37             return name;
38         }
39 }
40
41 // A D function definition
42 class DFunction : DSymbol {
43     public:
44         //char[]    name;       // name for the function
45         //DType     type;       // return type for the function
46         DType[]     params;     // parameters for the function
47
48         this() {
49         }
50
51         version (destructors) ~this() {
52             foreach (inout DType t; params)
53                 if (cast(DReservedType)t is null)
54                     delete t;
55         }
56
57         char[] toANSIString() {
58             char[] s;
59             bool first = true;
60
61             if (type is null) return name;
62
63             s = type.toANSIString() ~ " \033[0;37m" ~ name ~ "\033[0;36m" ~ "(";
64             foreach (DType dt; params) {
65                 if (!first) s ~= "\033[0;36m" ~ ", ";
66                 s ~= dt.toANSIString();
67                 first = false;
68             }
69             s ~= "\033[0;36m)\033[37m";
70
71             return s;
72         }
73
74         char[] toString() {
75             char[] s;
76             bool first = true;
77
78             if (type is null) return name;
79
80             s = type.toString() ~ " " ~ name ~ "(";
81             foreach (DType dt; params) {
82                 if (!first) s ~= ", ";
83                 s ~= dt.toString();
84                 first = false;
85             }
86             s ~= ")";
87
88             return s;
89         }
90 }
91
92 // A D class definition:
93 class DClass : DSymbol {
94     public:
95         // Doesn't have much.
96         // Should expand to contain functions and other symbols.
97
98         this(char[] name) {
99             this.name = name;
100         }
101
102         char[] toANSIString() {
103             return "\033[0;37mclass " ~ name;
104         }
105
106         char[] toString() {
107             return "class " ~ name;
108         }
109 }
110
111 // A D module definition:
112 class DModule : DSymbol {
113     public:
114         // Doesn't have much.
115         // Should expand to contain class definitions, functions, and other symbols.
116
117         this(char[] name) {
118             this.name = name;
119         }
120
121         char[] toANSIString() {
122             return "\033[0;37mmodule " ~ name;
123         }
124
125         char[] toString() {
126             return "module " ~ name;
127         }
128 }
129
130
131 // A reserved type:
132 class DReservedType : DType {
133     public:
134         this() {
135            
136         }
137
138         // Initialize a DType with a string representation:
139         this(char[] chars) {
140             asString = chars;
141         }
142
143         version (destructors) ~this() {
144             debug (destruct) printf("DReservedType.~this()\n");
145         }
146 }
147
148 // A D type:
149 class DType {
150     private:
151         char[]  asString;       // what this type is as a string
152
153     public:
154         // Some static basic types:
155         static DReservedType None;      // ever used?
156         static DReservedType Void;
157         static DReservedType Byte;
158         static DReservedType UByte;
159         static DReservedType Short;
160         static DReservedType UShort;
161         static DReservedType Int;
162         static DReservedType UInt;
163         static DReservedType Long;
164         static DReservedType ULong;
165         static DReservedType Float;
166         static DReservedType Double;
167         static DReservedType Real;
168
169         // imaginary and complex:
170         static DReservedType IFloat;
171         static DReservedType IDouble;
172         static DReservedType IReal;
173         static DReservedType CFloat;
174         static DReservedType CDouble;
175         static DReservedType CReal;
176
177         // other types:
178         static DReservedType Bit;
179         static DReservedType Char;
180         static DReservedType WChar;
181         static DReservedType DChar;
182
183         // Initialize the basic types:
184         static this() {
185             // basic types:
186             None = new DReservedType("none");       // ever used?
187             Void = new DReservedType("void");
188             Byte = new DReservedType("byte");
189             UByte = new DReservedType("ubyte");
190             Short = new DReservedType("short");
191             UShort = new DReservedType("ushort");
192             Int = new DReservedType("int");
193             UInt = new DReservedType("uint");
194             Long = new DReservedType("long");
195             ULong = new DReservedType("ulong");
196             Float = new DReservedType("float");
197             Double = new DReservedType("double");
198             Real = new DReservedType("real");
199
200             // imaginary and complex:
201             IFloat = new DReservedType("ifloat");
202             IDouble = new DReservedType("idouble");
203             IReal = new DReservedType("ireal");
204             CFloat = new DReservedType("cfloat");
205             CDouble = new DReservedType("cdouble");
206             CReal = new DReservedType("creal");
207
208             // other types:
209             Bit = new DReservedType("bit");
210             Char = new DReservedType("char");
211             WChar = new DReservedType("wchar");
212             DChar = new DReservedType("dchar");
213         }
214
215         version (destructors) static ~this() {
216             debug (destruct) printf("static DType::~this()\n");
217             // basic types:
218             delete None;        // ever used?
219             delete Void;
220             delete Byte;
221             delete UByte;
222             delete Short;
223             delete UShort;
224             delete Int;
225             delete UInt;
226             delete Long;
227             delete ULong;
228             delete Float;
229             delete Double;
230             delete Real;
231
232             // imaginary and complex:
233             delete IFloat;
234             delete IDouble;
235             delete IReal;
236             delete CFloat;
237             delete CDouble;
238             delete CReal;
239
240             // other types:
241             delete Bit;
242             delete Char;
243             delete WChar;
244             delete DChar;
245             debug (destruct) printf("static DType::~this() deleted\n");
246         }
247
248     public:
249         // Not sure why, but the compiler complains without it:
250         this() {
251            
252         }
253
254         version (destructors) ~this() {
255            
256         }
257
258         // Convert the type to its string representation:
259         char[] toANSIString() {
260             return "\033[34m" ~ asString;
261         }
262
263         char[] toString() {
264             return asString;
265         }
266 }
267
268 // This exception is thrown on parsing errors and type errors:
269 class DTypeException : Exception {
270     public:
271         this(char[] msg) {
272             super("DTypeException: " ~ msg);
273         }
274 }
275
276 // Simple D types:
277
278 // Array:
279 class DTypeArray : DType {
280     private:
281         DType   internalType;       // the type of the array
282
283     public:
284         this(DType singleType) {
285             this.internalType = singleType;
286         }
287
288         version (destructors) ~this() {
289             debug (destruct) printf("DTypeArray.~this()\n");
290             if (cast(DReservedType)internalType is null)
291                 delete internalType;
292         }
293
294         // append a [] to the end of the type:
295         char[] toANSIString() {
296             return internalType.toANSIString() ~ "\033[1;31m[]\033[0;37m";
297         }
298
299         char[] toString() {
300             return internalType.toString() ~ "[]";
301         }
302 }
303
304 // Static array:
305 class DTypeSArray : DType {
306     private:
307         DType   internalType;       // the type of the array
308
309     public:
310         this(DType singleType) {
311             this.internalType = singleType;
312         }
313
314         version (destructors) ~this() {
315             debug (destruct) printf("DTypeSArray.~this()\n");
316             if (cast(DReservedType)internalType is null)
317                 delete internalType;
318         }
319
320         // append a [] to the end of the type:
321         char[] toANSIString() {
322             return internalType.toANSIString() ~ "\033[1;31m[]\033[0;37m";
323         }
324
325         char[] toString() {
326             return internalType.toString() ~ "[]";
327         }
328 }
329
330 // Dynamic array:
331 class DTypeDArray : DType {
332     private:
333         DType   internalType;       // the type of the array
334
335     public:
336         this(DType singleType) {
337             this.internalType = singleType;
338         }
339
340         version (destructors) ~this() {
341             debug (destruct) printf("DTypeDArray.~this()\n");
342             if (cast(DReservedType)internalType is null)
343                 delete internalType;
344         }
345
346         // append a [] to the end of the type:
347         char[] toANSIString() {
348             return internalType.toANSIString() ~ "\033[1;31m[]\033[0;37m";
349         }
350
351         char[] toString() {
352             return internalType.toString() ~ "[]";
353         }
354 }
355
356 // Pointer:
357 class DTypePointer : DType {
358     private:
359         DType   internalType;       // the type of pointer
360
361     public:
362         this(DType singleType) {
363             this.internalType = singleType;
364         }
365
366         version (destructors) ~this() {
367             debug (destruct) ("DTypePointer.~this()\n");
368             if (cast(DReservedType)internalType is null)
369                 delete internalType;
370         }
371
372         char[] toANSIString() {
373             return internalType.toANSIString() ~ "\033[1;33m*\033[0;37m";
374         }
375
376         char[] toString() {
377             return internalType.toString() ~ "*";
378         }
379 }
380
381 // Reference:
382 class DTypeReference : DType {
383     private:
384         DType   internalType;       // the type of reference
385
386     public:
387         this(DType singleType) {
388             this.internalType = singleType;
389         }
390
391         version (destructors) ~this() {
392             debug (destruct) printf("DTypeReference.~this()\n");
393             if (cast(DReservedType)internalType is null)
394                 delete internalType;
395         }
396
397         char[] toANSIString() {
398             return internalType.toANSIString() ~ "\033[1;33m&\033[0;37m";
399         }
400        
401         char[] toString() {
402             return internalType.toString() ~ "&";
403         }
404 }
405
406 // out parameter:
407 // (in is default)
408 class DTypeOut : DType {
409     private:
410         DType   internalType;       // an out parameter
411
412     public:
413         this(DType singleType) {
414             if (!(cast(DTypeInOut)singleType is null))
415                 throw new DTypeException("inout cannot be followed by out!");
416             if (!(cast(DTypeOut)singleType is null))
417                 throw new DTypeException("out cannot be followed by out!");
418
419             this.internalType = singleType;
420         }
421
422         version (destructors) ~this() {
423             debug (destruct) printf("DTypeOut.~this()\n");
424             if (cast(DReservedType)internalType is null)
425                 delete internalType;
426         }
427
428         char[] toANSIString() {
429             return "\033[34mout " ~ internalType.toANSIString();
430         }
431
432         char[] toString() {
433             return "out " ~ internalType.toString();
434         }
435 }
436
437 // inout parameter:
438 class DTypeInOut : DType {
439     private:
440         DType   internalType;       // an inout parameter
441
442     public:
443         this(DType singleType) {
444             if (!(cast(DTypeInOut)singleType is null))
445                 throw new DTypeException("inout cannot be followed by inout!");
446             if (!(cast(DTypeOut)singleType is null))
447                 throw new DTypeException("out cannot be followed by inout!");
448
449             this.internalType = singleType;
450         }
451
452         version (destructors) ~this() {
453             debug (destruct) printf("DTypeInOut.~this()\n");
454             if (cast(DReservedType)internalType is null)
455                 delete internalType;
456         }
457
458         char[] toANSIString() {
459             return "\033[34minout " ~ internalType.toANSIString();
460         }
461
462         char[] toString() {
463             return "inout " ~ internalType.toString();
464         }
465 }
466
467 // enum:
468 class DTypeEnumeration : DType {
469     private:
470         char[]  identifier;         // the name of the enum type
471
472     public:
473         this(char[] ident) {
474             this.identifier = ident;
475         }
476
477         version (destructors) ~this() {
478             debug (destruct) printf("DTypeEnumeration.~this()\n");
479         }
480
481         char[] toANSIString() {
482             return "\033[0;37m" ~ identifier;
483         }
484
485         char[] toString() {
486             return identifier;
487         }
488 }
489
490 // typedef:
491 class DTypeTypedef : DType {
492     private:
493         char[]  identifier;         // the name of the typedef type
494
495     public:
496         this(char[] ident) {
497             this.identifier = ident;
498         }
499
500         version (destructors) ~this() {
501             debug (destruct) printf("DTypeTypedef.~this()\n");
502         }
503
504         char[] toANSIString() {
505             return "\033[0;37m" ~ identifier;
506         }
507
508         char[] toString() {
509             return identifier;
510         }
511 }
512
513 // delegate:
514 class DTypeDelegate : DType {
515     private:
516         char[]  identifier;         // the name of the delegate type
517
518     public:
519         this(char[] ident) {
520             this.identifier = ident;
521         }
522
523         version (destructors) ~this() {
524             debug (destruct) printf("DTypeDelegate.~this()\n");
525         }
526
527         char[] toANSIString() {
528             return "\033[0;37m" ~ identifier;
529         }
530
531         char[] toString() {
532             return identifier;
533         }
534 }
535
536 // class instance:
537 class DTypeClass : DType {
538     private:
539         char[]  identifier;         // the name of the class type
540
541     public:
542         this(char[] ident) {
543             this.identifier = ident;
544         }
545
546         version (destructors) ~this() {
547             debug (destruct) printf("DTypeClass.~this()\n");
548         }
549
550         char[] toANSIString() {
551             return "\033[0;37m" ~ identifier;
552         }
553
554         char[] toString() {
555             return identifier;
556         }
557 }
558
559 // struct instance:
560 class DTypeStruct : DType {
561     private:
562         char[]  identifier;         // the name of the struct type
563
564     public:
565         this(char[] ident) {
566             this.identifier = ident;
567         }
568
569         version (destructors) ~this() {
570             debug (destruct) printf("DTypeStruct.~this()\n");
571         }
572
573         char[] toANSIString() {
574             return "\033[0;37m" ~ identifier;
575         }
576
577         char[] toString() {
578             return identifier;
579         }
580 }
581
582 // identifier:
583 class DTypeIdentifier : DType {
584     private:
585         char[]  identifier;
586
587     public:
588         this(char[] ident) {
589             this.identifier = ident;
590         }
591
592         version (destructors) ~this() {
593             debug (destruct) printf("DTypeIdentifier.~this()\n");
594         }
595
596         char[] toANSIString() {
597             return "\033[0;37m" ~ identifier;
598         }
599
600         char[] toString() {
601             return identifier;
602         }
603 }
604
605 // The extractor class:
606 class DSymbolExtractor {
607     private:
608
609         // extracts a series of dot-separated identifiers:
610         char[] extractidentifiers(char[] id, inout int i) {
611             char[]  s;
612             bool first = true;
613
614             for (;;) {
615                 int num = i;
616
617                 // Parse numeric length:
618                 while (i < id.length) {
619                     if (!isdigit(id[i])) break;
620                     ++i;
621                 }
622                 if (num == i) break;
623
624                 // Get the length as an integer:
625                 int len = atoi(id[num .. i]);
626                 // Extract the identifier
627                 if (!first) s ~= ".";
628
629                 if (i+len > id.length)
630                     throw new DTypeException("length of identifier would exceed length of mangled string!");
631
632                 s ~= id[i .. i+len];
633                 i += len;
634
635                 // Dot-separate after this:
636                 first = false;
637             }
638
639             // Return the identifier string:
640             return s;
641         }
642
643         // extracts a single definition (like a parameter)
644         DType extracttypeinfo(char[] id, inout int i) {
645             if (i >= id.length)
646                 throw new DTypeException("unexpected end of identifier!");
647
648             // Extract the type info:
649             switch (id[i]) {
650                 // array, static array, dynamic array:
651                 case 'A': ++i; return new DTypeArray(extracttypeinfo(id, i));
652                 case 'G': ++i; return new DTypeSArray(extracttypeinfo(id, i));
653                 case 'H': ++i; return new DTypeDArray(extracttypeinfo(id, i));
654                 // pointer:
655                 case 'P': ++i; return new DTypePointer(extracttypeinfo(id, i));
656                 // reference:
657                 case 'R': ++i; return new DTypeReference(extracttypeinfo(id, i));
658                 // out:
659                 case 'J': ++i; return new DTypeOut(extracttypeinfo(id, i));
660                 // inout:
661                 case 'K': ++i; return new DTypeInOut(extracttypeinfo(id, i));
662
663                 // enum:
664                 case 'E': ++i; return new DTypeEnumeration(extractidentifiers(id, i));
665                 // typedef:
666                 case 'T': ++i; return new DTypeTypedef(extractidentifiers(id, i));
667                 // delegate:
668                 case 'D': ++i; return new DTypeDelegate(extractidentifiers(id, i));
669                 // class:
670                 case 'C': ++i; return new DTypeClass(extractidentifiers(id, i));
671                 // struct:
672                 case 'S': ++i; return new DTypeStruct(extractidentifiers(id, i));
673                 // identifier:
674                 case 'I': ++i