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 SingleImport singleImport)
2657     {
2658         debug(verbose) writeln("SingleImport");
2659 
2660         /**
2661         Token rename;
2662         IdentifierChain identifierChain;
2663         **/
2664 
2665         if (singleImport.rename != tok!"")
2666         {
2667             format(singleImport.rename);
2668             put(" = ");
2669         }
2670         format(singleImport.identifierChain);
2671     }
2672 
2673     void format(const SpecifiedFunctionBody specifiedFunctionBody)
2674     {
2675         debug(verbose) writeln("SpecifiedFunctionBody");
2676 
2677         with(specifiedFunctionBody)
2678         {
2679             foreach (contract; functionContracts)
2680                 format(contract);
2681             if (specifiedFunctionBody.hasDo)
2682             {
2683                 newlineIndent();
2684                 put("do");
2685             }
2686             if (blockStatement)
2687                 format(blockStatement);
2688         }
2689     }
2690 
2691     void format(const Statement statement)
2692     {
2693         debug(verbose) writeln("Statement");
2694 
2695         /**
2696         StatementNoCaseNoDefault statementNoCaseNoDefault;
2697         CaseStatement caseStatement;
2698         CaseRangeStatement caseRangeStatement;
2699         DefaultStatement defaultStatement;
2700         **/
2701 
2702         with(statement)
2703         {
2704             if (statementNoCaseNoDefault)
2705             {
2706                 format(statementNoCaseNoDefault);
2707                 return;
2708             }
2709 
2710             newlineIndent();
2711             if (caseStatement) format(caseStatement);
2712             else if (caseRangeStatement) format(caseRangeStatement);
2713             else if (defaultStatement) format(defaultStatement);
2714         }
2715     }
2716 
2717     void format(const StatementNoCaseNoDefault statementNoCaseNoDefault)
2718     {
2719         debug(verbose) writeln("StatementNoCaseNoDefault");
2720 
2721         string mix(string s) { return "if (" ~ s ~ ") format(" ~ s ~ ");"; }
2722 
2723         with(statementNoCaseNoDefault)
2724         {
2725             if (!blockStatement) newlineIndent();
2726 
2727             enum stmnts = TypeTuple!(
2728                 "labeledStatement",
2729                 "blockStatement",
2730                 "ifStatement",
2731                 "whileStatement",
2732                 "doStatement",
2733                 "forStatement",
2734                 "foreachStatement",
2735                 "switchStatement",
2736                 "finalSwitchStatement",
2737                 "continueStatement",
2738                 "breakStatement",
2739                 "returnStatement",
2740                 "gotoStatement",
2741                 "withStatement",
2742                 "synchronizedStatement",
2743                 "tryStatement",
2744                 "throwStatement",
2745                 "scopeGuardStatement",
2746                 "asmStatement",
2747                 "conditionalStatement",
2748                 "staticAssertStatement",
2749                 "versionSpecification",
2750                 "debugSpecification",
2751                 "expressionStatement"
2752             );
2753 
2754             foreach(s; stmnts)
2755                 mixin(mix(s));
2756         }
2757     }
2758 
2759     void format(const StaticAssertDeclaration staticAssertDeclaration, const Attribute[] attrs = null)
2760     {
2761         debug(verbose) writeln("StaticAssertDeclaration");
2762 
2763         newThing(What.other);
2764         putAttrs(attrs);
2765         format(staticAssertDeclaration.staticAssertStatement);
2766         put(";");
2767     }
2768 
2769     void format(const StaticAssertStatement staticAssertStatement)
2770     {
2771         debug(verbose) writeln("StaticAssertStatement");
2772 
2773         put("static ");
2774         format(staticAssertStatement.assertExpression);
2775     }
2776 
2777     void format(const StaticConstructor staticConstructor, const Attribute[] attrs = null)
2778     {
2779         debug(verbose) writeln("StaticConstructor");
2780 
2781         putAttrs(attrs);
2782         put("static this()");
2783         format(staticConstructor.functionBody);
2784     }
2785 
2786     void format(const StaticDestructor staticDestructor, const Attribute[] attrs = null)
2787     {
2788         debug(verbose) writeln("StaticDestructor");
2789 
2790         putAttrs(attrs);
2791         put("static ~this()");
2792         format(staticDestructor.functionBody);
2793     }
2794 
2795     void format(const StaticIfCondition staticIfCondition)
2796     {
2797         debug(verbose) writeln("StaticIfCondition");
2798 
2799         put("static if (");
2800         format(staticIfCondition.assignExpression);
2801         put(")");
2802     }
2803 
2804     void format(const StorageClass storageClass)
2805     {
2806         debug(verbose) writeln("StorageClass");
2807 
2808         /**
2809         AtAttribute atAttribute;
2810         Deprecated deprecated_;
2811         LinkageAttribute linkageAttribute;
2812         Token token;
2813         **/
2814 
2815         with(storageClass)
2816         {
2817             if (atAttribute) format(atAttribute);
2818             else if (deprecated_) format(deprecated_);
2819             else if (linkageAttribute) format(linkageAttribute);
2820             else format(token);
2821         }
2822     }
2823 
2824     void format(const StructBody structBody)
2825     {
2826         debug(verbose) writeln("StructBody");
2827 
2828         if (structBody.declarations.length > 0)
2829         {
2830             startBlock();
2831             foreach(count, decl; structBody.declarations)
2832                 format(decl);
2833             endBlock();
2834         }
2835         else
2836         {
2837             space();
2838             put("{}");
2839         }
2840     }
2841 
2842     void format(const StructDeclaration decl, const Attribute[] attrs = null)
2843     {
2844         debug(verbose) writeln("StructDeclaration");
2845 
2846         /**
2847         Token name;
2848         TemplateParameters templateParameters;
2849         Constraint constraint;
2850         StructBody structBody;
2851         string comment;
2852         **/
2853 
2854         newThing(What.aggregateDecl);
2855         putComment(decl.comment);
2856         putAttrs(attrs);
2857         put("struct ");
2858         format(decl.name);
2859 
2860         if (decl.templateParameters)
2861             format(decl.templateParameters);
2862 
2863         if (decl.constraint)
2864         {
2865             space();
2866             format(decl.constraint);
2867         }
2868 
2869         if (decl.structBody)
2870             format(decl.structBody);
2871         else
2872             put(";");
2873     }
2874 
2875     void format(const StructInitializer structInitializer)
2876     {
2877         debug(verbose) writeln("StructInitializer");
2878 
2879         put("{");
2880         format(structInitializer.structMemberInitializers);
2881         put("}");
2882     }
2883 
2884     void format(const StructMemberInitializer structMemberInitializer)
2885     {
2886         debug(verbose) writeln("StructMemberInitializer");
2887 
2888         /**
2889         Token identifier;
2890         NonVoidInitializer nonVoidInitializer;
2891         **/
2892 
2893         with(structMemberInitializer)
2894         {
2895             if (identifier != tok!"")
2896             {
2897                 format(identifier);
2898                 put(":");
2899             }
2900             format(nonVoidInitializer);
2901         }
2902     }
2903 
2904     void format(const StructMemberInitializers structMemberInitializers)
2905     {
2906         debug(verbose) writeln("StructMemberInitializers");
2907 
2908         foreach(count, mem; structMemberInitializers.structMemberInitializers)
2909         {
2910             if (count) put(", ");
2911             format(mem);
2912         }
2913     }
2914 
2915     void format(const SwitchStatement switchStatement, bool isFinal = false)
2916     {
2917         debug(verbose) writeln("SwitchStatement");
2918 
2919         /**
2920         Expression expression;
2921         Statement statement;
2922         **/
2923 
2924         with(switchStatement)
2925         {
2926             newThing(What.other);
2927             isFinal ? put(" final switch(") : put("switch(");
2928             format(expression);
2929             put(")");
2930 
2931             bool needBlock = statement.statementNoCaseNoDefault &&
2932                              !(statement.statementNoCaseNoDefault.withStatement ||
2933                                statement.statementNoCaseNoDefault.blockStatement );
2934 
2935             if (needBlock)
2936                 startBlock();
2937             format(statement);
2938             if (needBlock)
2939                 endBlock();
2940         }
2941     }
2942 
2943     void format(const Symbol symbol)
2944     {
2945         debug(verbose) writeln("Symbol");
2946 
2947         if (symbol.dot)
2948             put(".");
2949         format(symbol.identifierOrTemplateChain);
2950     }
2951 
2952     void format(const SynchronizedStatement synchronizedStatement)
2953     {
2954         debug(verbose) writeln("SynchronizedStatement");
2955 
2956         /**
2957         Expression expression;
2958         StatementNoCaseNoDefault statementNoCaseNoDefault;
2959         **/
2960 
2961         with(synchronizedStatement)
2962         {
2963             put("synchronized");
2964             if (expression)
2965             {
2966                 put("(");
2967                 format(expression);
2968                 put(")");
2969             }
2970             format(statementNoCaseNoDefault);
2971         }
2972     }
2973 
2974     void format(const TemplateAliasParameter templateAliasParameter)
2975     {
2976         debug(verbose) writeln("TemplateAliasParameter");
2977 
2978         /**
2979         Type type;
2980         Token identifier;
2981         Type colonType;
2982         AssignExpression colonExpression;
2983         Type assignType;
2984         AssignExpression assignExpression;
2985         **/
2986 
2987         with(templateAliasParameter)
2988         {
2989             put("alias ");
2990             if (type)
2991             {
2992                 format(type);
2993                 space();
2994             }
2995             format(identifier);
2996             if (colonType)
2997             {
2998                 put(" : ");
2999                 format(colonType);
3000             }
3001             else if (colonExpression)
3002             {
3003                 put(" : ");
3004                 format(colonExpression);
3005             }
3006             if (assignType)
3007             {
3008                 put(" = ");
3009                 format(assignType);
3010             }
3011             else if (assignExpression)
3012             {
3013                 put(" = ");
3014                 format(assignExpression);
3015             }
3016         }
3017     }
3018 
3019     void format(const TemplateArgument templateArgument)
3020     {
3021         debug(verbose) writeln("TemplateArgument");
3022 
3023         /**
3024         Type type;
3025         AssignExpression assignExpression;
3026         **/
3027 
3028         with(templateArgument)
3029         {
3030             if (type) format(type);
3031             if (assignExpression) format(assignExpression);
3032         }
3033     }
3034 
3035     void format(const TemplateArgumentList templateArgumentList, bool parens = true)
3036     {
3037         debug(verbose) writeln("TemplateArgumentList");
3038 
3039         if (parens) put("!(");
3040         foreach(count, arg; templateArgumentList.items)
3041         {
3042             if (count) put(", ");
3043             format(arg);
3044         }
3045         if (parens) put(")");
3046     }
3047 
3048     void format(const TemplateArguments templateArguments)
3049     {
3050         debug(verbose) writeln("TemplateArguments");
3051 
3052         /**
3053         TemplateArgumentList templateArgumentList;
3054         TemplateSingleArgument templateSingleArgument;
3055         **/
3056 
3057         with(templateArguments)
3058         {
3059             if (templateArgumentList) format(templateArgumentList);
3060             else if (templateSingleArgument) format(templateSingleArgument);
3061             else put("!()");
3062         }
3063     }
3064 
3065     void format(const TemplateDeclaration templateDeclaration, const Attribute[] attrs = null)
3066     {
3067         debug(verbose) writeln("TemplateDeclaration");
3068 
3069         /**
3070         Token name;
3071         TemplateParameters templateParameters;
3072         Constraint constraint;
3073         Declaration[] declarations;
3074         EponymousTemplateDeclaration eponymousTemplateDeclaration;
3075         string comment;
3076         **/
3077 
3078         with(templateDeclaration)
3079         {
3080             newThing(What.other);
3081             putComment(comment);
3082             putAttrs(attrs);
3083 
3084             put("template ");
3085             format(name);
3086 
3087             if (templateParameters)
3088                 format(templateParameters);
3089 
3090             if (constraint)
3091             {
3092                 space();
3093                 format(constraint);
3094             }
3095 
3096             startBlock();
3097             foreach(d; declarations)
3098                 format(d);
3099             endBlock();
3100         }
3101     }
3102 
3103     void format(const TemplateInstance templateInstance)
3104     {
3105         debug(verbose) writeln("TemplateInstance");
3106 
3107         /**
3108         Token identifier;
3109         TemplateArguments templateArguments;
3110         **/
3111 
3112         with(templateInstance)
3113         {
3114             format(identifier);
3115             if (templateArguments) format(templateArguments);
3116         }
3117     }
3118 
3119     void format(const TemplateMixinExpression templateMixinExpression)
3120     {
3121         debug(verbose) writeln("TemplateMixinExpression");
3122 
3123         /**
3124         Token identifier;
3125         TemplateArguments templateArguments;
3126         MixinTemplateName mixinTemplateName;
3127         **/
3128 
3129         with(templateMixinExpression)
3130         {
3131             put("mixin ");
3132             format(mixinTemplateName);
3133             if (templateArguments) format(templateArguments);
3134             space();
3135             format(identifier);
3136         }
3137     }
3138 
3139     void format(const TemplateParameter templateParameter)
3140     {
3141         debug(verbose) writeln("TemplateParameter");
3142 
3143         with(templateParameter)
3144         {
3145             if (templateTypeParameter)
3146                 format(templateTypeParameter);
3147             else if (templateValueParameter)
3148                 format(templateValueParameter);
3149             else if (templateAliasParameter)
3150                 format(templateAliasParameter);
3151             else if (templateTupleParameter)
3152                 format(templateTupleParameter);
3153             else if (templateThisParameter)
3154                 format(templateThisParameter);
3155         }
3156     }
3157 
3158     void format(const TemplateParameterList templateParameterList)
3159     {
3160         debug(verbose) writeln("TemplateParameterList");
3161 
3162         foreach(i, param; templateParameterList.items)
3163         {
3164             if (i) put(", ");
3165             format(param);
3166         }
3167     }
3168 
3169     void format(const TemplateParameters templateParameters)
3170     {
3171         debug(verbose) writeln("TemplateParameters");
3172 
3173         with(templateParameters)
3174         {
3175             put("(");
3176             if (templateParameterList)
3177                 format(templateParameterList);
3178             put(")");
3179         }
3180     }
3181 
3182     void format(const TemplateSingleArgument templateSingleArgument)
3183     {
3184         debug(verbose) writeln("TemplateSingleArgument");
3185 
3186         /**
3187         Token token;
3188         **/
3189 
3190         put("!");
3191         format(templateSingleArgument.token);
3192     }
3193 
3194     void format(const TemplateThisParameter templateThisParameter)
3195     {
3196         debug(verbose) writeln("TemplateThisParameter");
3197 
3198         with(templateThisParameter)
3199         {
3200             put("this ");
3201             if (templateTypeParameter)
3202                 format(templateTypeParameter);
3203         }
3204     }
3205 
3206     void format(const TemplateTupleParameter templateTupleParameter)
3207     {
3208         debug(verbose) writeln("TemplateTupleParameter");
3209 
3210         format(templateTupleParameter.identifier);
3211         put("...");
3212     }
3213 
3214     void format(const TemplateTypeParameter templateTypeParameter)
3215     {
3216         debug(verbose) writeln("TemplateTypeParameter");
3217 
3218         /**
3219         Token identifier;
3220         Type colonType;
3221         Type assignType;
3222         **/
3223 
3224         with(templateTypeParameter)
3225         {
3226             format(identifier);
3227             if (colonType)
3228             {
3229                 put(" : ");
3230                 format(colonType);
3231             }
3232             if (assignType)
3233             {
3234                 put(" = ");
3235                 format(assignType);
3236             }
3237         }
3238     }
3239 
3240     void format(const TemplateValueParameter templateValueParameter)
3241     {
3242         debug(verbose) writeln("TemplateValueParameter");
3243 
3244         /**
3245         Type type;
3246         Token identifier;
3247         Expression expression;
3248         TemplateValueParameterDefault templateValueParameterDefault;
3249         **/
3250 
3251         with(templateValueParameter)
3252         {
3253             if (type) format(type);
3254             space();
3255             format(identifier);
3256 
3257             if (assignExpression)
3258             {
3259                 put(" : ");
3260                 format(assignExpression);
3261             }
3262 
3263             if (templateValueParameterDefault)
3264             {
3265                 put(" = ");
3266                 format(templateValueParameterDefault);
3267             }
3268         }
3269     }
3270 
3271     void format(const TemplateValueParameterDefault templateValueParameterDefault)
3272     {
3273         debug(verbose) writeln("TemplateValueParameterDefault");
3274 
3275         with(templateValueParameterDefault)
3276             assignExpression ? format(assignExpression) : format(token);
3277     }
3278 
3279     void format(const TernaryExpression expr)
3280     {
3281         debug(verbose) writeln("TernaryExpression");
3282 
3283         /**
3284         ExpressionNode orOrExpression;
3285         ExpressionNode expression;
3286         ExpressionNode ternaryExpression;
3287         **/
3288 
3289         format(expr.orOrExpression);
3290 
3291         if (expr.expression && expr.ternaryExpression)
3292         {
3293             put(" ? ");
3294             format(expr.expression);
3295             put(" : ");
3296             format(expr.ternaryExpression);
3297         }
3298     }
3299 
3300     void format(const ThrowStatement throwStatement)
3301     {
3302         debug(verbose) writeln("ThrowStatement");
3303 
3304         put("throw ");
3305         assert(throwStatement.expression);
3306         format(throwStatement.expression);
3307         put(";");
3308     }
3309 
3310     void format(const Token token)
3311     {
3312         debug(verbose) writeln("Token ", tokenRep(token));
3313         put(tokenRep(token));
3314     }
3315 
3316     void format(const TraitsExpression traitExpr)
3317     {
3318         debug(verbose) writeln("TraitsExpression");
3319 
3320         /**
3321         Token identifier;
3322         TemplateArgumentList templateArgumentList;
3323         **/
3324 
3325         put("__traits(");
3326         format(traitExpr.identifier);
3327         put(", ");
3328         format(traitExpr.templateArgumentList, false);
3329         put(")");
3330     }
3331 
3332     void format(const TryStatement tryStatement)
3333     {
3334         debug(verbose) writeln("TryStatement");
3335 
3336         /**
3337         DeclarationOrStatement declarationOrStatement;
3338         Catches catches;
3339         Finally finally_;
3340         **/
3341 
3342         with(tryStatement)
3343         {
3344             newThing(What.other);
3345             put("try");
3346             maybeIndent(declarationOrStatement);
3347             if (catches) format(catches);
3348             if (finally_) format(finally_);
3349         }
3350     }
3351 
3352     void format(const Type type)
3353     {
3354         debug(verbose) writeln("Type(");
3355 
3356         /**
3357         IdType[] typeConstructors;
3358         TypeSuffix[] typeSuffixes;
3359         Type2 type2;
3360         **/
3361 
3362         foreach (count, constructor; type.typeConstructors)
3363         {
3364             if (count) space();
3365             put(tokenRep(constructor));
3366         }
3367 
3368         if (type.typeConstructors.length) space();
3369         if (type.type2) format(type.type2);
3370 
3371         foreach (suffix; type.typeSuffixes)
3372             format(suffix);
3373 
3374         debug(verbose) writeln(")");
3375     }
3376 
3377     void format(const Type2 type2)
3378     {
3379         debug(verbose) writeln("Type2");
3380 
3381         /**
3382         IdType builtinType;
3383         TypeofExpression typeofExpression;
3384         IdentifierList identifierList;
3385         IdType typeConstructor;
3386         Type type;
3387         TraitsExpression traitsExpression;
3388         MixinExpression mixinExpression;
3389         **/
3390 
3391         if (type2.typeIdentifierPart !is null)
3392         {
3393             format(type2.typeIdentifierPart);
3394         }
3395         else if (type2.typeofExpression !is null)
3396         {
3397             format(type2.typeofExpression);
3398             if (type2.typeIdentifierPart)
3399             {
3400                 put(".");
3401                 format(type2.typeIdentifierPart);
3402             }
3403             return;
3404         }
3405         else if (type2.typeConstructor != tok!"")
3406         {
3407             put(tokenRep(type2.typeConstructor));
3408             put("(");
3409             format(type2.type);
3410             put(")");
3411         }
3412         else if (type2.traitsExpression)
3413         {
3414             format(type2.traitsExpression);
3415         }
3416         else if (type2.mixinExpression)
3417         {
3418             format(type2.mixinExpression);
3419         }
3420         else
3421         {
3422             put(tokenRep(type2.builtinType));
3423             if (type2.typeIdentifierPart)
3424             {
3425                 put(".");
3426                 format(type2.typeIdentifierPart);
3427             }
3428         }
3429     }
3430 
3431     void format(const TypeSpecialization typeSpecialization)
3432     {
3433         debug(verbose) writeln("TypeSpecialization");
3434 
3435         /**
3436         Token token;
3437         Type type;
3438         **/
3439 
3440         with(typeSpecialization)
3441         {
3442             format(token);
3443             if (type) format(type);
3444         }
3445     }
3446 
3447     void format(const TypeSuffix typeSuffix)
3448     {
3449         debug(verbose) writeln("TypeSuffix");
3450 
3451         /**
3452         Token delegateOrFunction;
3453         bool star;
3454         bool array;
3455         Type type;
3456         AssignExpression low;
3457         AssignExpression high;
3458         Parameters parameters;
3459         MemberFunctionAttribute[] memberFunctionAttributes;
3460         **/
3461 
3462         if (typeSuffix.star.type != tok!"")
3463         {
3464             put("*");
3465             return;
3466         }
3467         else if (typeSuffix.array)
3468         {
3469             if (typeSuffix.type is null)
3470             {
3471                 if (typeSuffix.low is null)
3472                 {
3473                     put("[]");
3474                     return;
3475                 }
3476                 else
3477                 {
3478                     if (typeSuffix.high is null)
3479                     {
3480                         put("[");
3481                         format(typeSuffix.low);
3482                         put("]");
3483                         return;
3484                     }
3485                     else
3486                     {
3487                         put("[");
3488                         format(typeSuffix.low);
3489                         put("..");
3490                         format(typeSuffix.high);
3491                         put("]");
3492                         return;
3493                     }
3494                 }
3495             }
3496             else
3497             {
3498                 put("[");
3499                 format(typeSuffix.type);
3500                 put("]");
3501                 return;
3502             }
3503         }
3504         else
3505         {
3506             space();
3507             format(typeSuffix.delegateOrFunction);
3508             if (typeSuffix.parameters) format(typeSuffix.parameters);
3509             foreach(attr; typeSuffix.memberFunctionAttributes)
3510             {
3511                 space();
3512                 format(attr);
3513             }
3514             return;
3515         }
3516     }
3517 
3518     void format(const TypeidExpression idExpr)
3519     {
3520         debug(verbose) writeln("TypeidExpression");
3521 
3522         /**
3523         Type type;
3524         Expression expression;
3525         **/
3526 
3527         put("typeid (");
3528         idExpr.type ? format(idExpr.type) : format(idExpr.expression);
3529         put(")");
3530     }
3531 
3532     void format(const TypeofExpression typeofExpr)
3533     {
3534         debug(verbose) writeln("TypeofExpression");
3535 
3536         /**
3537         Expression expression;
3538         Token return_;
3539         **/
3540 
3541         put("typeof(");
3542         typeofExpr.expression ? format(typeofExpr.expression) : format(typeofExpr.return_);
3543         put(")");
3544     }
3545 
3546     void format(const UnaryExpression unary)
3547     {
3548         debug(verbose) writeln("UnaryExpression(");
3549 
3550         /**
3551         Type type;
3552         PrimaryExpression primaryExpression;
3553         Token prefix;
3554         Token suffix;
3555         UnaryExpression unaryExpression;
3556         NewExpression newExpression;
3557         DeleteExpression deleteExpression;
3558         CastExpression castExpression;
3559         FunctionCallExpression functionCallExpression;
3560         ArgumentList argumentList;
3561         IdentifierOrTemplateInstance identifierOrTemplateInstance;
3562         AssertExpression assertExpression;
3563         SliceExpression sliceExpression;
3564         IndexExpression indexExpression;
3565         **/
3566 
3567         with(unary)
3568         {
3569             if (prefix != tok!"") format(prefix);
3570 
3571             if (type)
3572             {
3573                 // handle things like (void*).sizeof
3574                 if (identifierOrTemplateInstance)
3575                 {
3576                     put("(");
3577                     format(type);
3578                     put(")");
3579                 }
3580                 else
3581                 {
3582                     format(type);
3583                     put("(");
3584                     if (argumentList)
3585                         format(argumentList);
3586                     put(")");
3587                 }
3588             }
3589 
3590             if (primaryExpression) format(primaryExpression);
3591             if (newExpression) format(newExpression);
3592             if (deleteExpression) format(deleteExpression);
3593             if (castExpression) format(castExpression);
3594             if (functionCallExpression) format(functionCallExpression);
3595             if (assertExpression) format(assertExpression);
3596             if (indexExpression) format(indexExpression);
3597 
3598             if (unaryExpression) format(unaryExpression);
3599             if (suffix != tok!"") format(suffix);
3600 
3601             if (identifierOrTemplateInstance)
3602             {
3603                 put(".");
3604                 format(identifierOrTemplateInstance);
3605             }
3606         }
3607 
3608         debug(verbose) writeln(")");
3609     }
3610 
3611     void format(const UnionDeclaration decl, const Attribute[] attrs = null)
3612     {
3613         debug(verbose) writeln("UnionDeclaration");
3614 
3615         /**
3616         Token name;
3617         TemplateParameters templateParameters;
3618         Constraint constraint;
3619         StructBody structBody;
3620         string comment;
3621         **/
3622 
3623         newThing(What.aggregateDecl);
3624         putComment(decl.comment);
3625         putAttrs(attrs);
3626         put("union ");
3627         format(decl.name);
3628         if (decl.templateParameters)
3629             format(decl.templateParameters);
3630         if (decl.constraint)
3631         {
3632             space();
3633             format(decl.constraint);
3634         }
3635         format(decl.structBody);
3636     }
3637 
3638     void format(const Unittest unittest_, const Attribute[] attrs = null)
3639     {
3640         debug(verbose) writeln("Unittest");
3641 
3642         /**
3643         BlockStatement blockStatement;
3644         string comment;
3645         **/
3646 
3647         newThing(What.functionDecl);
3648         putComment(unittest_.comment);
3649         putAttrs(attrs);
3650         put("unittest");
3651         format(unittest_.blockStatement);
3652     }
3653 
3654     void format(const VariableDeclaration decl, const Attribute[] attrs = null)
3655     {
3656         debug(verbose) writeln("VariableDeclaration");
3657 
3658         /**
3659         Type type;
3660         Declarator[] declarators;
3661         StorageClass storageClass;
3662         AutoDeclaration autoDeclaration;
3663         string comment;
3664         **/
3665 
3666         newThing(What.variableDecl);
3667         putComment(decl.comment);
3668         putAttrs(attrs);
3669 
3670         if (decl.autoDeclaration)
3671             format(decl.autoDeclaration);
3672         else
3673         {
3674             foreach (c; decl.storageClasses)
3675             {
3676                 format(c);
3677                 space();
3678             }
3679             if (decl.type) format(decl.type);
3680             if (decl.declarators.length) space();
3681             foreach(count, d; decl.declarators)
3682             {
3683                 if (count) put(", ");
3684                 format(d);
3685             }
3686         }
3687         put(";");
3688     }
3689 
3690     void format(const Vector vector)
3691     {
3692         debug(verbose) writeln("Vector");
3693 
3694         put("__vector");
3695         if (vector.type)
3696         {
3697             put("(");
3698             format(vector.type);
3699             put(")");
3700         }
3701     }
3702 
3703     void format(const VersionCondition versionCondition)
3704     {
3705         debug(verbose) writeln("VersionCondition");
3706 
3707         put("version (");
3708         format(versionCondition.token);
3709         put(")");
3710     }
3711 
3712     void format(const VersionSpecification ver, const Attribute[] attrs = null)
3713     {
3714         debug(verbose) writeln("VersionSpecification");
3715 
3716         newThing(What.other);
3717         putAttrs(attrs);
3718         put("version = ");
3719         format(ver.token);
3720         put(";");
3721     }
3722 
3723     void format(const WhileStatement stmt)
3724     {
3725         debug(verbose) writeln("WhileStatement");
3726 
3727         /**
3728         Expression expression;
3729         DeclarationOrStatement declarationOrStatement;
3730         **/
3731 
3732         newThing(What.other);
3733         put("while (");
3734         format(stmt.expression);
3735         put(")");
3736         maybeIndent(stmt.declarationOrStatement);
3737     }
3738 
3739     void format(const WithStatement stmt)
3740     {
3741         debug(verbose) writeln("WithStatement");
3742 
3743         /**
3744         Expression expression;
3745         DeclarationsOrStatement declarationOrStatement;
3746         **/
3747 
3748         space();
3749         put("with (");
3750         format(stmt.expression);
3751         put(")");
3752         if (stmt.declarationOrStatement)
3753             format(stmt.declarationOrStatement);
3754     }
3755 
3756     void format(const XorExpression xorExpression)
3757     {
3758         debug(verbose) writeln("XorExpression");
3759         mixin(binary("xorExpression", "^"));
3760     }
3761 
3762     Sink sink;
3763 
3764 protected:
3765 
3766     import std.uni : isWhite;
3767 
3768     void indent()
3769     {
3770         indentLevel++;
3771     }
3772 
3773     void outdent()
3774     {
3775         if (indentLevel == 0)
3776             return;
3777         indentLevel--;
3778     }
3779 
3780     void putIndent()
3781     {
3782         if (!indentLevel) return;
3783         auto i = getIndent();
3784         put(i);
3785     }
3786 
3787     string getIndent()
3788     {
3789         if (useTabs)
3790         {
3791             char[] c = new char[indentLevel];
3792             c[] = '\t';
3793             return cast(string) c;
3794         }
3795         else
3796         {
3797             char[] c = new char[indentLevel * indentWidth];
3798             c[] = ' ';
3799             return cast(string) c;
3800         }
3801     }
3802 
3803     enum What
3804     {
3805         functionDecl,
3806         aggregateDecl,
3807         attributeDecl,
3808         conditionalDecl,
3809         variableDecl,
3810         importDecl,
3811         expr,
3812         loop,
3813         else_,
3814         catch_,
3815         other
3816     }
3817 
3818     void newThing(What thing)
3819     {
3820         lastThing = currentThing;
3821         currentThing = thing;
3822 
3823         with(What) {
3824 
3825             if (lastThing == importDecl && thing != importDecl)
3826             {
3827                 lineGap(1);
3828                 return;
3829             }
3830 
3831             if (lastThing == loop)
3832             {
3833                 lineGap(1);
3834                 return;
3835             }
3836 
3837             switch(thing)
3838             {
3839                 case other:
3840                     newline();
3841                     break;
3842                 case aggregateDecl:
3843                 case attributeDecl:
3844                 case functionDecl:
3845                     lineGap(1);
3846                     break;
3847                 case conditionalDecl:
3848                     //lineGap(1);
3849                     break;
3850                 case variableDecl:
3851                     lineGap(1);
3852                     break;
3853                 case importDecl:
3854                     newlineIndent();
3855                     break;
3856                 case expr: break;
3857                 case catch_: goto case;
3858                 case else_:
3859                     final switch(style) with(IndentStyle)
3860                     {
3861                         case allman: newline(); break;
3862                         case otbs: space(); break;
3863                     }
3864                     break;
3865                 default: newlineIndent(); break;
3866             }
3867         }
3868     }
3869 
3870     void lineGap(int gap)
3871     {
3872         foreach (i; 0 .. gap + 1)
3873         {
3874             if (i == gap)
3875                 newlineIndent();
3876             else
3877                 newline();
3878         }
3879     }
3880 
3881     void newlineIndent()
3882     {
3883         if (ignoreNewlines)
3884         {
3885             space(); // don't do this when splitting lines
3886         }
3887         else
3888         {
3889             sink.put("\n");
3890             lineLength = 0;
3891             putIndent();
3892         }
3893     }
3894 
3895     void newline()
3896     {
3897         sink.put("\n");
3898         lineLength = 0;
3899     }
3900 
3901     void space()
3902     {
3903         put(" ");
3904     }
3905 
3906     static string binary(string symbol, string operator = null, bool nospace = false)
3907     {
3908         return "with(" ~ symbol ~ "){"
3909              ~ "format(left); if (right is null) return;"
3910              ~ (nospace ? "" : "put(` `);")
3911              ~ (operator ? "put(`" ~ operator ~ "`);" : "put(tokenRep(operator));")
3912              ~ (nospace ? "" : "put(` `);")
3913              ~ "format(right);}";
3914     }
3915 
3916     void startBlock()
3917     {
3918         final switch(style) with(IndentStyle)
3919         {
3920             case allman: newline(); break;
3921             case otbs: space(); break;
3922         }
3923         putIndent();
3924         put("{");
3925         indent();
3926     }
3927 
3928     void endBlock()
3929     {
3930         outdent();
3931         newline();
3932         putIndent();
3933         put("}");
3934     }
3935 
3936     string tokenRep(Token t)
3937     {
3938         return t.text.length ? t.text : tokenRep(t.type);
3939     }
3940 
3941     string tokenRep(IdType t)
3942     {
3943         return t ? str(t) : "";
3944     }
3945 
3946     void putComment(string c)
3947     {
3948         import std..string : splitLines;
3949         if (!c.length) return;
3950         put(c.splitLines().join("\n" ~ getIndent()));
3951         newlineIndent();
3952     }
3953 
3954     void putAttrs(const Attribute[] attrs)
3955     {
3956         if (attrs !is null)
3957         {
3958             foreach(count, attr; attrs)
3959             {
3960                 format(attr);
3961                 space();
3962             }
3963         }
3964     }
3965 
3966     void put(string s)
3967     {
3968         sink.put(s);
3969         lineLength += s.length; // TODO: tabs / spaces?
3970     }
3971 
3972     void formatCaseDecls(const DeclarationsAndStatements declsAndStmnts)
3973     {
3974         bool seenBlock = false;
3975         auto items = declsAndStmnts.declarationsAndStatements;
3976         foreach(item; items)
3977         {
3978             bool _indent = false;
3979             if (item.declaration) _indent = true;
3980             if (item.statement && item.statement.statementNoCaseNoDefault)
3981             {
3982                 if (item.statement.statementNoCaseNoDefault.blockStatement)
3983                     seenBlock = true;
3984                 else if (!item.statement.statementNoCaseNoDefault.labeledStatement)
3985                     _indent = true;
3986             }
3987             if (seenBlock) _indent = false;
3988             if (_indent) indent();
3989             format(item);
3990             if (_indent) outdent();
3991         }
3992     }
3993 
3994     bool needIndent(const Statement s)
3995     {
3996         return s.statementNoCaseNoDefault &&
3997                !s.statementNoCaseNoDefault.blockStatement;
3998     }
3999 
4000     bool needIndent(const Declaration d)
4001     {
4002         return !d.declarations.length;
4003     }
4004 
4005     bool needIndent(const DeclarationOrStatement dors)
4006     {
4007         return (dors.declaration && needIndent(dors.declaration)) ||
4008                (dors.statement && needIndent(dors.statement));
4009     }
4010 
4011     void maybeIndent(T)(const T t)
4012     {
4013         auto _indent = needIndent(t);
4014         if (_indent) indent();
4015         format(t);
4016         if (_indent) outdent();
4017     }
4018 
4019     bool isEmptyDeclaration(const Declaration decl)
4020     {
4021         with(decl)
4022         {
4023             string mix(string[] s) {
4024                 string r;
4025                 foreach(c, d; s)
4026                     r ~= (c > 0 ? "else " : "") ~ "if (" ~ d ~ ") return false;";
4027                 return r;
4028             }
4029             mixin(mix(possibleDeclarations));
4030             return attributes.length == 0 &&
4031                    declarations.length == 0;
4032         }
4033     }
4034 
4035     bool ignoreNewlines = false;
4036     bool useTabs;
4037     uint caseDepth;
4038     uint indentWidth;
4039     uint indentLevel;
4040     IndentStyle style;
4041 
4042 
4043     What lastThing, currentThing;
4044     uint lineLength;
4045     uint maxLineLength = 80;
4046 
4047     enum possibleDeclarations = [
4048         "attributeDeclaration",
4049         "importDeclaration",
4050         "functionDeclaration",
4051         "variableDeclaration",
4052         "aliasThisDeclaration",
4053         "structDeclaration",
4054         "classDeclaration",
4055         "interfaceDeclaration",
4056         "unionDeclaration",
4057         "enumDeclaration",
4058         "aliasDeclaration",
4059         "mixinDeclaration",
4060         "mixinTemplateDeclaration",
4061         "unittest_",
4062         "staticAssertDeclaration",
4063         "templateDeclaration",
4064         "constructor",
4065         "destructor",
4066         "staticConstructor",
4067         "staticDestructor",
4068         "sharedStaticDestructor",
4069         "sharedStaticConstructor",
4070         "conditionalDeclaration",
4071         "pragmaDeclaration",
4072         "versionSpecification",
4073         "invariant_",
4074         "postblit"
4075     ];
4076 }
4077 
4078 version (unittest)
4079 void testFormatNode(Node)(string sourceCode, string expected = "")
4080 {
4081     Appender!string fmt;
4082     ubyte[] code = cast(ubyte[]) sourceCode;
4083 
4084     class CatchInterestingStuff : ASTVisitor
4085     {
4086         alias visit = ASTVisitor.visit;
4087         override void visit(const(Node) stuff)
4088         {
4089             stuff.accept(this);
4090             format(&fmt, stuff);
4091             if (expected.length)
4092                 assert(fmt.data.canFind(expected), "\n" ~ fmt.data);
4093             else
4094                 assert(fmt.data.canFind(sourceCode), "\n" ~ fmt.data);
4095         }
4096     }
4097 
4098     static void errorFunc(string,size_t,size_t,string msg, bool)
4099     {assert(0, "The AST to format contains error(s) : " ~ msg);}
4100 
4101     LexerConfig config;
4102     StringCache cache = StringCache(32);
4103     RollbackAllocator rba;
4104     auto toks = getTokensForParser(code, config, &cache);
4105     Module mod = parseModule(ParserConfig(toks, "stdin", &rba, &errorFunc));
4106     (new CatchInterestingStuff).visit(mod);
4107 }
4108 
4109 unittest
4110 {
4111     testFormatNode!(VariableDeclaration)("__traits(getMember, Foo, \"Bar\") fooBar;");
4112     testFormatNode!(VariableDeclaration)("const(__traits(getMember, Foo, \"Bar\")) fooBar;");
4113     testFormatNode!(VariableDeclaration)("T.T y;");
4114     testFormatNode!(VariableDeclaration)("T[] y;");
4115     testFormatNode!(VariableDeclaration)("T* y;");
4116     testFormatNode!(VariableDeclaration)("T[0].Y y;");
4117     testFormatNode!(VariableDeclaration)("T.T[] y;");
4118     testFormatNode!(VariableDeclaration)("T.T[8] y;");
4119     testFormatNode!(VariableDeclaration)("T.T[8].T y;");
4120     testFormatNode!(VariableDeclaration)(`.T!"af" taf;`);
4121     testFormatNode!(VariableDeclaration)(`.T!0[] t;`);
4122     testFormatNode!(VariableDeclaration)(`T!(0)[] t;`);
4123     testFormatNode!(VariableDeclaration)(`T!(0)[dim] t;`);
4124     testFormatNode!(VariableDeclaration)(`const shared t = [0, 1];`);
4125 
4126     testFormatNode!(OutStatement)(
4127 `
4128 void foo()
4129 out{static if (true) {baz();}}
4130 do{}
4131 `,
4132 `out
4133 {
4134     static if (true)
4135     {
4136         baz();
4137     }
4138 }`);
4139 
4140     testFormatNode!(AutoDeclaration)("auto f = a;");
4141     testFormatNode!(AutoDeclaration)("auto f = ref () => a;");
4142     testFormatNode!(AliasDeclaration)("alias f = ref () => a;");
4143 
4144     testFormatNode!(AliasDeclaration)("alias int F(int);");
4145     testFormatNode!(AliasDeclaration)("alias const int F(int);");
4146     testFormatNode!(AliasDeclaration)("alias const int F(int) nothrow;");
4147     testFormatNode!(AliasDeclaration)("alias f(T) = void(T t);");
4148     testFormatNode!(AliasDeclaration)("alias f(T) = void(int, int, int) const pure nothrow;");
4149 
4150     testFormatNode!(AliasDeclaration)("alias MT = mixin (strEnum1, strEnum2);");
4151 
4152     testFormatNode!(Module)("static assert(() @trusted { return bar()(3); }() == 4);",
4153 `static assert (() @trusted
4154 { return bar()(3);
4155 }() == 4)`
4156 );
4157     testFormatNode!(Module)("int foo() { return 2; }",
4158 `int foo()
4159 {
4160     return 2;
4161 }`
4162 );
4163 
4164     testFormatNode!(Module)("int foo() do { return 2; }",
4165 `int foo()
4166 do
4167 {
4168     return 2;
4169 }`
4170 );
4171 
4172     testFormatNode!(Module)("int foo(int i) in(i > 0) do { return 2; }",
4173 `int foo(int i)
4174 in (i > 0)
4175 do
4176 {
4177     return 2;
4178 }`
4179 );
4180 
4181     testFormatNode!(Module)("int foo(int i) in { assert(i > 0); } do { return 2; }",
4182 `int foo(int i)
4183 in
4184 {
4185     assert (i > 0);
4186 }
4187 do
4188 {
4189     return 2;
4190 }`
4191 );
4192 
4193     testFormatNode!(Module)("int foo() out(j; j > 0) do { return 2; }",
4194 `int foo()
4195 out (j; j > 0)
4196 do
4197 {
4198     return 2;
4199 }`
4200 );
4201 
4202     testFormatNode!(Module)("int foo() out(j) { assert(j > 0); } do { return 2; }",
4203 `int foo()
4204 out (j)
4205 {
4206     assert (j > 0);
4207 }
4208 do
4209 {
4210     return 2;
4211 }`
4212 );
4213 
4214     testFormatNode!(Module)("version(BAR) {
4215         int foo(int i)
4216         in(i > 0) in { assert(i > 0); }
4217         out(j; j > 0) out(j) { assert(j>0); }
4218         do { return 2; } int i; }
4219     ",
4220 `version (BAR)
4221 {
4222 
4223     int foo(int i)
4224     in (i > 0)
4225     in
4226     {
4227         assert (i > 0);
4228     }
4229     out (j; j > 0)
4230     out (j)
4231     {
4232         assert (j > 0);
4233     }
4234     do
4235     {
4236         return 2;
4237     }
4238 
4239     int i;
4240 }`
4241 );
4242 }