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