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