1 module dparse.formatter;
2 
3 import std.algorithm;
4 import std.range;
5 import std.stdio;
6 import std.typetuple:TypeTuple;
7 
8 import dparse.ast;
9 import dparse.lexer;
10 
11 //debug = verbose;
12 
13 /**
14  * The only brace styles worth using.
15  */
16 enum IndentStyle
17 {
18     /**
19      * ---
20      * if (something)
21      * {
22      *     foo();
23      *     bar();
24      * }
25      * else
26      * {
27      *     bar();
28      *     baz();
29      * }
30      * ---
31      */
32     allman,
33     /**
34      * ---
35      * if (something) {
36      *     foo();
37      *     bar();
38      * } else {
39      *     bar();
40      *     baz();
41      * }
42      * ---
43      */
44     otbs,
45 }
46 
47 /**
48  *
49  */
50 void format(Sink, T)(Sink sink, T node, bool useTabs = false,
51     IndentStyle style = IndentStyle.allman, uint indentWith = 4)
52 {
53     Formatter!Sink formatter = new Formatter!(Sink)(sink, useTabs, style, indentWith);
54     formatter.format(node);
55 }
56 
57 ///
58 class Formatter(Sink)
59 {
60     /**
61      * Params:
62      *     sink = the output range that the formatted source code is placed in
63      *     useTabs = if true, tabs are used for indent levels instead of spaces
64      *     style = the brace style
65      *     indenteWidth = the number of spaces used for indentation if useTabs is false
66      */
67     this(Sink sink, bool useTabs = false, IndentStyle style = IndentStyle.allman, uint indentWidth = 4)
68     {
69         this.sink = sink;
70         this.useTabs = useTabs;
71         this.style = style;
72         this.indentWidth = indentWidth;
73     }
74 
75     ///
76     void format(const AddExpression addExpression)
77     {
78         debug(verbose) writeln("AddExpression");
79         mixin(binary("addExpression"));
80     }
81 
82     ///
83     void format(const AliasDeclaration aliasDeclaration, const Attribute[] attrs = null)
84     {
85         debug(verbose) writeln("AliasDeclaration");
86 
87         /**
88         LinkageAttribute linkageAttribute;
89         Type type;
90         Token name;
91         AliasInitializer[] initializers;
92         string comment;
93         **/
94 
95         with(aliasDeclaration)
96         {
97             newThing(What.other);
98             putComment(comment);
99             putAttrs(attrs);
100             put("alias ");
101 
102             if (initializers.length) // alias ident = a, ident2 = b, etc
103             {
104                 foreach(count, init; initializers)
105                 {
106                     if (count)
107                         put(", ");
108                     format(init);
109                 }
110             }
111             else
112             {
113                 foreach (storageClass; storageClasses)
114                 {
115                     format(storageClass);
116                     space();
117                 }
118 
119                 if (type)
120                 {
121                     format(type);
122                     space();
123                 }
124                 format(identifierList);
125             }
126             put(";");
127         }
128     }
129 
130     void format(const AliasInitializer aliasInitializer)
131     {
132         debug(verbose) writeln("AliasInitializer");
133 
134         /**
135         Token name;
136         Type type;
137         **/
138 
139         with(aliasInitializer)
140         {
141             format(name);
142             put(" = ");
143             format(type);
144         }
145     }
146 
147     void format(const AliasThisDeclaration decl, const Attribute[] attrs = null)
148     {
149         debug(verbose) writeln("AliasThisDeclaration");
150 
151         /**
152         Token identifier;
153         **/
154 
155         putAttrs(attrs);
156         put("alias ");
157         format(decl.identifier);
158         put(" this;");
159     }
160 
161     void format(const AlignAttribute alignAttribute)
162     {
163         debug(verbose) writeln("AlignAttribute");
164 
165         /**
166         Token intLiteral;
167         **/
168 
169         put("align");
170         if (alignAttribute.intLiteral.text)
171         {
172             put("(");
173             format(alignAttribute.intLiteral);
174             put(")");
175         }
176     }
177 
178     void format(const AndAndExpression andAndExpression)
179     {
180         debug(verbose) writeln("AndAndExpression");
181 
182         with(andAndExpression)
183         {
184             format(left);
185             if (right)
186             {
187                 put(" && ");
188                 format(right);
189             }
190         }
191     }
192 
193     void format(const AndExpression andExpression)
194     {
195         debug(verbose) writeln("AndExpression");
196 
197         with(andExpression)
198         {
199             format(left);
200             if (right)
201             {
202                 put(" & ");
203                 format(right);
204             }
205         }
206     }
207 
208     void format(const ArgumentList argumentList)
209     {
210         debug(verbose) writeln("ArgumentList");
211 
212         foreach(count, arg; argumentList.items)
213         {
214             if (count) put(", ");
215             format(arg);
216         }
217     }
218 
219     void format(const Arguments arguments)
220     {
221         debug(verbose) writeln("Arguments");
222 
223         put("(");
224         if (arguments.argumentList) format(arguments.argumentList);
225         put(")");
226     }
227 
228     void format(const ArrayInitializer arrayInitializer)
229     {
230         debug(verbose) writeln("ArrayInitializer");
231 
232         /**
233         ArrayMemberInitialization[] arrayMemberInitializations;
234         **/
235 
236         put("[");
237         foreach(count, init; arrayInitializer.arrayMemberInitializations)
238         {
239             format(init);
240             if (count < arrayInitializer.arrayMemberInitializations.length - 1)
241                 put(", ");
242         }
243         put("]");
244     }
245 
246     void format(const ArrayLiteral arrayLiteral)
247     {
248         debug(verbose) writeln("ArrayLiteral");
249 
250         /**
251         ArgumentList argumentList;
252         **/
253         put("[");
254         if (arrayLiteral.argumentList)
255             format(arrayLiteral.argumentList);
256         put("]");
257     }
258 
259     void format(const ArrayMemberInitialization arrayMemberInitialization)
260     {
261         debug(verbose) writeln("ArrayMemberInitialization");
262 
263         /**
264         AssignExpression assignExpression;
265         NonVoidInitializer nonVoidInitializer;
266         **/
267 
268         with(arrayMemberInitialization)
269         {
270             if (assignExpression)
271             {
272                 format(assignExpression);
273                 put(":");
274             }
275             if (nonVoidInitializer)
276                 format(nonVoidInitializer);
277 
278         }
279     }
280 
281     void format(const AsmAddExp asmAddExp)
282     {
283         assert(false);
284     }
285 
286     void format(const AsmAndExp asmAndExp)
287     {
288         assert(false);
289     }
290 
291     void format(const AsmBrExp asmBrExp)
292     {
293         assert(false);
294     }
295 
296     void format(const AsmEqualExp asmEqualExp)
297     {
298         assert(false);
299     }
300 
301     void format(const AsmExp asmExp)
302     {
303         assert(false);
304     }
305 
306     void format(const AsmInstruction asmInstruction)
307     {
308         assert(false);
309     }
310 
311     void format(const AsmLogAndExp asmLogAndExp)
312     {
313         assert(false);
314     }
315 
316     void format(const AsmLogOrExp asmLogOrExp)
317     {
318         assert(false);
319     }
320 
321     void format(const AsmMulExp asmMulExp)
322     {
323         assert(false);
324     }
325 
326     void format(const AsmOrExp asmOrExp)
327     {
328         assert(false);
329     }
330 
331     void format(const AsmPrimaryExp asmPrimaryExp)
332     {
333         assert(false);
334     }
335 
336     void format(const AsmRelExp asmRelExp)
337     {
338         assert(false);
339     }
340 
341     void format(const AsmShiftExp asmShiftExp)
342     {
343         assert(false);
344     }
345 
346     void format(const AsmStatement asmStatement)
347     {
348         assert(false);
349     }
350 
351     void format(const AsmTypePrefix asmTypePrefix)
352     {
353         assert(false);
354     }
355 
356     void format(const AsmUnaExp asmUnaExp)
357     {
358         assert(false);
359     }
360 
361     void format(const AsmXorExp asmXorExp)
362     {
363         assert(false);
364     }
365 
366     void format(const AssertExpression assertExpression)
367     {
368         debug(verbose) writeln("AssertExpression");
369 
370         /**
371         AssignExpression assertion;
372         AssignExpression message;
373         **/
374 
375         with(assertExpression)
376         {
377             put("assert (");
378             format(assertion);
379             if (message)
380             {
381                 put(", ");
382                 format(message);
383             }
384             put(")");
385         }
386     }
387 
388     void format(const AssignExpression assignExpression)
389     {
390         debug(verbose) writeln("AssignExpression");
391 
392         /**
393         ExpressionNode ternaryExpression;
394         ExpressionNode assignExpression;
395         IdType operator;
396         **/
397 
398         if (assignExpression.ternaryExpression)
399             format(assignExpression.ternaryExpression);
400 
401         if(assignExpression.expression)
402         {
403             space();
404             put(tokenRep(assignExpression.operator));
405             space();
406             format(assignExpression.expression);
407         }
408     }
409 
410     void format(const AssocArrayLiteral assocArrayLiteral)
411     {
412         debug(verbose) writeln("AssocArrayLiteral");
413 
414         /**
415         KeyValuePairs keyValuePairs;
416         **/
417 
418         put("[");
419         format(assocArrayLiteral.keyValuePairs);
420         put("]");
421     }
422 
423     void format(const AtAttribute atAttribute)
424     {
425         debug(verbose) writeln("AtAttribute");
426 
427         /**
428         FunctionCallExpression functionCallExpression;
429         ArgumentList argumentList;
430         Token identifier;
431         **/
432 
433         with(atAttribute)
434         {
435             put("@");
436             format(identifier);
437             if(argumentList) format(argumentList);
438         }
439     }
440 
441     void format(const Attribute att)
442     {
443         debug(verbose) writeln("Attribute");
444 
445         /**
446         LinkageAttribute linkageAttribute;
447         AlignAttribute alignAttribute;
448         PragmaExpression pragmaExpression;
449         StorageClass storageClass;
450         IdType attribute;
451         **/
452 
453         with(att)
454         {
455             if (pragmaExpression) format(pragmaExpression);
456             if (attribute.type != tok!"") put(tokenRep(attribute.type));
457             if (identifierChain)
458             {
459                 put("(");
460                 format(identifierChain);
461                 put(")");
462             }
463             if (deprecated_) format(deprecated_);
464             if (atAttribute) format(atAttribute);
465             if (linkageAttribute) format(linkageAttribute);
466         }
467     }
468 
469     void format(const AttributeDeclaration decl, const Attribute[] attrs = null)
470     {
471         debug(verbose) writeln("AttributeDeclaration");
472 
473         auto cIndent = indentLevel;
474         outdent();
475         newThing(What.attributeDecl);
476         putAttrs(attrs);
477         format(decl.attribute);
478         put(":");
479         indentLevel = cIndent;
480     }
481 
482     void format(const AutoDeclaration decl)
483     {
484         debug(verbose) writeln("AutoDeclaration");
485 
486         /**
487         Token[] identifiers;
488         Initializer[] initializers;
489         **/
490 
491         // zip doesn't work here, dmd 2.064.2
492         assert(decl.identifiers.length == decl.initializers.length);
493         foreach(i; 0..decl.identifiers.length)
494         {
495             if (i) put(", ");
496             format(decl.identifiers[i]);
497             put(" = ");
498             format(decl.initializers[i]);
499         }
500     }
501 
502     void format(const BlockStatement blockStatement)
503     {
504         debug(verbose) writeln("BlockStatement");
505 
506         if (blockStatement.declarationsAndStatements is null)
507         {
508             space();
509             put("{}");
510         }
511         else
512         {
513             startBlock();
514             format(blockStatement.declarationsAndStatements);
515             endBlock();
516         }
517     }
518 
519     void format(const BodyStatement bodyStatement)
520     {
521         debug(verbose) writeln("BodyStatement");
522 
523         newline();
524         put("body");
525         format(bodyStatement.blockStatement);
526     }
527 
528     void format(const BreakStatement breakStatement)
529     {
530         debug(verbose) writeln("BreakStatement");
531 
532         put("break");
533         if (breakStatement.label != tok!"")
534         {
535             space();
536             format(breakStatement.label);
537         }
538         put(";");
539     }
540 
541     void format(const BaseClass baseClass)
542     {
543         debug(verbose) writeln("BaseClass");
544         with(baseClass)
545         {
546             if (type2) format(type2);
547         }
548     }
549 
550     void format(const BaseClassList baseClassList)
551     {
552         debug(verbose) writeln("BaseClassList");
553         put(" : ");
554         foreach(count, item; baseClassList.items)
555         {
556             format(item);
557             if (count < baseClassList.items.length - 1)
558                 put(", ");
559         }
560     }
561 
562     void format(const CaseRangeStatement caseRangeStatement)
563     {
564         debug(verbose) writeln("CaseRangeStatement");
565 
566         /**
567         AssignExpression low;
568         AssignExpression high;
569         DeclarationsAndStatements declarationsAndStatements;
570         **/
571 
572         with(caseRangeStatement)
573         {
574             if (low)
575             {
576                 put("case ");
577                 format(low);
578                 put(": .. ");
579             }
580             put("case ");
581             format(high);
582             put(":");
583 
584             formatCaseDecls(declarationsAndStatements);
585         }
586     }
587 
588     void format(const CaseStatement caseStatement)
589     {
590         debug(verbose) writeln("CaseStatement");
591 
592         /**
593         ArgumentList argumentList;
594         DeclarationsAndStatements declarationsAndStatements;
595         **/
596 
597         with(caseStatement)
598         {
599             if (argumentList)
600             {
601                 put("case ");
602                 format(argumentList);
603                 put(":");
604             }
605 
606             formatCaseDecls(declarationsAndStatements);
607         }
608     }
609 
610     void format(const CastExpression castExpression)
611     {
612         debug(verbose) writeln("CastExpression");
613 
614         /**
615         Type type;
616         CastQualifier castQualifier;
617         UnaryExpression unaryExpression;
618         **/
619 
620         with(castExpression)
621         {
622             put("cast(");
623             if (castQualifier)
624             {
625                 format(castQualifier);
626                 space();
627             }
628             if (type) format(type);
629             put(")");
630             if (unaryExpression) format(unaryExpression);
631         }
632     }
633 
634     void format(const CastQualifier qual)
635     {
636         debug(verbose) writeln("CastQualifier");
637 
638         /**
639         Token first;
640         Token second;
641         **/
642 
643         format(qual.first);
644         if (qual.second != tok!"")
645         {
646             space();
647             format(qual.second);
648         }
649     }
650 
651     void format(const Catch catch_)
652     {
653         debug(verbose) writeln("Catch");
654 
655         /**
656         Type type;
657         Token identifier;
658         DeclarationOrStatement declarationOrStatement;
659         **/
660 
661         with(catch_)
662         {
663             newThing(What.catch_);
664             put("catch(");
665             format(type);
666             if (identifier != tok!"")
667             {
668                 space();
669                 format(identifier);
670             }
671             put(")");
672             if (declarationOrStatement) maybeIndent(declarationOrStatement);
673         }
674     }
675 
676     void format(const Catches catches)
677     {
678         debug(verbose) writeln("Catches");
679 
680         /**
681         Catch[] catches;
682         LastCatch lastCatch;
683         **/
684 
685         foreach(c; catches.catches)
686             format(c);
687         if (catches.lastCatch)
688             format(catches.lastCatch);
689     }
690 
691     void format(const ClassDeclaration decl, const Attribute[] attrs = null)
692     {
693         debug(verbose) writeln("ClassDeclaration");
694 
695         /**
696         Token name;
697         TemplateParameters templateParameters;
698         Constraint constraint;
699         BaseClassList baseClassList;
700         StructBody structBody;
701         string comment;
702         **/
703 
704         newThing(What.aggregateDecl);
705         putComment(decl.comment);
706         putAttrs(attrs);
707 
708         put("class ");
709         format(decl.name);
710 
711         if (decl.templateParameters)
712             format(decl.templateParameters);
713 
714         if (decl.constraint)
715         {
716             space();
717             format(decl.constraint);
718         }
719 
720         if (decl.baseClassList)
721         {
722             format(decl.baseClassList);
723         }
724 
725         format(decl.structBody);
726     }
727 
728     void format(const CmpExpression cmpExpression)
729     {
730         debug(verbose) writeln("CmpExpression");
731 
732         /**
733         ExpressionNode shiftExpression;
734         ExpressionNode equalExpression;
735         ExpressionNode identityExpression;
736         ExpressionNode relExpression;
737         ExpressionNode inExpression;
738         **/
739 
740         with(cmpExpression)
741         {
742             if (shiftExpression) format(shiftExpression);
743             else if (equalExpression) format(equalExpression);
744             else if (identityExpression) format(identityExpression);
745             else if (relExpression) format(relExpression);
746             else if (inExpression) format(inExpression);
747         }
748     }
749 
750     void format(const CompileCondition compileCondition)
751     {
752         debug(verbose) writeln("CompileCondition");
753 
754         /**
755         VersionCondition versionCondition;
756         DebugCondition debugCondition;
757         StaticIfCondition staticIfCondition;
758         **/
759 
760         with(compileCondition)
761         {
762             if (versionCondition) format(versionCondition);
763             else if (debugCondition) format(debugCondition);
764             else if (staticIfCondition) format(staticIfCondition);
765         }
766     }
767 
768     void format(const ConditionalDeclaration decl, const Attribute[] attrs = null)
769     {
770         debug(verbose) writeln("ConditionalDeclaration");
771 
772         /**
773         CompileCondition compileCondition;
774         Declaration[] trueDeclarations;
775         Declaration[] falseDeclaration;
776         **/
777 
778         newThing(What.conditionalDecl);
779         putAttrs(attrs);
780         format(decl.compileCondition);
781 
782         if (decl.trueDeclarations.length > 1)
783         {
784             startBlock();
785             foreach (d; decl.trueDeclarations)
786                 format(d);
787             endBlock();
788         }
789         else if (decl.trueDeclarations.length == 0)
790             maybeIndent(decl.trueDeclarations[0]);
791         else
792             put("{}");
793 
794         if (decl.falseDeclarations.length > 0)
795             put("else");
796 
797         if (decl.falseDeclarations.length > 1)
798         {
799             startBlock();
800             foreach (d; decl.falseDeclarations)
801                 format(d);
802             endBlock();
803         }
804         else if (decl.falseDeclarations.length == 0)
805             maybeIndent(decl.falseDeclarations[0]);
806         else
807             put("{}");
808     }
809 
810     void format(const ConditionalStatement stmnt)
811     {
812         debug(verbose) writeln("ConditionalStatement");
813 
814         /**
815         CompileCondition compileCondition;
816         DeclarationOrStatement trueStatement;
817         DeclarationOrStatement falseStatement;
818         **/
819 
820         newThing(What.other);
821         if (stmnt.compileCondition)
822             format(stmnt.compileCondition);
823 
824         if (stmnt.trueStatement)
825             maybeIndent(stmnt.trueStatement);
826 
827         if (stmnt.falseStatement)
828         {
829             newThing(What.else_);
830             put("else ");
831 
832             // else if...
833             if (stmnt.falseStatement.statement &&
834                 stmnt.falseStatement.statement.statementNoCaseNoDefault &&
835                 stmnt.falseStatement.statement.statementNoCaseNoDefault.conditionalStatement)
836             {
837                 format(stmnt.falseStatement.statement.statementNoCaseNoDefault.conditionalStatement);
838                 return;
839             }
840 
841             maybeIndent(stmnt.falseStatement);
842         }
843     }
844 
845     void format(const Constraint constraint)
846     {
847         debug(verbose) writeln("Constraint");
848 
849         if (constraint.expression)
850         {
851             indent();
852             newline();
853             put("if(");
854             format(constraint.expression);
855             put(")");
856             outdent();
857         }
858     }
859 
860     void format(const Constructor constructor, const Attribute[] attrs = null)
861     {
862         debug(verbose) writeln("Constructor");
863 
864         /**
865         Parameters parameters;
866         FunctionBody functionBody;
867         Constraint constraint;
868         MemberFunctionAttribute[] memberFunctionAttributes;
869         TemplateParameters templateParameters;
870         size_t location;
871         string comment;
872         **/
873 
874         newThing(What.functionDecl);
875         putComment(constructor.comment);
876         putAttrs(attrs);
877 
878         put("this");
879 
880         if (constructor.templateParameters)
881             format(constructor.templateParameters);
882 
883         if (constructor.parameters)
884             format(constructor.parameters);
885 
886         foreach(att; constructor.memberFunctionAttributes)
887         {
888             space();
889             format(att);
890         }
891 
892         if (constructor.constraint)
893         {
894             space();
895             format(constructor.constraint);
896         }
897 
898         if (constructor.functionBody)
899             format(constructor.functionBody);
900         else
901             put(";");
902     }
903 
904     void format(const ContinueStatement continueStatement)
905     {
906         debug(verbose) writeln("ContinueStatement");
907 
908         put("continue");
909         if (continueStatement.label != tok!"")
910         {
911             space();
912             format(continueStatement.label);
913         }
914         put(";");
915     }
916 
917     void format(const DebugCondition debugCondition)
918     {
919         debug(verbose) writeln("DebugCondition");
920 
921         put("debug");
922         if (debugCondition.identifierOrInteger != tok!"")
923         {
924             put("(");
925             format(debugCondition.identifierOrInteger);
926             put(")");
927         }
928     }
929 
930     void format(const DebugSpecification debugSpecification)
931     {
932         debug(verbose) writeln("DebugSpecification");
933 
934         newThing(What.other);
935         put("debug = ");
936         format(debugSpecification.identifierOrInteger);
937         put(";");
938     }
939 
940     void format(const Declaration declaration)
941     {
942         debug(verbose) writeln("Declaration");
943 
944         with(declaration)
945         {
946             string mix(string[] s) {
947                 string r;
948                 foreach(c, d; s)
949                     r ~= (c > 0 ? "else " : "") ~ "if (" ~ d ~ ") { format(" ~ d ~ ", attributes); }";
950                 return r;
951             }
952 
953             mixin(mix(possibleDeclarations));
954 
955             if (declarations.length)
956             {
957                 putAttrs(attributes);
958                 startBlock();
959                 foreach(d; declarations)
960                     format(d);
961                 endBlock();
962             }
963         }
964     }
965 
966     void format(const DeclarationOrStatement declarationsOrStatement)
967     {
968         debug(verbose) writeln("DeclarationOrStatement");
969 
970         with(declarationsOrStatement)
971             declaration !is null ? format(declaration) : format(statement);
972     }
973 
974     void format(const DeclarationsAndStatements declarationsAndStatements)
975     {
976         debug(verbose) writeln("DeclarationsAndStatements");
977 
978         foreach(ds; declarationsAndStatements.declarationsAndStatements)
979             format(ds);
980     }
981 
982     void format(const Declarator declarator)
983     {
984         debug(verbose) writeln("Declarator");
985 
986         /**
987         Token name;
988         Initializer initializer;
989         **/
990 
991         format(declarator.name);
992 
993         foreach(suffix; declarator.cstyle)
994             format(suffix);
995 
996         if (declarator.templateParameters)
997             format(declarator.templateParameters);
998 
999         if (declarator.initializer)
1000         {
1001             put(" = ");
1002             format(declarator.initializer);
1003         }
1004     }
1005 
1006     void format(const DefaultStatement defaultStatement)
1007     {
1008         debug(verbose) writeln("DefaultStatement");
1009 
1010         /**
1011         DeclarationsAndStatements declarationsAndStatements;
1012         **/
1013 
1014         put("default:");
1015         formatCaseDecls(defaultStatement.declarationsAndStatements);
1016     }
1017 
1018     void format(const DeleteExpression deleteExpression)
1019     {
1020         debug(verbose) writeln("DeleteExpression");
1021 
1022         put("delete ");
1023         format(deleteExpression.unaryExpression);
1024     }
1025 
1026     void format(const DeleteStatement deleteStatement)
1027     {
1028         debug(verbose) writeln("DeleteStatement");
1029 
1030         format(deleteStatement.deleteExpression);
1031         put(";");
1032     }
1033 
1034     void format(const Deprecated deprecated_)
1035     {
1036         debug (verbose)
1037             writeln("Deprecated");
1038         put("deprecated");
1039         if (deprecated_.assignExpression !is null)
1040         {
1041             put("(");
1042             format(deprecated_.assignExpression);
1043             put(")");
1044         }
1045     }
1046 
1047     void format(const Destructor destructor, const Attribute[] attrs = null)
1048     {
1049         debug(verbose) writeln("Destructor");
1050 
1051         /**
1052         FunctionBody functionBody;
1053         **/
1054 
1055         newThing(What.functionDecl);
1056         putAttrs(attrs);
1057         put("~this()");
1058 
1059         if (destructor.functionBody)
1060             format(destructor.functionBody);
1061         else
1062             put(";");
1063     }
1064 
1065     void format(const DoStatement doStatement)
1066     {
1067         debug(verbose) writeln("DoStatement");
1068 
1069         /**
1070         StatementNoCaseNoDefault statementNoCaseNoDefault;
1071         Expression expression;
1072         **/
1073 
1074         with(doStatement)
1075         {
1076             newThing(What.other);
1077             put("do");
1078             if (statementNoCaseNoDefault) format(statementNoCaseNoDefault);
1079             space();
1080             put("while (");
1081             format(expression);
1082             put(");");
1083         }
1084     }
1085 
1086     void format(const EnumBody enumBody)
1087     {
1088         debug(verbose) writeln("EnumBody");
1089 
1090         newline();
1091         startBlock();
1092         foreach(count, member; enumBody.enumMembers)
1093         {
1094             format(member);
1095 
1096             if (count < enumBody.enumMembers.length - 1)
1097                 put(",");
1098 
1099             if (member.comment.length)
1100             {
1101                 space();
1102                 put(member.comment);
1103             }
1104         }
1105         endBlock();
1106     }
1107 
1108     void format(const EnumDeclaration enumDeclaration, const Attribute[] attrs = null)
1109     {
1110         debug(verbose) writeln("EnumDeclaration");
1111 
1112         /**
1113         Token name;
1114         Type type;
1115         EnumBody enumBody;
1116         string comment;
1117         **/
1118 
1119         with(enumDeclaration)
1120         {
1121             newThing(What.aggregateDecl);
1122             putComment(comment);
1123             putAttrs(attrs);
1124             put("enum ");
1125             if (name != tok!"")
1126             {
1127                 format(name);
1128                 space();
1129             }
1130             if (type)
1131             {
1132                 put(": ");
1133                 format(type);
1134                 space();
1135             }
1136             if (enumBody) format(enumBody);
1137         }
1138     }
1139 
1140     void format(const EnumMember enumMember)
1141     {
1142         debug(verbose) writeln("EnumMember");
1143 
1144         /**
1145         Token name;
1146         Type type;
1147         AssignExpression assignExpression;
1148         string comment;
1149         **/
1150 
1151         with(enumMember)
1152         {
1153             newline();
1154             if (type) format(type);
1155             format(name);
1156             if (assignExpression)
1157             {
1158                 put(" = ");
1159                 format(assignExpression);
1160             }
1161         }
1162     }
1163 
1164     void format(const EponymousTemplateDeclaration decl)
1165     {
1166         debug(verbose) writeln("EponymousTemplateDeclaration");
1167 
1168         /**
1169         Token name;
1170         TemplateParameters templateParameters;
1171         AssignExpression assignExpression;
1172         **/
1173 
1174         put("enum ");
1175         put(tokenRep(decl.name));
1176         if (decl.templateParameters)
1177             format(decl.templateParameters);
1178         if (decl.assignExpression)
1179         {
1180             put(" = ");
1181             format(decl.assignExpression);
1182         }
1183         put(";");
1184     }
1185 
1186     void format(const EqualExpression equalExpression)
1187     {
1188         debug(verbose) writeln("EqualExpression");
1189 
1190         mixin(binary("equalExpression"));
1191     }
1192 
1193     void format(const Expression expression)
1194     {
1195         debug(verbose) writeln("Expression");
1196 
1197         foreach(count, item; expression.items)
1198         {
1199             if (count)
1200                 put(", ");
1201             format(item);
1202         }
1203     }
1204 
1205     void format(const ExpressionNode n)
1206     {
1207         debug(verbose) writeln("ExpressionNode");
1208 
1209         if (cast(AddExpression) n) format(cast(AddExpression) n);
1210         else if (cast(AndAndExpression) n) format(cast(AndAndExpression) n);
1211         else if (cast(AndExpression) n) format(cast(AndExpression) n);
1212         else if (cast(AsmAddExp) n) format(cast(AsmAddExp) n);
1213         else if (cast(AsmAndExp) n) format(cast(AsmAndExp) n);
1214         else if (cast(AsmEqualExp) n) format(cast(AsmEqualExp) n);
1215         else if (cast(AsmLogAndExp) n) format(cast(AsmLogAndExp) n);
1216         else if (cast(AsmLogOrExp) n) format(cast(AsmLogOrExp) n);
1217         else if (cast(AsmMulExp) n) format(cast(AsmMulExp) n);
1218         else if (cast(AsmOrExp) n) format(cast(AsmOrExp) n);
1219         else if (cast(AsmRelExp) n) format(cast(AsmRelExp) n);
1220         else if (cast(AsmShiftExp) n) format(cast(AsmShiftExp) n);
1221         else if (cast(AssertExpression) n) format(cast(AssertExpression) n);
1222         else if (cast(AssignExpression) n) format(cast(AssignExpression) n);
1223         else if (cast(CmpExpression) n) format(cast(CmpExpression) n);
1224         else if (cast(DeleteExpression) n) format(cast(DeleteExpression) n);
1225         else if (cast(EqualExpression) n) format(cast(EqualExpression) n);
1226         else if (cast(Expression) n) format(cast(Expression) n);
1227         else if (cast(FunctionCallExpression) n) format(cast(FunctionCallExpression) n);
1228         else if (cast(FunctionLiteralExpression) n) format(cast(FunctionLiteralExpression) n);
1229         else if (cast(IdentityExpression) n) format(cast(IdentityExpression) n);
1230         else if (cast(ImportExpression) n) format(cast(ImportExpression) n);
1231         else if (cast(IndexExpression) n) format(cast(IndexExpression) n);
1232         else if (cast(InExpression) n) format(cast(InExpression) n);
1233         else if (cast(IsExpression) n) format(cast(IsExpression) n);
1234         else if (cast(MixinExpression) n) format(cast(MixinExpression) n);
1235         else if (cast(MulExpression) n) format(cast(MulExpression) n);
1236         else if (cast(NewAnonClassExpression) n) format(cast(NewAnonClassExpression) n);
1237         else if (cast(NewExpression) n) format(cast(NewExpression) n);
1238         else if (cast(OrExpression) n) format(cast(OrExpression) n);
1239         else if (cast(OrOrExpression) n) format(cast(OrOrExpression) n);
1240         else if (cast(PowExpression) n) format(cast(PowExpression) n);
1241         else if (cast(PragmaExpression) n) format(cast(PragmaExpression) n);
1242         else if (cast(PrimaryExpression) n) format(cast(PrimaryExpression) n);
1243         else if (cast(RelExpression) n) format(cast(RelExpression) n);
1244         else if (cast(ShiftExpression) n) format(cast(ShiftExpression) n);
1245         else if (cast(TemplateMixinExpression) n) format(cast(TemplateMixinExpression) n);
1246         else if (cast(TernaryExpression) n) format(cast(TernaryExpression) n);
1247         else if (cast(TraitsExpression) n) format(cast(TraitsExpression) n);
1248         else if (cast(TypeidExpression) n) format(cast(TypeidExpression) n);
1249         else if (cast(TypeofExpression) n) format(cast(TypeofExpression) n);
1250         else if (cast(UnaryExpression) n) format(cast(UnaryExpression) n);
1251         else if (cast(XorExpression) n) format(cast(XorExpression) n);
1252     }
1253 
1254     void format(const ExpressionStatement expressionStatement)
1255     {
1256         debug(verbose) writeln("ExpressionStatement");
1257 
1258         if (expressionStatement.expression)
1259             format(expressionStatement.expression);
1260         put(";");
1261     }
1262 
1263     void format(const FinalSwitchStatement finalSwitchStatement)
1264     {
1265         debug(verbose) writeln("FinalSwitchStatement");
1266 
1267         format(finalSwitchStatement.switchStatement, true);
1268     }
1269 
1270     void format(const Finally finally_)
1271     {
1272         debug(verbose) writeln("Finally");
1273 
1274         put("finally");
1275         format(finally_.declarationOrStatement);
1276     }
1277 
1278     void format(const ForStatement forStatement)
1279     {
1280         debug(verbose) writeln("ForStatement");
1281 
1282         /**
1283         DeclarationOrStatement initialization;
1284         ExpressionStatement test;
1285         Expression increment;
1286         DeclarationOrStatement declarationOrStatement;
1287         **/
1288 
1289         with(forStatement)
1290         {
1291             newThing(What.other);
1292             put("for (");
1293             if (initialization) format(initialization);
1294             else put(";");
1295             space();
1296             if (test) format(test);
1297             put(";");
1298             space();
1299             if (increment) format(increment);
1300             put(")");
1301 
1302             if (declarationOrStatement) maybeIndent(declarationOrStatement);
1303         }
1304     }
1305 
1306     void format(const ForeachStatement foreachStatement)
1307     {
1308         debug(verbose) writeln("ForeachStatement");
1309 
1310         /**
1311         IdType type;
1312         ForeachTypeList foreachTypeList;
1313         ForeachType foreachType;
1314         Expression low;
1315         Expression high;
1316         DeclarationOrStatement declarationOrStatement;
1317         size_t startIndex;
1318         **/
1319 
1320         with(foreachStatement)
1321         {
1322             newThing(What.loop);
1323             if (type) put(tokenRep(type));
1324             else assert(false);
1325 
1326             put(" (");
1327             if (foreachTypeList) format(foreachTypeList);
1328             else if (foreachType) format(foreachType);
1329 
1330             put("; ");
1331 
1332             if (low) format(low);
1333             if (high)
1334             {
1335                 put("..");
1336                 format(high);
1337             }
1338             put(")");
1339             format(declarationOrStatement);
1340         }
1341     }
1342 
1343     void format(const ForeachType foreachType)
1344     {
1345         debug(verbose) writeln("ForeachType");
1346 
1347         /**
1348         IdType[] typeConstructors;
1349         Type type;
1350         Token identifier;
1351         **/
1352 
1353         with(foreachType)
1354         {
1355             foreach(tp; typeConstructors)
1356             {
1357                 if (tp) put(tokenRep(tp));
1358                 space();
1359             }
1360             if (type)
1361             {
1362                 format(type);
1363                 space();
1364             }
1365             format(identifier);
1366         }
1367     }
1368 
1369     void format(const ForeachTypeList foreachTypeList)
1370     {
1371         debug(verbose) writeln("ForeachTypeList");
1372 
1373         /**
1374         ForeachType[] items;
1375         **/
1376 
1377         foreach(count, item; foreachTypeList.items)
1378         {
1379             format(item);
1380             if (count < foreachTypeList.items.length - 1)
1381                 put(", ");
1382         }
1383     }
1384 
1385     void format(const FunctionAttribute functionAttribute)
1386     {
1387         debug(verbose) writeln("FunctionAttribute");
1388 
1389         /**
1390         Token token;
1391         AtAttribute atAttribute;
1392         **/
1393 
1394         with(functionAttribute)
1395         {
1396             if (token != tok!"")
1397             {
1398                 format(token);
1399                 space();
1400             }
1401             if (atAttribute) format(atAttribute);
1402         }
1403     }
1404 
1405     void format(const FunctionBody functionBody)
1406     {
1407         debug(verbose) writeln("FunctionBody");
1408 
1409         with(functionBody)
1410         {
1411             if (blockStatement)
1412             {
1413                 format(blockStatement);
1414                 return;
1415             }
1416             if (inStatement)
1417                 format(inStatement);
1418             if (outStatement)
1419                 format(outStatement);
1420             if (bodyStatement)
1421                 format(bodyStatement);
1422         }
1423     }
1424 
1425     void format(const FunctionCallExpression functionCallExpression)
1426     {
1427         debug(verbose) writeln("FunctionCallExpression");
1428 
1429         /**
1430         Type type;
1431         UnaryExpression unaryExpression;
1432         TemplateArguments templateArguments;
1433         Arguments arguments;
1434         **/
1435 
1436         with(functionCallExpression)
1437         {
1438             if (type) format(type);
1439             if (unaryExpression) format(unaryExpression);
1440             if (templateArguments) format(templateArguments);
1441             if (arguments) format(arguments);
1442         }
1443     }
1444 
1445     void format(const FunctionDeclaration decl, const Attribute[] attrs = null)
1446     {
1447         debug(verbose) writeln("FunctionDeclaration");
1448 
1449         /**
1450         bool hasAuto;
1451         bool hasRef;
1452         **/
1453 
1454         newThing(What.functionDecl);
1455         putComment(decl.comment);
1456         putAttrs(attrs);
1457 
1458         foreach (sc; decl.storageClasses)
1459             format(sc);
1460 
1461         if (decl.returnType)
1462             format(decl.returnType);
1463 
1464         space();
1465         format(decl.name);
1466 
1467         if (decl.templateParameters)
1468             format(decl.templateParameters);
1469         if (decl.parameters)
1470             format(decl.parameters);
1471         foreach(attr; decl.memberFunctionAttributes)
1472         {
1473             space();
1474             format(attr);
1475         }
1476         if (decl.constraint)
1477         {
1478             space();
1479             format(decl.constraint);
1480         }
1481 
1482         if (decl.functionBody)
1483             format(decl.functionBody);
1484         else
1485             put(";");
1486     }
1487 
1488     void format(const FunctionLiteralExpression functionLiteralExpression)
1489     {
1490         debug(verbose) writeln("FunctionLiteralExpression");
1491 
1492         with(functionLiteralExpression)
1493         {
1494             put(tokenRep(functionOrDelegate));
1495 
1496             space();
1497             if (returnType) format(returnType);
1498             if (parameters) format(parameters);
1499 
1500             foreach(att; memberFunctionAttributes)
1501             {
1502                 space();
1503                 format(att);
1504             }
1505 
1506             ignoreNewlines = true;
1507             if (functionBody)
1508                 format(functionBody);
1509             else
1510             {
1511                 put(" => ");
1512                 format(assignExpression);
1513             }
1514             ignoreNewlines = false;
1515         }
1516     }
1517 
1518     void format(const GotoStatement gotoStatement)
1519     {
1520         debug(verbose) writeln("GotoStatement");
1521 
1522         put("goto ");
1523         gotoStatement.label != tok!"" ?
1524             put(tokenRep(gotoStatement.label)) :
1525                 format(gotoStatement.expression);
1526         put(";");
1527     }
1528 
1529     void format(const IdentifierChain identifierChain)
1530     {
1531         debug(verbose) writeln("IdentifierChain");
1532 
1533         foreach(count, ident; identifierChain.identifiers)
1534         {
1535             if (count) put(".");
1536             put(ident.text);
1537         }
1538     }
1539 
1540     void format(const IdentifierList identifierList)
1541     {
1542         debug(verbose) writeln("IdentifierList");
1543         foreach(count, ident; identifierList.identifiers)
1544         {
1545             if (count) put(", ");
1546             put(ident.text);
1547         }
1548     }
1549 
1550     void format(const IdentifierOrTemplateChain identifierOrTemplateChain)
1551     {
1552         debug(verbose) writeln("IdentifierOrTemplateChain");
1553 
1554         with(identifierOrTemplateChain)
1555         {
1556             foreach(count, ident; identifiersOrTemplateInstances)
1557             {
1558                 if (count) put(".");
1559                 format(ident);
1560             }
1561         }
1562     }
1563 
1564     void format(const IdentifierOrTemplateInstance identifierOrTemplateInstance)
1565     {
1566         debug(verbose) writeln("IdentifierOrTemplateInstance");
1567 
1568         with(identifierOrTemplateInstance)
1569         {
1570             format(identifier);
1571             if (templateInstance)
1572                 format(templateInstance);
1573         }
1574     }
1575 
1576     void format(const IdentityExpression identityExpression)
1577     {
1578         debug(verbose) writeln("IdentityExpression");
1579 
1580         with(identityExpression)
1581         {
1582             if (left) format(left);
1583             put(negated ? " !is " : " is ");
1584             if (right) format(right);
1585         }
1586     }
1587 
1588     void format(const IfStatement ifStatement)
1589     {
1590         debug(verbose) writeln("IfStatement");
1591 
1592         /**
1593         Token identifier;
1594         Type type;
1595         Expression expression;
1596         DeclarationOrStatement thenStatement;
1597         DeclarationOrStatement elseStatement;
1598         **/
1599 
1600         with(ifStatement)
1601         {
1602             bool isAuto = identifier != tok!"" && !type;
1603             bool isAssign = isAuto || type;
1604 
1605             put("if (");
1606 
1607             if (isAuto) put("auto ");
1608             if (type)
1609             {
1610                 format(type);
1611                 space();
1612             }
1613             if (identifier != tok!"")
1614             {
1615                 format(identifier);
1616                 space();
1617             }
1618             if (isAssign) put("= ");
1619             if (expression) format(expression);
1620             put(")");
1621 
1622             if (thenStatement)
1623                 maybeIndent(thenStatement);
1624 
1625             if (elseStatement)
1626             {
1627                 newThing(What.else_);
1628                 put("else ");
1629 
1630                 if (elseStatement.statement &&
1631                     elseStatement.statement.statementNoCaseNoDefault &&
1632                     elseStatement.statement.statementNoCaseNoDefault.ifStatement)
1633                 {
1634                     // this is to stop automatic newlineIndent
1635                     format(elseStatement.statement.statementNoCaseNoDefault.ifStatement);
1636                 }
1637                 else
1638                     maybeIndent(elseStatement);
1639             }
1640 
1641         }
1642     }
1643 
1644     void format(const ImportBind importBind)
1645     {
1646         debug(verbose) writeln("ImportBind");
1647 
1648         format(importBind.left);
1649         if (importBind.right != tok!"")
1650         {
1651             put(" = ");
1652             format(importBind.right);
1653         }
1654     }
1655 
1656     void format(const ImportBindings importBindings)
1657     {
1658         debug(verbose) writeln("ImportBindings");
1659 
1660         /**
1661         SingleImport singleImport;
1662         ImportBind[] importBinds;
1663         **/
1664 
1665         with(importBindings)
1666         {
1667             format(singleImport);
1668             put(" : ");
1669             foreach(count, bind; importBinds)
1670             {
1671                 if (count) put(", ");
1672                 format(bind);
1673             }
1674         }
1675     }
1676 
1677     void format(const ImportDeclaration importDeclaration, const Attribute[] attrs = null)
1678     {
1679         debug(verbose) writeln("ImportDeclaration");
1680 
1681         /**
1682         SingleImport[] singleImports;
1683         ImportBindings importBindings;
1684         **/
1685 
1686         with(importDeclaration)
1687         {
1688             newThing(What.importDecl);
1689             putAttrs(attrs);
1690             put("import ");
1691 
1692             if (singleImports.length == 1)
1693             {
1694                 format(singleImports[0]);
1695             }
1696             else if (singleImports.length > 1)
1697             {
1698                 indent();
1699                 newlineIndent();
1700                 foreach(count, imp; singleImports)
1701                 {
1702                     format(imp);
1703                     if (count < singleImports.length - 1)
1704                     {
1705                         put(", ");
1706                         newlineIndent();
1707                     }
1708                 }
1709                 outdent();
1710             }
1711 
1712             if (importBindings)
1713             {
1714                 if (singleImports.length)
1715                     put(", ");
1716                 format(importBindings);
1717             }
1718             put(";");
1719         }
1720     }
1721 
1722     void format(const ImportExpression importExpression)
1723     {
1724         debug(verbose) writeln("ImportExpression");
1725 
1726         put("import (");
1727         format(importExpression.assignExpression);
1728         put(");");
1729     }
1730 
1731     void format(const Index index)
1732     {
1733         format(index.low);
1734         if (index.high !is null)
1735         {
1736             put(" .. ");
1737             format(index.high);
1738         }
1739     }
1740 
1741     void format(const IndexExpression indexExpression)
1742     {
1743         debug(verbose) writeln("IndexExpression");
1744 
1745         /**
1746         UnaryExpression unaryExpression;
1747         ArgumentList argumentList;
1748         **/
1749 
1750         with(indexExpression)
1751         {
1752             format(indexExpression.unaryExpression);
1753             put("[");
1754             foreach (i, index; indexes)
1755             {
1756                 if (i != 0)
1757                     put(", ");
1758                 format(index);
1759             }
1760             put("]");
1761         }
1762     }
1763 
1764     void format(const InExpression inExpression)
1765     {
1766         debug(verbose) writeln("InExpression");
1767 
1768         with(inExpression)
1769         {
1770             if (left) format(left);
1771             put(negated ? " !in " : " in ");
1772             if (right) format(right);
1773         }
1774     }
1775 
1776     void format(const InStatement inStatement)
1777     {
1778         debug(verbose) writeln("InStatement");
1779         put("in");
1780         format(inStatement.blockStatement);
1781     }
1782 
1783     void format(const Initialize initialize)
1784     {
1785         debug(verbose) writeln("Initialize");
1786         assert(false);
1787     }
1788 
1789     void format(const Initializer initializer)
1790     {
1791         debug(verbose) writeln("Initializer");
1792 
1793         initializer.nonVoidInitializer ? format(initializer.nonVoidInitializer) : put("void");
1794     }
1795 
1796     void format(const InterfaceDeclaration interfaceDeclaration, const Attribute[] attrs = null)
1797     {
1798         debug(verbose) writeln("InterfaceDeclaration");
1799 
1800         /**
1801         Token name;
1802         TemplateParameters templateParameters;
1803         Constraint constraint;
1804         BaseClassList baseClassList;
1805         StructBody structBody;
1806         string comment;
1807         **/
1808 
1809         with(interfaceDeclaration)
1810         {
1811             newThing(What.aggregateDecl);
1812             putComment(comment);
1813             putAttrs(attrs);
1814 
1815             put("interface ");
1816             format(name);
1817             if (templateParameters) format(templateParameters);
1818             if (constraint)
1819             {
1820                 space();
1821                 format(constraint);
1822             }
1823             if (baseClassList)
1824             {
1825                 format(baseClassList);
1826             }
1827 
1828             if (structBody)
1829                 format(structBody);
1830             else
1831                 put(";");
1832         }
1833     }
1834 
1835     void format(const Invariant invariant_, const Attribute[] attrs = null)
1836     {
1837         debug(verbose) writeln("Invariant");
1838 
1839         /**
1840         BlockStatement blockStatement;
1841         string comment;
1842         **/
1843 
1844         putComment(invariant_.comment);
1845         putAttrs(attrs);
1846         put("invariant()");
1847         format(invariant_.blockStatement);
1848     }
1849 
1850     void format(const IsExpression isExpression)
1851     {
1852         debug(verbose) writeln("IsExpression");
1853 
1854         /**
1855         Type type;
1856         Token identifier;
1857         TypeSpecialization typeSpecialization;
1858         TemplateParameterList templateParameterList;
1859         IdType equalsOrColon;
1860         **/
1861 
1862         with(isExpression)
1863         {
1864             put("is(");
1865             if (type) format(type);
1866             if (identifier != tok!"")
1867             {
1868                 space();
1869                 format(identifier);
1870             }
1871 
1872             if (equalsOrColon)
1873             {
1874                 space();
1875                 put(tokenRep(equalsOrColon));
1876                 space();
1877             }
1878 
1879             if (typeSpecialization) format(typeSpecialization);
1880             if (templateParameterList)
1881             {
1882                 put(", ");
1883                 format(templateParameterList);
1884             }
1885             put(")");
1886         }
1887     }
1888 
1889     void format(const KeyValuePair keyValuePair)
1890     {
1891         debug(verbose) writeln("KeyValuePair");
1892 
1893         /**
1894         AssignExpression key;
1895         AssignExpression value;
1896         **/
1897 
1898         format(keyValuePair.key);
1899         put(":");
1900         format(keyValuePair.value);
1901     }
1902 
1903     void format(const KeyValuePairs keyValuePairs)
1904     {
1905         debug(verbose) writeln("KeyValuePairs");
1906 
1907         /**
1908         KeyValuePair[] keyValuePairs;
1909         **/
1910 
1911         foreach(count, pair; keyValuePairs.keyValuePairs)
1912         {
1913             format(pair);
1914             if (count + 1 < keyValuePairs.keyValuePairs.length)
1915                 put(", ");
1916         }
1917     }
1918 
1919     void format(const LabeledStatement stmt)
1920     {
1921         debug(verbose) writeln("LabeledStatement");
1922 
1923         /**
1924         Token identifier;
1925         DeclarationOrStatement declarationOrStatement;
1926         **/
1927 
1928         format(stmt.identifier);
1929         put(":");
1930         if (stmt.declarationOrStatement)
1931             format(stmt.declarationOrStatement);
1932     }
1933 
1934     void format(const LastCatch lastCatch)
1935     {
1936         debug(verbose) writeln("LastCatch");
1937 
1938         put("catch");
1939         format(lastCatch.statementNoCaseNoDefault);
1940     }
1941 
1942     void format(const LinkageAttribute linkageAttribute)
1943     {
1944         debug(verbose) writeln("LinkageAttribute");
1945 
1946         /**
1947         Token identifier;
1948         bool hasPlusPlus;
1949         IdentifierChain identifierChain;
1950         **/
1951 
1952         put("extern (");
1953         format(linkageAttribute.identifier);
1954         if (linkageAttribute.hasPlusPlus)
1955         {
1956             put("++");
1957             if (linkageAttribute.identifierChain && linkageAttribute.identifierChain.identifiers.length > 0)
1958             {
1959                 put(", ");
1960                 format(linkageAttribute.identifierChain);
1961             }
1962         }
1963         put(")");
1964     }
1965 
1966     void format(const MemberFunctionAttribute memberFunctionAttribute)
1967     {
1968         debug(verbose) writeln("MemberFunctionAttribute");
1969 
1970         /**
1971         IdType tokenType;
1972         AtAttribute atAttribute;
1973         **/
1974 
1975         with(memberFunctionAttribute)
1976         {
1977             if (tokenType) put(tokenRep(tokenType));
1978             else format(atAttribute);
1979         }
1980     }
1981 
1982     void format(const MixinDeclaration mixinDeclaration, const Attribute[] attrs = null)
1983     {
1984         debug(verbose) writeln("MixinDeclaration");
1985 
1986         /**
1987         MixinExpression mixinExpression;
1988         TemplateMixinExpression templateMixinExpression;
1989         **/
1990 
1991         with(mixinDeclaration)
1992         {
1993             putAttrs(attrs);
1994             if (mixinExpression) format(mixinExpression);
1995             else format(templateMixinExpression);
1996             put(";");
1997         }
1998     }
1999 
2000     void format(const MixinExpression mixinExpression)
2001     {
2002         debug(verbose) writeln("MixinExpression");
2003 
2004         put("mixin (");
2005         format(mixinExpression.assignExpression);
2006         put(")");
2007     }
2008 
2009     void format(const MixinTemplateDeclaration mixinTemplateDeclaration, const Attribute[] attrs = null)
2010     {
2011         debug(verbose) writeln("MixinTemplateDeclaration");
2012 
2013         putAttrs(attrs);
2014         put("mixin ");
2015         format(mixinTemplateDeclaration.templateDeclaration);
2016     }
2017 
2018     void format(const MixinTemplateName mixinTemplateName)
2019     {
2020         debug(verbose) writeln("MixinTemplateName");
2021 
2022         /**
2023         Symbol symbol;
2024         IdentifierOrTemplateChain identifierOrTemplateChain;
2025         TypeofExpression typeofExpression;
2026         **/
2027 
2028         with(mixinTemplateName)
2029         {
2030             if (symbol) format(symbol);
2031             else
2032             {
2033                 format(typeofExpression);
2034                 put(".");
2035                 format(identifierOrTemplateChain);
2036             }
2037         }
2038     }
2039 
2040     void format(const Module module_)
2041     {
2042         debug(verbose) writeln("Module");
2043 
2044         /**
2045         ModuleDeclaration moduleDeclaration;
2046         Declaration[] declarations;
2047         **/
2048 
2049         format(module_.moduleDeclaration);
2050         foreach(decl; module_.declarations)
2051             format(decl);
2052     }
2053 
2054     void format(const ModuleDeclaration moduleDeclaration)
2055     {
2056         debug(verbose) writeln("ModuleDeclaration");
2057         if (moduleDeclaration is null) return;
2058 
2059         /**
2060         IdentifierChain moduleName;
2061         **/
2062 
2063         put("module ");
2064         format(moduleDeclaration.moduleName);
2065         put(";");
2066         newlineIndent();
2067         newlineIndent();
2068     }
2069 
2070     void format(const MulExpression mulExpression)
2071     {
2072         debug(verbose) writeln("MulExpression");
2073         mixin(binary("mulExpression"));
2074     }
2075 
2076     void format(const NewAnonClassExpression newAnonClassExpression)
2077     {
2078         debug(verbose) writeln("NewAnonClassExpression");
2079 
2080         /**
2081         Arguments allocatorArguments;
2082         Arguments constructorArguments;
2083         BaseClassList baseClassList;
2084         StructBody structBody;
2085         **/
2086 
2087         with(newAnonClassExpression)
2088         {
2089             if (allocatorArguments)
2090             {
2091                 format(allocatorArguments);
2092                 space();
2093             }
2094             put("class");
2095             if (constructorArguments)
2096                 format(constructorArguments);
2097 
2098             if (baseClassList)
2099             {
2100                 space();
2101                 format(baseClassList);
2102             }
2103 
2104             format(structBody);
2105         }
2106     }
2107 
2108     void format(const NewExpression newExpression)
2109     {
2110         debug(verbose) writeln("NewExpression");
2111 
2112         /**
2113         Type type;
2114         NewAnonClassExpression newAnonClassExpression;
2115         Arguments arguments;
2116         AssignExpression assignExpression;
2117         **/
2118 
2119         with(newExpression)
2120         {
2121             put("new ");
2122             if (newAnonClassExpression) format(newAnonClassExpression);
2123             else
2124             {
2125                 if (type) format(type);
2126                 if (arguments) format(arguments);
2127                 if (assignExpression)
2128                 {
2129                     put("[");
2130                     format(assignExpression);
2131                     put("]");
2132                 }
2133             }
2134         }
2135     }
2136 
2137     void format(const NonVoidInitializer nonVoidInitializer)
2138     {
2139         debug(verbose) writeln("NonVoidInitializer");
2140 
2141         /**
2142         AssignExpression assignExpression;
2143         ArrayInitializer arrayInitializer;
2144         StructInitializer structInitializer;
2145         **/
2146 
2147         with(nonVoidInitializer)
2148         {
2149             if (assignExpression) format(assignExpression);
2150             else if (arrayInitializer) format(arrayInitializer);
2151             else if (structInitializer) format(structInitializer);
2152         }
2153     }
2154 
2155     void format(const Operands operands)
2156     {
2157         debug(verbose) writeln("Operands");
2158         assert(false);
2159     }
2160 
2161     void format(const OrExpression orExpression)
2162     {
2163         debug(verbose) writeln("OrExpression");
2164         mixin(binary("orExpression", "|"));
2165     }
2166 
2167     void format(const OrOrExpression orOrExpression)
2168     {
2169         debug(verbose) writeln("OrOrExpression");
2170         mixin(binary("orOrExpression", "||"));
2171     }
2172 
2173     void format(const OutStatement stmnt)
2174     {
2175         debug(verbose) writeln("OutStatement");
2176 
2177         /**
2178         Token parameter;
2179         BlockStatement blockStatement;
2180         **/
2181 
2182         put("out");
2183         if (stmnt.parameter != tok!"")
2184         {
2185             put(" (");
2186             format(stmnt.parameter);
2187             put(")");
2188         }
2189         format(stmnt.blockStatement);
2190     }
2191 
2192     void format(const Parameter parameter)
2193     {
2194         debug(verbose) writeln("Parameter");
2195 
2196         /**
2197         IdType[] parameterAttributes;
2198         Type type;
2199         Token name;
2200         bool vararg;
2201         AssignExpression default_;
2202         TypeSuffix[] cstyle;
2203         **/
2204 
2205         foreach (count, attribute; parameter.parameterAttributes)
2206         {
2207             if (count) space();
2208             put(tokenRep(attribute));
2209         }
2210 
2211         if (parameter.parameterAttributes.length > 0)
2212             space();
2213 
2214         if (parameter.type !is null)
2215             format(parameter.type);
2216 
2217         if (parameter.name.type != tok!"")
2218         {
2219             space();
2220             put(parameter.name.text);
2221         }
2222 
2223         foreach(suffix; parameter.cstyle)
2224             format(suffix);
2225 
2226         if (parameter.default_)
2227         {
2228             put(" = ");
2229             format(parameter.default_);
2230         }
2231 
2232         if (parameter.vararg)
2233             put("...");
2234     }
2235 
2236     void format(const Parameters parameters)
2237     {
2238         debug(verbose) writeln("Parameters");
2239 
2240         /**
2241         Parameter[] parameters;
2242         bool hasVarargs;
2243         **/
2244 
2245         put("(");
2246         foreach (count, param; parameters.parameters)
2247         {
2248             if (count) put(", ");
2249             format(param);
2250         }
2251         if (parameters.hasVarargs)
2252         {
2253             if (parameters.parameters.length)
2254                 put(", ");
2255             put("...");
2256         }
2257         put(")");
2258     }
2259 
2260     void format(const Postblit postblit, const Attribute[] attrs = null)
2261     {
2262         debug(verbose) writeln("Postblit");
2263 
2264         /**
2265         FunctionBody functionBody;
2266         **/
2267 
2268         newThing(What.functionDecl);
2269         putAttrs(attrs);
2270         put("this(this)");
2271 
2272         foreach(attr; postblit.memberFunctionAttributes)
2273         {
2274             space();
2275             format(attr);
2276         }
2277 
2278         if (postblit.functionBody)
2279             format(postblit.functionBody);
2280         else
2281             put(";");
2282     }
2283 
2284     void format(const PowExpression powExpression)
2285     {
2286         debug(verbose) writeln("PowExpression");
2287         mixin(binary("powExpression", "^^", true));
2288     }
2289 
2290     void format(const PragmaDeclaration pragmaDeclaration, const Attribute[] attrs = null)
2291     {
2292         debug(verbose) writeln("PragmaDeclaration");
2293 
2294         /**
2295         PragmaExpression pragmaExpression;
2296         **/
2297 
2298         putAttrs(attrs);
2299         format(pragmaDeclaration.pragmaExpression);
2300         put(";");
2301     }
2302 
2303     void format(const PragmaExpression pragmaExpression)
2304     {
2305         debug(verbose) writeln("PragmaExpression");
2306 
2307         /**
2308         Token identifier;
2309         ArgumentList argumentList;
2310         **/
2311 
2312         put("pragma(");
2313         format(pragmaExpression.identifier);
2314         if (pragmaExpression.argumentList)
2315         {
2316             put(", ");
2317             format(pragmaExpression.argumentList);
2318         }
2319         put(")");
2320     }
2321 
2322     void format(const PrimaryExpression primaryExpression)
2323     {
2324         debug(verbose) writeln("PrimaryExpression");
2325 
2326         /**
2327         Token dot;
2328         Token primary;
2329         IdentifierOrTemplateInstance identifierOrTemplateInstance;
2330         Token basicType;
2331         TypeofExpression typeofExpression;
2332         TypeidExpression typeidExpression;
2333         ArrayLiteral arrayLiteral;
2334         AssocArrayLiteral assocArrayLiteral;
2335         Expression expression;
2336         IsExpression isExpression;
2337         LambdaExpression lambdaExpression;
2338         FunctionLiteralExpression functionLiteralExpression;
2339         TraitsExpression traitsExpression;
2340         MixinExpression mixinExpression;
2341         ImportExpression importExpression;
2342         Vector vector;
2343         **/
2344 
2345         with(primaryExpression)
2346         {
2347             if (dot != tok!"") put(".");
2348             if (basicType != tok!"") format(basicType);
2349             if (primary != tok!"")
2350             {
2351                 if (basicType != tok!"") put("."); // i.e. : uint.max
2352                 format(primary);
2353             }
2354 
2355             if (expression)
2356             {
2357                 put("(");
2358                 format(expression);
2359                 put(")");
2360             }
2361             else if (identifierOrTemplateInstance)
2362             {
2363                 format(identifierOrTemplateInstance);
2364             }
2365             else if (typeofExpression) format(typeofExpression);
2366             else if (typeidExpression) format(typeidExpression);
2367             else if (arrayLiteral) format(arrayLiteral);
2368             else if (assocArrayLiteral) format(assocArrayLiteral);
2369             else if (isExpression) format(isExpression);
2370             else if (functionLiteralExpression) format(functionLiteralExpression);
2371             else if (traitsExpression) format(traitsExpression);
2372             else if (mixinExpression) format(mixinExpression);
2373             else if (importExpression) format(importExpression);
2374             else if (vector) format(vector);
2375         }
2376     }
2377 
2378     void format(const Register register)
2379     {
2380         debug(verbose) writeln("Register");
2381         assert(false);
2382     }
2383 
2384     void format(const RelExpression relExpression)
2385     {
2386         debug(verbose) writeln("RelExpression");
2387         mixin(binary("relExpression"));
2388     }
2389 
2390     void format(const ReturnStatement returnStatement)
2391     {
2392         debug(verbose) writeln("ReturnStatement");
2393 
2394         put("return");
2395         if (returnStatement.expression)
2396         {
2397             space();
2398             format(returnStatement.expression);
2399         }
2400         put(";");
2401     }
2402 
2403     void format(const ScopeGuardStatement scopeGuardStatement)
2404     {
2405         debug(verbose) writeln("ScopeGuardStatement");
2406 
2407         /**
2408         Token identifier;
2409         StatementNoCaseNoDefault statementNoCaseNoDefault;
2410         **/
2411 
2412         with(scopeGuardStatement)
2413         {
2414             put("scope(");
2415             format(identifier);
2416             put(")");
2417             indent();
2418             format(statementNoCaseNoDefault);
2419             outdent();
2420         }
2421     }
2422 
2423     void format(const SharedStaticConstructor sharedStaticConstructor, const Attribute[] attrs = null)
2424     {
2425         debug(verbose) writeln("SharedStaticConstructor");
2426 
2427         with(sharedStaticConstructor)
2428         {
2429             newThing(What.functionDecl);
2430             putComment(comment);
2431             putAttrs(attrs);
2432             put("shared static this()");
2433             format(functionBody);
2434         }
2435     }
2436 
2437     void format(const SharedStaticDestructor sharedStaticDestructor, const Attribute[] attrs = null)
2438     {
2439         debug(verbose) writeln("SharedStaticDestructor");
2440 
2441         with(sharedStaticDestructor)
2442         {
2443             newThing(What.functionDecl);
2444             putComment(comment);
2445             putAttrs(attrs);
2446             put("shared static ~this()");
2447             format(functionBody);
2448         }
2449     }
2450 
2451     void format(const ShiftExpression shiftExpression)
2452     {
2453         debug(verbose) writeln("ShiftExpression");
2454         mixin(binary("shiftExpression"));
2455     }
2456 
2457     void format(const SingleImport singleImport)
2458     {
2459         debug(verbose) writeln("SingleImport");
2460 
2461         /**
2462         Token rename;
2463         IdentifierChain identifierChain;
2464         **/
2465 
2466         if (singleImport.rename != tok!"")
2467         {
2468             format(singleImport.rename);
2469             put(" = ");
2470         }
2471         format(singleImport.identifierChain);
2472     }
2473 
2474     void format(const Statement statement)
2475     {
2476         debug(verbose) writeln("Statement");
2477 
2478         /**
2479         StatementNoCaseNoDefault statementNoCaseNoDefault;
2480         CaseStatement caseStatement;
2481         CaseRangeStatement caseRangeStatement;
2482         DefaultStatement defaultStatement;
2483         **/
2484 
2485         with(statement)
2486         {
2487             if (statementNoCaseNoDefault)
2488             {
2489                 format(statementNoCaseNoDefault);
2490                 return;
2491             }
2492 
2493             newlineIndent();
2494             if (caseStatement) format(caseStatement);
2495             else if (caseRangeStatement) format(caseRangeStatement);
2496             else if (defaultStatement) format(defaultStatement);
2497         }
2498     }
2499 
2500     void format(const StatementNoCaseNoDefault statementNoCaseNoDefault)
2501     {
2502         debug(verbose) writeln("StatementNoCaseNoDefault");
2503 
2504         string mix(string s) { return "if (" ~ s ~ ") format(" ~ s ~ ");"; }
2505 
2506         with(statementNoCaseNoDefault)
2507         {
2508             if (!blockStatement) newlineIndent();
2509 
2510             enum stmnts = TypeTuple!(
2511                 "labeledStatement",
2512                 "blockStatement",
2513                 "ifStatement",
2514                 "whileStatement",
2515                 "doStatement",
2516                 "forStatement",
2517                 "foreachStatement",
2518                 "switchStatement",
2519                 "finalSwitchStatement",
2520                 "continueStatement",
2521                 "breakStatement",
2522                 "returnStatement",
2523                 "gotoStatement",
2524                 "withStatement",
2525                 "synchronizedStatement",
2526                 "tryStatement",
2527                 "throwStatement",
2528                 "scopeGuardStatement",
2529                 "asmStatement",
2530                 "conditionalStatement",
2531                 "staticAssertStatement",
2532                 "versionSpecification",
2533                 "debugSpecification",
2534                 "expressionStatement"
2535             );
2536 
2537             foreach(s; stmnts)
2538                 mixin(mix(s));
2539         }
2540     }
2541 
2542     void format(const StaticAssertDeclaration staticAssertDeclaration, const Attribute[] attrs = null)
2543     {
2544         debug(verbose) writeln("StaticAssertDeclaration");
2545 
2546         newThing(What.other);
2547         putAttrs(attrs);
2548         format(staticAssertDeclaration.staticAssertStatement);
2549         put(";");
2550     }
2551 
2552     void format(const StaticAssertStatement staticAssertStatement)
2553     {
2554         debug(verbose) writeln("StaticAssertStatement");
2555 
2556         put("static ");
2557         format(staticAssertStatement.assertExpression);
2558     }
2559 
2560     void format(const StaticConstructor staticConstructor, const Attribute[] attrs = null)
2561     {
2562         debug(verbose) writeln("StaticConstructor");
2563 
2564         putAttrs(attrs);
2565         put("static this()");
2566         format(staticConstructor.functionBody);
2567     }
2568 
2569     void format(const StaticDestructor staticDestructor, const Attribute[] attrs = null)
2570     {
2571         debug(verbose) writeln("StaticDestructor");
2572 
2573         putAttrs(attrs);
2574         put("static ~this()");
2575         format(staticDestructor.functionBody);
2576     }
2577 
2578     void format(const StaticIfCondition staticIfCondition)
2579     {
2580         debug(verbose) writeln("StaticIfCondition");
2581 
2582         put("static if (");
2583         format(staticIfCondition.assignExpression);
2584         put(")");
2585     }
2586 
2587     void format(const StorageClass storageClass)
2588     {
2589         debug(verbose) writeln("StorageClass");
2590 
2591         /**
2592         AtAttribute atAttribute;
2593         Deprecated deprecated_;
2594         LinkageAttribute linkageAttribute;
2595         Token token;
2596         **/
2597 
2598         with(storageClass)
2599         {
2600             if (atAttribute) format(atAttribute);
2601             else if (deprecated_) format(deprecated_);
2602             else if (linkageAttribute) format(linkageAttribute);
2603             else format(token);
2604         }
2605     }
2606 
2607     void format(const StructBody structBody)
2608     {
2609         debug(verbose) writeln("StructBody");
2610 
2611         if (structBody.declarations.length > 0)
2612         {
2613             startBlock();
2614             foreach(count, decl; structBody.declarations)
2615                 format(decl);
2616             endBlock();
2617         }
2618         else
2619         {
2620             space();
2621             put("{}");
2622         }
2623     }
2624 
2625     void format(const StructDeclaration decl, const Attribute[] attrs = null)
2626     {
2627         debug(verbose) writeln("StructDeclaration");
2628 
2629         /**
2630         Token name;
2631         TemplateParameters templateParameters;
2632         Constraint constraint;
2633         StructBody structBody;
2634         string comment;
2635         **/
2636 
2637         newThing(What.aggregateDecl);
2638         putComment(decl.comment);
2639         putAttrs(attrs);
2640         put("struct ");
2641         format(decl.name);
2642 
2643         if (decl.templateParameters)
2644             format(decl.templateParameters);
2645 
2646         if (decl.constraint)
2647         {
2648             space();
2649             format(decl.constraint);
2650         }
2651 
2652         if (decl.structBody)
2653             format(decl.structBody);
2654         else
2655             put(";");
2656     }
2657 
2658     void format(const StructInitializer structInitializer)
2659     {
2660         debug(verbose) writeln("StructInitializer");
2661 
2662         put("{");
2663         format(structInitializer.structMemberInitializers);
2664         put("}");
2665     }
2666 
2667     void format(const StructMemberInitializer structMemberInitializer)
2668     {
2669         debug(verbose) writeln("StructMemberInitializer");
2670 
2671         /**
2672         Token identifier;
2673         NonVoidInitializer nonVoidInitializer;
2674         **/
2675 
2676         with(structMemberInitializer)
2677         {
2678             if (identifier != tok!"")
2679             {
2680                 format(identifier);
2681                 put(":");
2682             }
2683             format(nonVoidInitializer);
2684         }
2685     }
2686 
2687     void format(const StructMemberInitializers structMemberInitializers)
2688     {
2689         debug(verbose) writeln("StructMemberInitializers");
2690 
2691         foreach(count, mem; structMemberInitializers.structMemberInitializers)
2692         {
2693             if (count) put(", ");
2694             format(mem);
2695         }
2696     }
2697 
2698     void format(const SwitchStatement switchStatement, bool isFinal = false)
2699     {
2700         debug(verbose) writeln("SwitchStatement");
2701 
2702         /**
2703         Expression expression;
2704         Statement statement;
2705         **/
2706 
2707         with(switchStatement)
2708         {
2709             newThing(What.other);
2710             isFinal ? put(" final switch(") : put("switch(");
2711             format(expression);
2712             put(")");
2713 
2714             bool needBlock = statement.statementNoCaseNoDefault &&
2715                              !(statement.statementNoCaseNoDefault.withStatement ||
2716                                statement.statementNoCaseNoDefault.blockStatement );
2717 
2718             if (needBlock)
2719                 startBlock();
2720             format(statement);
2721             if (needBlock)
2722                 endBlock();
2723         }
2724     }
2725 
2726     void format(const Symbol symbol)
2727     {
2728         debug(verbose) writeln("Symbol");
2729 
2730         if (symbol.dot)
2731             put(".");
2732         format(symbol.identifierOrTemplateChain);
2733     }
2734 
2735     void format(const SynchronizedStatement synchronizedStatement)
2736     {
2737         debug(verbose) writeln("SynchronizedStatement");
2738 
2739         /**
2740         Expression expression;
2741         StatementNoCaseNoDefault statementNoCaseNoDefault;
2742         **/
2743 
2744         with(synchronizedStatement)
2745         {
2746             put("synchronized");
2747             if (expression)
2748             {
2749                 put("(");
2750                 format(expression);
2751                 put(")");
2752             }
2753             format(statementNoCaseNoDefault);
2754         }
2755     }
2756 
2757     void format(const TemplateAliasParameter templateAliasParameter)
2758     {
2759         debug(verbose) writeln("TemplateAliasParameter");
2760 
2761         /**
2762         Type type;
2763         Token identifier;
2764         Type colonType;
2765         AssignExpression colonExpression;
2766         Type assignType;
2767         AssignExpression assignExpression;
2768         **/
2769 
2770         with(templateAliasParameter)
2771         {
2772             put("alias ");
2773             if (type)
2774             {
2775                 format(type);
2776                 space();
2777             }
2778             format(identifier);
2779             if (colonType)
2780             {
2781                 put(" : ");
2782                 format(colonType);
2783             }
2784             else if (colonExpression)
2785             {
2786                 put(" : ");
2787                 format(colonExpression);
2788             }
2789             if (assignType)
2790             {
2791                 put(" = ");
2792                 format(assignType);
2793             }
2794             else if (assignExpression)
2795             {
2796                 put(" = ");
2797                 format(assignExpression);
2798             }
2799         }
2800     }
2801 
2802     void format(const TemplateArgument templateArgument)
2803     {
2804         debug(verbose) writeln("TemplateArgument");
2805 
2806         /**
2807         Type type;
2808         AssignExpression assignExpression;
2809         **/
2810 
2811         with(templateArgument)
2812         {
2813             if (type) format(type);
2814             if (assignExpression) format(assignExpression);
2815         }
2816     }
2817 
2818     void format(const TemplateArgumentList templateArgumentList, bool parens = true)
2819     {
2820         debug(verbose) writeln("TemplateArgumentList");
2821 
2822         if (parens) put("!(");
2823         foreach(count, arg; templateArgumentList.items)
2824         {
2825             if (count) put(", ");
2826             format(arg);
2827         }
2828         if (parens) put(")");
2829     }
2830 
2831     void format(const TemplateArguments templateArguments)
2832     {
2833         debug(verbose) writeln("TemplateArguments");
2834 
2835         /**
2836         TemplateArgumentList templateArgumentList;
2837         TemplateSingleArgument templateSingleArgument;
2838         **/
2839 
2840         with(templateArguments)
2841         {
2842             if (templateArgumentList) format(templateArgumentList);
2843             else if (templateSingleArgument) format(templateSingleArgument);
2844             else put("!()");
2845         }
2846     }
2847 
2848     void format(const TemplateDeclaration templateDeclaration, const Attribute[] attrs = null)
2849     {
2850         debug(verbose) writeln("TemplateDeclaration");
2851 
2852         /**
2853         Token name;
2854         TemplateParameters templateParameters;
2855         Constraint constraint;
2856         Declaration[] declarations;
2857         EponymousTemplateDeclaration eponymousTemplateDeclaration;
2858         string comment;
2859         **/
2860 
2861         with(templateDeclaration)
2862         {
2863             newThing(What.other);
2864             putComment(comment);
2865             putAttrs(attrs);
2866 
2867             put("template ");
2868             format(name);
2869 
2870             if (templateParameters)
2871                 format(templateParameters);
2872 
2873             if (constraint)
2874             {
2875                 space();
2876                 format(constraint);
2877             }
2878 
2879             startBlock();
2880             foreach(d; declarations)
2881                 format(d);
2882             endBlock();
2883         }
2884     }
2885 
2886     void format(const TemplateInstance templateInstance)
2887     {
2888         debug(verbose) writeln("TemplateInstance");
2889 
2890         /**
2891         Token identifier;
2892         TemplateArguments templateArguments;
2893         **/
2894 
2895         with(templateInstance)
2896         {
2897             format(identifier);
2898             if (templateArguments) format(templateArguments);
2899         }
2900     }
2901 
2902     void format(const TemplateMixinExpression templateMixinExpression)
2903     {
2904         debug(verbose) writeln("TemplateMixinExpression");
2905 
2906         /**
2907         Token identifier;
2908         TemplateArguments templateArguments;
2909         MixinTemplateName mixinTemplateName;
2910         **/
2911 
2912         with(templateMixinExpression)
2913         {
2914             put("mixin ");
2915             format(mixinTemplateName);
2916             if (templateArguments) format(templateArguments);
2917             space();
2918             format(identifier);
2919         }
2920     }
2921 
2922     void format(const TemplateParameter templateParameter)
2923     {
2924         debug(verbose) writeln("TemplateParameter");
2925 
2926         with(templateParameter)
2927         {
2928             if (templateTypeParameter)
2929                 format(templateTypeParameter);
2930             else if (templateValueParameter)
2931                 format(templateValueParameter);
2932             else if (templateAliasParameter)
2933                 format(templateAliasParameter);
2934             else if (templateTupleParameter)
2935                 format(templateTupleParameter);
2936             else if (templateThisParameter)
2937                 format(templateThisParameter);
2938         }
2939     }
2940 
2941     void format(const TemplateParameterList templateParameterList)
2942     {
2943         debug(verbose) writeln("TemplateParameterList");
2944 
2945         foreach(i, param; templateParameterList.items)
2946         {
2947             if (i) put(", ");
2948             format(param);
2949         }
2950     }
2951 
2952     void format(const TemplateParameters templateParameters)
2953     {
2954         debug(verbose) writeln("TemplateParameters");
2955 
2956         with(templateParameters)
2957         {
2958             put("(");
2959             if (templateParameterList)
2960                 format(templateParameterList);
2961             put(")");
2962         }
2963     }
2964 
2965     void format(const TemplateSingleArgument templateSingleArgument)
2966     {
2967         debug(verbose) writeln("TemplateSingleArgument");
2968 
2969         /**
2970         Token token;
2971         **/
2972 
2973         put("!");
2974         format(templateSingleArgument.token);
2975     }
2976 
2977     void format(const TemplateThisParameter templateThisParameter)
2978     {
2979         debug(verbose) writeln("TemplateThisParameter");
2980 
2981         with(templateThisParameter)
2982         {
2983             put("this ");
2984             if (templateTypeParameter)
2985                 format(templateTypeParameter);
2986         }
2987     }
2988 
2989     void format(const TemplateTupleParameter templateTupleParameter)
2990     {
2991         debug(verbose) writeln("TemplateTupleParameter");
2992 
2993         format(templateTupleParameter.identifier);
2994         put("...");
2995     }
2996 
2997     void format(const TemplateTypeParameter templateTypeParameter)
2998     {
2999         debug(verbose) writeln("TemplateTypeParameter");
3000 
3001         /**
3002         Token identifier;
3003         Type colonType;
3004         Type assignType;
3005         **/
3006 
3007         with(templateTypeParameter)
3008         {
3009             format(identifier);
3010             if (colonType)
3011             {
3012                 put(" : ");
3013                 format(colonType);
3014             }
3015             if (assignType)
3016             {
3017                 put(" = ");
3018                 format(assignType);
3019             }
3020         }
3021     }
3022 
3023     void format(const TemplateValueParameter templateValueParameter)
3024     {
3025         debug(verbose) writeln("TemplateValueParameter");
3026 
3027         /**
3028         Type type;
3029         Token identifier;
3030         Expression expression;
3031         TemplateValueParameterDefault templateValueParameterDefault;
3032         **/
3033 
3034         with(templateValueParameter)
3035         {
3036             if (type) format(type);
3037             space();
3038             format(identifier);
3039 
3040             if (assignExpression)
3041             {
3042                 put(" : ");
3043                 format(assignExpression);
3044             }
3045 
3046             if (templateValueParameterDefault)
3047             {
3048                 put(" = ");
3049                 format(templateValueParameterDefault);
3050             }
3051         }
3052     }
3053 
3054     void format(const TemplateValueParameterDefault templateValueParameterDefault)
3055     {
3056         debug(verbose) writeln("TemplateValueParameterDefault");
3057 
3058         with(templateValueParameterDefault)
3059             assignExpression ? format(assignExpression) : format(token);
3060     }
3061 
3062     void format(const TernaryExpression expr)
3063     {
3064         debug(verbose) writeln("TernaryExpression");
3065 
3066         /**
3067         ExpressionNode orOrExpression;
3068         ExpressionNode expression;
3069         ExpressionNode ternaryExpression;
3070         **/
3071 
3072         format(expr.orOrExpression);
3073 
3074         if (expr.expression && expr.ternaryExpression)
3075         {
3076             put(" ? ");
3077             format(expr.expression);
3078             put(" : ");
3079             format(expr.ternaryExpression);
3080         }
3081     }
3082 
3083     void format(const ThrowStatement throwStatement)
3084     {
3085         debug(verbose) writeln("ThrowStatement");
3086 
3087         put("throw ");
3088         assert(throwStatement.expression);
3089         format(throwStatement.expression);
3090         put(";");
3091     }
3092 
3093     void format(const Token token)
3094     {
3095         debug(verbose) writeln("Token ", tokenRep(token));
3096         put(tokenRep(token));
3097     }
3098 
3099     void format(const TraitsExpression traitExpr)
3100     {
3101         debug(verbose) writeln("TraitsExpression");
3102 
3103         /**
3104         Token identifier;
3105         TemplateArgumentList templateArgumentList;
3106         **/
3107 
3108         put("__traits(");
3109         format(traitExpr.identifier);
3110         put(", ");
3111         format(traitExpr.templateArgumentList, false);
3112         put(")");
3113     }
3114 
3115     void format(const TryStatement tryStatement)
3116     {
3117         debug(verbose) writeln("TryStatement");
3118 
3119         /**
3120         DeclarationOrStatement declarationOrStatement;
3121         Catches catches;
3122         Finally finally_;
3123         **/
3124 
3125         with(tryStatement)
3126         {
3127             newThing(What.other);
3128             put("try");
3129             maybeIndent(declarationOrStatement);
3130             if (catches) format(catches);
3131             if (finally_) format(finally_);
3132         }
3133     }
3134 
3135     void format(const Type type)
3136     {
3137         debug(verbose) writeln("Type(");
3138 
3139         /**
3140         IdType[] typeConstructors;
3141         TypeSuffix[] typeSuffixes;
3142         Type2 type2;
3143         **/
3144 
3145         foreach (count, constructor; type.typeConstructors)
3146         {
3147             if (count) space();
3148             put(tokenRep(constructor));
3149         }
3150 
3151         if (type.typeConstructors.length) space();
3152         format(type.type2);
3153 
3154         foreach (suffix; type.typeSuffixes)
3155             format(suffix);
3156 
3157         debug(verbose) writeln(")");
3158     }
3159 
3160     void format(const Type2 type2)
3161     {
3162         debug(verbose) writeln("Type2");
3163 
3164         /**
3165         IdType builtinType;
3166         Symbol symbol;
3167         TypeofExpression typeofExpression;
3168         IdentifierOrTemplateChain identifierOrTemplateChain;
3169         IdType typeConstructor;
3170         Type type;
3171         **/
3172 
3173         if (type2.symbol !is null)
3174         {
3175             format(type2.symbol);
3176         }
3177         else if (type2.typeofExpression !is null)
3178         {
3179             format(type2.typeofExpression);
3180             if (type2.identifierOrTemplateChain)
3181             {
3182                 put(".");
3183                 format(type2.identifierOrTemplateChain);
3184             }
3185             return;
3186         }
3187         else if (type2.typeConstructor != tok!"")
3188         {
3189             put(tokenRep(type2.typeConstructor));
3190             put("(");
3191             format(type2.type);
3192             put(")");
3193         }
3194         else
3195         {
3196             put(tokenRep(type2.builtinType));
3197             if (type2.identifierOrTemplateChain !is null)
3198             {
3199                 put(".");
3200                 format(type2.identifierOrTemplateChain);
3201             }
3202         }
3203     }
3204 
3205     void format(const TypeSpecialization typeSpecialization)
3206     {
3207         debug(verbose) writeln("TypeSpecialization");
3208 
3209         /**
3210         Token token;
3211         Type type;
3212         **/
3213 
3214         with(typeSpecialization)
3215         {
3216             format(token);
3217             if (type) format(type);
3218         }
3219     }
3220 
3221     void format(const TypeSuffix typeSuffix)
3222     {
3223         debug(verbose) writeln("TypeSuffix");
3224 
3225         /**
3226         Token delegateOrFunction;
3227         bool star;
3228         bool array;
3229         Type type;
3230         AssignExpression low;
3231         AssignExpression high;
3232         Parameters parameters;
3233         MemberFunctionAttribute[] memberFunctionAttributes;
3234         **/
3235 
3236         if (typeSuffix.star.type != tok!"")
3237         {
3238             put("*");
3239             return;
3240         }
3241         else if (typeSuffix.array)
3242         {
3243             if (typeSuffix.type is null)
3244             {
3245                 if (typeSuffix.low is null)
3246                 {
3247                     put("[]");
3248                     return;
3249                 }
3250                 else
3251                 {
3252                     if (typeSuffix.high is null)
3253                     {
3254                         put("[");
3255                         format(typeSuffix.low);
3256                         put("]");
3257                         return;
3258                     }
3259                     else
3260                     {
3261                         put("[");
3262                         format(typeSuffix.low);
3263                         put("..");
3264                         format(typeSuffix.high);
3265                         put("]");
3266                         return;
3267                     }
3268                 }
3269             }
3270             else
3271             {
3272                 put("[");
3273                 format(typeSuffix.type);
3274                 put("]");
3275                 return;
3276             }
3277         }
3278         else
3279         {
3280             space();
3281             format(typeSuffix.delegateOrFunction);
3282             if (typeSuffix.parameters) format(typeSuffix.parameters);
3283             foreach(attr; typeSuffix.memberFunctionAttributes)
3284             {
3285                 space();
3286                 format(attr);
3287             }
3288             return;
3289         }
3290     }
3291 
3292     void format(const TypeidExpression idExpr)
3293     {
3294         debug(verbose) writeln("TypeidExpression");
3295 
3296         /**
3297         Type type;
3298         Expression expression;
3299         **/
3300 
3301         put("typeid (");
3302         idExpr.type ? format(idExpr.type) : format(idExpr.expression);
3303         put(")");
3304     }
3305 
3306     void format(const TypeofExpression typeofExpr)
3307     {
3308         debug(verbose) writeln("TypeofExpression");
3309 
3310         /**
3311         Expression expression;
3312         Token return_;
3313         **/
3314 
3315         put("typeof(");
3316         typeofExpr.expression ? format(typeofExpr.expression) : format(typeofExpr.return_);
3317         put(")");
3318     }
3319 
3320     void format(const UnaryExpression unary)
3321     {
3322         debug(verbose) writeln("UnaryExpression(");
3323 
3324         /**
3325         Type type;
3326         PrimaryExpression primaryExpression;
3327         Token prefix;
3328         Token suffix;
3329         UnaryExpression unaryExpression;
3330         NewExpression newExpression;
3331         DeleteExpression deleteExpression;
3332         CastExpression castExpression;
3333         FunctionCallExpression functionCallExpression;
3334         ArgumentList argumentList;
3335         IdentifierOrTemplateInstance identifierOrTemplateInstance;
3336         AssertExpression assertExpression;
3337         SliceExpression sliceExpression;
3338         IndexExpression indexExpression;
3339         **/
3340 
3341         with(unary)
3342         {
3343             if (prefix != tok!"") format(prefix);
3344 
3345             if (type)
3346             {
3347                 // handle things like (void*).sizeof
3348                 if (identifierOrTemplateInstance)
3349                 {
3350                     put("(");
3351                     format(type);
3352                     put(")");
3353                 }
3354                 else
3355                 {
3356                     format(type);
3357                     put("(");
3358                     if (argumentList)
3359                         format(argumentList);
3360                     put(")");
3361                 }
3362             }
3363 
3364             if (primaryExpression) format(primaryExpression);
3365             if (newExpression) format(newExpression);
3366             if (deleteExpression) format(deleteExpression);
3367             if (castExpression) format(castExpression);
3368             if (functionCallExpression) format(functionCallExpression);
3369             if (assertExpression) format(assertExpression);
3370             if (indexExpression) format(indexExpression);
3371 
3372             if (unaryExpression) format(unaryExpression);
3373             if (suffix != tok!"") format(suffix);
3374 
3375             if (identifierOrTemplateInstance)
3376             {
3377                 put(".");
3378                 format(identifierOrTemplateInstance);
3379             }
3380         }
3381 
3382         debug(verbose) writeln(")");
3383     }
3384 
3385     void format(const UnionDeclaration decl, const Attribute[] attrs = null)
3386     {
3387         debug(verbose) writeln("UnionDeclaration");
3388 
3389         /**
3390         Token name;
3391         TemplateParameters templateParameters;
3392         Constraint constraint;
3393         StructBody structBody;
3394         string comment;
3395         **/
3396 
3397         newThing(What.aggregateDecl);
3398         putComment(decl.comment);
3399         putAttrs(attrs);
3400         put("union ");
3401         format(decl.name);
3402         if (decl.templateParameters)
3403             format(decl.templateParameters);
3404         if (decl.constraint)
3405         {
3406             space();
3407             format(decl.constraint);
3408         }
3409         format(decl.structBody);
3410     }
3411 
3412     void format(const Unittest unittest_, const Attribute[] attrs = null)
3413     {
3414         debug(verbose) writeln("Unittest");
3415 
3416         /**
3417         BlockStatement blockStatement;
3418         string comment;
3419         **/
3420 
3421         newThing(What.functionDecl);
3422         putComment(unittest_.comment);
3423         putAttrs(attrs);
3424         put("unittest");
3425         format(unittest_.blockStatement);
3426     }
3427 
3428     void format(const VariableDeclaration decl, const Attribute[] attrs = null)
3429     {
3430         debug(verbose) writeln("VariableDeclaration");
3431 
3432         /**
3433         Type type;
3434         Declarator[] declarators;
3435         StorageClass storageClass;
3436         AutoDeclaration autoDeclaration;
3437         string comment;
3438         **/
3439 
3440         newThing(What.variableDecl);
3441         putComment(decl.comment);
3442         putAttrs(attrs);
3443 
3444         if (decl.autoDeclaration)
3445             format(decl.autoDeclaration);
3446         else
3447         {
3448             foreach (c; decl.storageClasses)
3449             {
3450                 format(c);
3451                 space();
3452             }
3453             if (decl.type) format(decl.type);
3454             if (decl.declarators.length) space();
3455             foreach(count, d; decl.declarators)
3456             {
3457                 if (count) put(", ");
3458                 format(d);
3459             }
3460         }
3461         put(";");
3462     }
3463 
3464     void format(const Vector vector)
3465     {
3466         debug(verbose) writeln("Vector");
3467 
3468         put("__vector(");
3469         format(vector.type);
3470         put(")");
3471     }
3472 
3473     void format(const VersionCondition versionCondition)
3474     {
3475         debug(verbose) writeln("VersionCondition");
3476 
3477         put("version (");
3478         format(versionCondition.token);
3479         put(")");
3480     }
3481 
3482     void format(const VersionSpecification ver, const Attribute[] attrs = null)
3483     {
3484         debug(verbose) writeln("VersionSpecification");
3485 
3486         newThing(What.other);
3487         putAttrs(attrs);
3488         put("version = ");
3489         format(ver.token);
3490         put(";");
3491     }
3492 
3493     void format(const WhileStatement stmt)
3494     {
3495         debug(verbose) writeln("WhileStatement");
3496 
3497         /**
3498         Expression expression;
3499         DeclarationOrStatement declarationOrStatement;
3500         **/
3501 
3502         newThing(What.other);
3503         put("while (");
3504         format(stmt.expression);
3505         put(")");
3506         maybeIndent(stmt.declarationOrStatement);
3507     }
3508 
3509     void format(const WithStatement stmt)
3510     {
3511         debug(verbose) writeln("WithStatement");
3512 
3513         /**
3514         Expression expression;
3515         StatementNoCaseNoDefault statementNoCaseNoDefault;
3516         **/
3517 
3518         space();
3519         put("with (");
3520         format(stmt.expression);
3521         put(")");
3522         format(stmt.statementNoCaseNoDefault);
3523     }
3524 
3525     void format(const XorExpression xorExpression)
3526     {
3527         debug(verbose) writeln("XorExpression");
3528         mixin(binary("xorExpression", "^"));
3529     }
3530 
3531     Sink sink;
3532 
3533 protected:
3534 
3535     import std.uni : isWhite;
3536 
3537     void indent()
3538     {
3539         indentLevel++;
3540     }
3541 
3542     void outdent()
3543     {
3544         if (indentLevel == 0)
3545             return;
3546         indentLevel--;
3547     }
3548 
3549     void putIndent()
3550     {
3551         if (!indentLevel) return;
3552         auto i = getIndent();
3553         put(i);
3554     }
3555 
3556     string getIndent()
3557     {
3558         if (useTabs)
3559         {
3560             char[] c = new char[indentLevel];
3561             c[] = '\t';
3562             return cast(string) c;
3563         }
3564         else
3565         {
3566             char[] c = new char[indentLevel * indentWidth];
3567             c[] = ' ';
3568             return cast(string) c;
3569         }
3570     }
3571 
3572     enum What
3573     {
3574         functionDecl,
3575         aggregateDecl,
3576         attributeDecl,
3577         conditionalDecl,
3578         variableDecl,
3579         importDecl,
3580         expr,
3581         loop,
3582         else_,
3583         catch_,
3584         other
3585     }
3586 
3587     void newThing(What thing)
3588     {
3589         lastThing = currentThing;
3590         currentThing = thing;
3591 
3592         with(What) {
3593 
3594             if (lastThing == importDecl && thing != importDecl)
3595             {
3596                 lineGap(1);
3597                 return;
3598             }
3599 
3600             if (lastThing == loop)
3601             {
3602                 lineGap(1);
3603                 return;
3604             }
3605 
3606             switch(thing)
3607             {
3608                 case other:
3609                     newline();
3610                     break;
3611                 case aggregateDecl:
3612                 case attributeDecl:
3613                 case functionDecl:
3614                     lineGap(1);
3615                     break;
3616                 case conditionalDecl:
3617                     lineGap(1);
3618                     break;
3619                 case variableDecl:
3620                     lineGap(1);
3621                     break;
3622                 case importDecl:
3623                     newlineIndent();
3624                     break;
3625                 case expr: break;
3626                 case catch_: goto case;
3627                 case else_:
3628                     final switch(style) with(IndentStyle)
3629                     {
3630                         case allman: newline(); break;
3631                         case otbs: space(); break;
3632                     }
3633                     break;
3634                 default: newlineIndent(); break;
3635             }
3636         }
3637     }
3638 
3639     void lineGap(int gap)
3640     {
3641         foreach (i; 0 .. gap + 1)
3642         {
3643             if (i == gap)
3644                 newlineIndent();
3645             else
3646                 newline();
3647         }
3648     }
3649 
3650     void newlineIndent()
3651     {
3652         if (ignoreNewlines)
3653         {
3654             space(); // don't do this when splitting lines
3655         }
3656         else
3657         {
3658             sink.put("\n");
3659             lineLength = 0;
3660             putIndent();
3661         }
3662     }
3663 
3664     void newline()
3665     {
3666         sink.put("\n");
3667         lineLength = 0;
3668     }
3669 
3670     void space()
3671     {
3672         put(" ");
3673     }
3674 
3675     static string binary(string symbol, string operator = null, bool nospace = false)
3676     {
3677         return "with(" ~ symbol ~ "){"
3678              ~ "format(left); if (right is null) return;"
3679              ~ (nospace ? "" : "put(` `);")
3680              ~ (operator ? "put(`" ~ operator ~ "`);" : "put(tokenRep(operator));")
3681              ~ (nospace ? "" : "put(` `);")
3682              ~ "format(right);}";
3683     }
3684 
3685     void startBlock()
3686     {
3687         final switch(style) with(IndentStyle)
3688         {
3689             case allman: newline(); break;
3690             case otbs: space(); break;
3691         }
3692         putIndent();
3693         put("{");
3694         indent();
3695     }
3696 
3697     void endBlock()
3698     {
3699         outdent();
3700         newline();
3701         putIndent();
3702         put("}");
3703     }
3704 
3705     string tokenRep(Token t)
3706     {
3707         return t.text.length ? t.text : tokenRep(t.type);
3708     }
3709 
3710     string tokenRep(IdType t)
3711     {
3712         return t ? str(t) : "";
3713     }
3714 
3715     void putComment(string c)
3716     {
3717         import std.string : splitLines;
3718         if (!c.length) return;
3719         put(c.splitLines().join("\n" ~ getIndent()));
3720         newlineIndent();
3721     }
3722 
3723     void putAttrs(const Attribute[] attrs)
3724     {
3725         if (attrs !is null)
3726         {
3727             foreach(count, attr; attrs)
3728             {
3729                 format(attr);
3730                 space();
3731             }
3732         }
3733     }
3734 
3735     void put(string s)
3736     {
3737         sink.put(s);
3738         lineLength += s.length; // TODO: tabs / spaces?
3739     }
3740 
3741     void formatCaseDecls(const DeclarationsAndStatements declsAndStmnts)
3742     {
3743         bool seenBlock = false;
3744         auto items = declsAndStmnts.declarationsAndStatements;
3745         foreach(item; items)
3746         {
3747             bool _indent = false;
3748             if (item.declaration) _indent = true;
3749             if (item.statement && item.statement.statementNoCaseNoDefault)
3750             {
3751                 if (item.statement.statementNoCaseNoDefault.blockStatement)
3752                     seenBlock = true;
3753                 else if (!item.statement.statementNoCaseNoDefault.labeledStatement)
3754                     _indent = true;
3755             }
3756             if (seenBlock) _indent = false;
3757             if (_indent) indent();
3758             format(item);
3759             if (_indent) outdent();
3760         }
3761     }
3762 
3763     bool needIndent(const Statement s)
3764     {
3765         return s.statementNoCaseNoDefault &&
3766                !s.statementNoCaseNoDefault.blockStatement;
3767     }
3768 
3769     bool needIndent(const Declaration d)
3770     {
3771         return !d.declarations.length;
3772     }
3773 
3774     bool needIndent(const DeclarationOrStatement dors)
3775     {
3776         return (dors.declaration && needIndent(dors.declaration)) ||
3777                (dors.statement && needIndent(dors.statement));
3778     }
3779 
3780     void maybeIndent(T)(const T t)
3781     {
3782         auto _indent = needIndent(t);
3783         if (_indent) indent();
3784         format(t);
3785         if (_indent) outdent();
3786     }
3787 
3788     bool isEmptyDeclaration(const Declaration decl)
3789     {
3790         with(decl)
3791         {
3792             string mix(string[] s) {
3793                 string r;
3794                 foreach(c, d; s)
3795                     r ~= (c > 0 ? "else " : "") ~ "if (" ~ d ~ ") return false;";
3796                 return r;
3797             }
3798             mixin(mix(possibleDeclarations));
3799             return attributes.length == 0 &&
3800                    declarations.length == 0;
3801         }
3802     }
3803 
3804     bool ignoreNewlines = false;
3805     bool useTabs;
3806     uint caseDepth;
3807     uint indentWidth;
3808     uint indentLevel;
3809     IndentStyle style;
3810 
3811 
3812     What lastThing, currentThing;
3813     uint lineLength;
3814     uint maxLineLength = 80;
3815 
3816     enum possibleDeclarations = [
3817         "attributeDeclaration",
3818         "importDeclaration",
3819         "functionDeclaration",
3820         "variableDeclaration",
3821         "aliasThisDeclaration",
3822         "structDeclaration",
3823         "classDeclaration",
3824         "interfaceDeclaration",
3825         "unionDeclaration",
3826         "enumDeclaration",
3827         "aliasDeclaration",
3828         "mixinDeclaration",
3829         "mixinTemplateDeclaration",
3830         "unittest_",
3831         "staticAssertDeclaration",
3832         "templateDeclaration",
3833         "constructor",
3834         "destructor",
3835         "staticConstructor",
3836         "staticDestructor",
3837         "sharedStaticDestructor",
3838         "sharedStaticConstructor",
3839         "conditionalDeclaration",
3840         "pragmaDeclaration",
3841         "versionSpecification",
3842         "invariant_",
3843         "postblit"
3844     ];
3845 }