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