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         }
2035         put(")");
2036     }
2037 
2038     void format(const MemberFunctionAttribute memberFunctionAttribute)
2039     {
2040         debug(verbose) writeln("MemberFunctionAttribute");
2041 
2042         /**
2043         IdType tokenType;
2044         AtAttribute atAttribute;
2045         **/
2046 
2047         with(memberFunctionAttribute)
2048         {
2049             if (tokenType) put(tokenRep(tokenType));
2050             else format(atAttribute);
2051         }
2052     }
2053 
2054     void format(const MixinDeclaration mixinDeclaration, const Attribute[] attrs = null)
2055     {
2056         debug(verbose) writeln("MixinDeclaration");
2057 
2058         /**
2059         MixinExpression mixinExpression;
2060         TemplateMixinExpression templateMixinExpression;
2061         **/
2062 
2063         with(mixinDeclaration)
2064         {
2065             putAttrs(attrs);
2066             if (mixinExpression) format(mixinExpression);
2067             else format(templateMixinExpression);
2068             put(";");
2069         }
2070     }
2071 
2072     void format(const MixinExpression mixinExpression)
2073     {
2074         debug(verbose) writeln("MixinExpression");
2075 
2076         put("mixin (");
2077         format(mixinExpression.assignExpression);
2078         put(")");
2079     }
2080 
2081     void format(const MixinTemplateDeclaration mixinTemplateDeclaration, const Attribute[] attrs = null)
2082     {
2083         debug(verbose) writeln("MixinTemplateDeclaration");
2084 
2085         putAttrs(attrs);
2086         put("mixin ");
2087         format(mixinTemplateDeclaration.templateDeclaration);
2088     }
2089 
2090     void format(const MixinTemplateName mixinTemplateName)
2091     {
2092         debug(verbose) writeln("MixinTemplateName");
2093 
2094         /**
2095         Symbol symbol;
2096         IdentifierOrTemplateChain identifierOrTemplateChain;
2097         TypeofExpression typeofExpression;
2098         **/
2099 
2100         with(mixinTemplateName)
2101         {
2102             if (symbol) format(symbol);
2103             else
2104             {
2105                 format(typeofExpression);
2106                 put(".");
2107                 format(identifierOrTemplateChain);
2108             }
2109         }
2110     }
2111 
2112     void format(const Module module_)
2113     {
2114         debug(verbose) writeln("Module");
2115 
2116         /**
2117         ModuleDeclaration moduleDeclaration;
2118         Declaration[] declarations;
2119         **/
2120 
2121         format(module_.moduleDeclaration);
2122         foreach(decl; module_.declarations)
2123             format(decl);
2124     }
2125 
2126     void format(const ModuleDeclaration moduleDeclaration)
2127     {
2128         debug(verbose) writeln("ModuleDeclaration");
2129         if (moduleDeclaration is null) return;
2130 
2131         /**
2132         IdentifierChain moduleName;
2133         **/
2134 
2135         put("module ");
2136         format(moduleDeclaration.moduleName);
2137         put(";");
2138         newlineIndent();
2139         newlineIndent();
2140     }
2141 
2142     void format(const MulExpression mulExpression)
2143     {
2144         debug(verbose) writeln("MulExpression");
2145         mixin(binary("mulExpression"));
2146     }
2147 
2148     void format(const NewAnonClassExpression newAnonClassExpression)
2149     {
2150         debug(verbose) writeln("NewAnonClassExpression");
2151 
2152         /**
2153         Arguments allocatorArguments;
2154         Arguments constructorArguments;
2155         BaseClassList baseClassList;
2156         StructBody structBody;
2157         **/
2158 
2159         with(newAnonClassExpression)
2160         {
2161             if (allocatorArguments)
2162             {
2163                 format(allocatorArguments);
2164                 space();
2165             }
2166             put("class");
2167             if (constructorArguments)
2168                 format(constructorArguments);
2169 
2170             if (baseClassList)
2171             {
2172                 space();
2173                 format(baseClassList);
2174             }
2175 
2176             format(structBody);
2177         }
2178     }
2179 
2180     void format(const NewExpression newExpression)
2181     {
2182         debug(verbose) writeln("NewExpression");
2183 
2184         /**
2185         Type type;
2186         NewAnonClassExpression newAnonClassExpression;
2187         Arguments arguments;
2188         AssignExpression assignExpression;
2189         **/
2190 
2191         with(newExpression)
2192         {
2193             put("new ");
2194             if (newAnonClassExpression) format(newAnonClassExpression);
2195             else
2196             {
2197                 if (type) format(type);
2198                 if (arguments) format(arguments);
2199                 if (assignExpression)
2200                 {
2201                     put("[");
2202                     format(assignExpression);
2203                     put("]");
2204                 }
2205             }
2206         }
2207     }
2208 
2209     void format(const NonVoidInitializer nonVoidInitializer)
2210     {
2211         debug(verbose) writeln("NonVoidInitializer");
2212 
2213         /**
2214         AssignExpression assignExpression;
2215         ArrayInitializer arrayInitializer;
2216         StructInitializer structInitializer;
2217         **/
2218 
2219         with(nonVoidInitializer)
2220         {
2221             if (assignExpression) format(assignExpression);
2222             else if (arrayInitializer) format(arrayInitializer);
2223             else if (structInitializer) format(structInitializer);
2224         }
2225     }
2226 
2227     void format(const Operands operands)
2228     {
2229         debug(verbose) writeln("Operands");
2230         assert(false);
2231     }
2232 
2233     void format(const OrExpression orExpression)
2234     {
2235         debug(verbose) writeln("OrExpression");
2236         mixin(binary("orExpression", "|"));
2237     }
2238 
2239     void format(const OrOrExpression orOrExpression)
2240     {
2241         debug(verbose) writeln("OrOrExpression");
2242         mixin(binary("orOrExpression", "||"));
2243     }
2244 
2245     void format(const OutStatement stmnt)
2246     {
2247         debug(verbose) writeln("OutStatement");
2248 
2249         /**
2250         Token parameter;
2251         BlockStatement blockStatement;
2252         **/
2253 
2254         put("out");
2255 	if(stmnt.expression) {
2256 		put(" (");
2257 		format(stmnt.parameter);
2258 		put("; ");
2259 		format(stmnt.expression);
2260 		put(")");
2261 		return;
2262 	}
2263         if (stmnt.parameter != tok!"")
2264         {
2265             put(" (");
2266             format(stmnt.parameter);
2267             put(")");
2268         }
2269 	if(stmnt.blockStatement)
2270         format(stmnt.blockStatement);
2271     }
2272 
2273     void format(const Parameter parameter)
2274     {
2275         debug(verbose) writeln("Parameter");
2276 
2277         /**
2278         IdType[] parameterAttributes;
2279         Type type;
2280         Token name;
2281         bool vararg;
2282         AssignExpression default_;
2283         TypeSuffix[] cstyle;
2284         **/
2285 
2286 	bool hadAtAttribute;
2287 
2288 	foreach (count, attribute; parameter.atAttributes)
2289 	{
2290 		hadAtAttribute = true;
2291             if (count) space();
2292             format(attribute);
2293 	}
2294 
2295         foreach (count, attribute; parameter.parameterAttributes)
2296         {
2297             if (count || hadAtAttribute) space();
2298             put(tokenRep(attribute));
2299         }
2300 
2301         if (parameter.parameterAttributes.length > 0)
2302             space();
2303 
2304         if (parameter.type !is null)
2305             format(parameter.type);
2306 
2307         if (parameter.name.type != tok!"")
2308         {
2309             space();
2310             put(parameter.name.text);
2311         }
2312 
2313         foreach(suffix; parameter.cstyle)
2314             format(suffix);
2315 
2316         if (parameter.default_)
2317         {
2318             put(" = ");
2319             format(parameter.default_);
2320         }
2321 
2322         if (parameter.vararg)
2323             put("...");
2324     }
2325 
2326     void format(const Parameters parameters)
2327     {
2328         debug(verbose) writeln("Parameters");
2329 
2330         /**
2331         Parameter[] parameters;
2332         bool hasVarargs;
2333         **/
2334 
2335         put("(");
2336         foreach (count, param; parameters.parameters)
2337         {
2338             if (count) put(", ");
2339             format(param);
2340         }
2341         if (parameters.hasVarargs)
2342         {
2343             if (parameters.parameters.length)
2344                 put(", ");
2345             put("...");
2346         }
2347         put(")");
2348     }
2349 
2350     void format(const Postblit postblit, const Attribute[] attrs = null)
2351     {
2352         debug(verbose) writeln("Postblit");
2353 
2354         /**
2355         FunctionBody functionBody;
2356         **/
2357 
2358         newThing(What.functionDecl);
2359         putAttrs(attrs);
2360         put("this(this)");
2361 
2362         foreach(attr; postblit.memberFunctionAttributes)
2363         {
2364             space();
2365             format(attr);
2366         }
2367 
2368         if (postblit.functionBody)
2369             format(postblit.functionBody);
2370         else
2371             put(";");
2372     }
2373 
2374     void format(const PowExpression powExpression)
2375     {
2376         debug(verbose) writeln("PowExpression");
2377         mixin(binary("powExpression", "^^", true));
2378     }
2379 
2380     void format(const PragmaDeclaration pragmaDeclaration, const Attribute[] attrs = null)
2381     {
2382         debug(verbose) writeln("PragmaDeclaration");
2383 
2384         /**
2385         PragmaExpression pragmaExpression;
2386         **/
2387 
2388         putAttrs(attrs);
2389         format(pragmaDeclaration.pragmaExpression);
2390         put(";");
2391     }
2392 
2393     void format(const PragmaExpression pragmaExpression)
2394     {
2395         debug(verbose) writeln("PragmaExpression");
2396 
2397         /**
2398         Token identifier;
2399         ArgumentList argumentList;
2400         **/
2401 
2402         put("pragma(");
2403         format(pragmaExpression.identifier);
2404         if (pragmaExpression.argumentList)
2405         {
2406             put(", ");
2407             format(pragmaExpression.argumentList);
2408         }
2409         put(")");
2410     }
2411 
2412     void format(const PrimaryExpression primaryExpression)
2413     {
2414         debug(verbose) writeln("PrimaryExpression");
2415 
2416         /**
2417         Token dot;
2418         Token primary;
2419         IdentifierOrTemplateInstance identifierOrTemplateInstance;
2420         Token basicType;
2421         TypeofExpression typeofExpression;
2422         TypeidExpression typeidExpression;
2423         ArrayLiteral arrayLiteral;
2424         AssocArrayLiteral assocArrayLiteral;
2425         Expression expression;
2426         IsExpression isExpression;
2427         LambdaExpression lambdaExpression;
2428         FunctionLiteralExpression functionLiteralExpression;
2429         TraitsExpression traitsExpression;
2430         MixinExpression mixinExpression;
2431         ImportExpression importExpression;
2432         Vector vector;
2433         **/
2434 
2435         with(primaryExpression)
2436         {
2437             if (dot != tok!"") put(".");
2438             if (basicType != tok!"") format(basicType);
2439             if (primary != tok!"")
2440             {
2441                 if (basicType != tok!"") put("."); // i.e. : uint.max
2442                 format(primary);
2443             }
2444 
2445             if (expression)
2446             {
2447                 put("(");
2448                 format(expression);
2449                 put(")");
2450             }
2451             else if (identifierOrTemplateInstance)
2452             {
2453                 format(identifierOrTemplateInstance);
2454             }
2455             else if (typeofExpression) format(typeofExpression);
2456             else if (typeidExpression) format(typeidExpression);
2457             else if (arrayLiteral) format(arrayLiteral);
2458             else if (assocArrayLiteral) format(assocArrayLiteral);
2459             else if (isExpression) format(isExpression);
2460             else if (lambdaExpression) format(lambdaExpression);
2461             else if (functionLiteralExpression) format(functionLiteralExpression);
2462             else if (traitsExpression) format(traitsExpression);
2463             else if (mixinExpression) format(mixinExpression);
2464             else if (importExpression) format(importExpression);
2465             else if (vector) format(vector);
2466         }
2467     }
2468 
2469     void format(const Register register)
2470     {
2471         debug(verbose) writeln("Register");
2472         assert(false);
2473     }
2474 
2475     void format(const RelExpression relExpression)
2476     {
2477         debug(verbose) writeln("RelExpression");
2478         mixin(binary("relExpression"));
2479     }
2480 
2481     void format(const ReturnStatement returnStatement)
2482     {
2483         debug(verbose) writeln("ReturnStatement");
2484 
2485         put("return");
2486         if (returnStatement.expression)
2487         {
2488             space();
2489             format(returnStatement.expression);
2490         }
2491         put(";");
2492     }
2493 
2494     void format(const ScopeGuardStatement scopeGuardStatement)
2495     {
2496         debug(verbose) writeln("ScopeGuardStatement");
2497 
2498         /**
2499         Token identifier;
2500         StatementNoCaseNoDefault statementNoCaseNoDefault;
2501         **/
2502 
2503         with(scopeGuardStatement)
2504         {
2505             put("scope(");
2506             format(identifier);
2507             put(")");
2508             indent();
2509             format(statementNoCaseNoDefault);
2510             outdent();
2511         }
2512     }
2513 
2514     void format(const SharedStaticConstructor sharedStaticConstructor, const Attribute[] attrs = null)
2515     {
2516         debug(verbose) writeln("SharedStaticConstructor");
2517 
2518         with(sharedStaticConstructor)
2519         {
2520             newThing(What.functionDecl);
2521             putComment(comment);
2522             putAttrs(attrs);
2523             put("shared static this()");
2524             format(functionBody);
2525         }
2526     }
2527 
2528     void format(const SharedStaticDestructor sharedStaticDestructor, const Attribute[] attrs = null)
2529     {
2530         debug(verbose) writeln("SharedStaticDestructor");
2531 
2532         with(sharedStaticDestructor)
2533         {
2534             newThing(What.functionDecl);
2535             putComment(comment);
2536             putAttrs(attrs);
2537             put("shared static ~this()");
2538             format(functionBody);
2539         }
2540     }
2541 
2542     void format(const ShiftExpression shiftExpression)
2543     {
2544         debug(verbose) writeln("ShiftExpression");
2545         mixin(binary("shiftExpression"));
2546     }
2547 
2548     void format(const SingleImport singleImport)
2549     {
2550         debug(verbose) writeln("SingleImport");
2551 
2552         /**
2553         Token rename;
2554         IdentifierChain identifierChain;
2555         **/
2556 
2557         if (singleImport.rename != tok!"")
2558         {
2559             format(singleImport.rename);
2560             put(" = ");
2561         }
2562         format(singleImport.identifierChain);
2563     }
2564 
2565     void format(const Statement statement)
2566     {
2567         debug(verbose) writeln("Statement");
2568 
2569         /**
2570         StatementNoCaseNoDefault statementNoCaseNoDefault;
2571         CaseStatement caseStatement;
2572         CaseRangeStatement caseRangeStatement;
2573         DefaultStatement defaultStatement;
2574         **/
2575 
2576         with(statement)
2577         {
2578             if (statementNoCaseNoDefault)
2579             {
2580                 format(statementNoCaseNoDefault);
2581                 return;
2582             }
2583 
2584             newlineIndent();
2585             if (caseStatement) format(caseStatement);
2586             else if (caseRangeStatement) format(caseRangeStatement);
2587             else if (defaultStatement) format(defaultStatement);
2588         }
2589     }
2590 
2591     void format(const StatementNoCaseNoDefault statementNoCaseNoDefault)
2592     {
2593         debug(verbose) writeln("StatementNoCaseNoDefault");
2594 
2595         string mix(string s) { return "if (" ~ s ~ ") format(" ~ s ~ ");"; }
2596 
2597         with(statementNoCaseNoDefault)
2598         {
2599             if (!blockStatement) newlineIndent();
2600 
2601             enum stmnts = TypeTuple!(
2602                 "labeledStatement",
2603                 "blockStatement",
2604                 "ifStatement",
2605                 "whileStatement",
2606                 "doStatement",
2607                 "forStatement",
2608                 "foreachStatement",
2609                 "switchStatement",
2610                 "finalSwitchStatement",
2611                 "continueStatement",
2612                 "breakStatement",
2613                 "returnStatement",
2614                 "gotoStatement",
2615                 "withStatement",
2616                 "synchronizedStatement",
2617                 "tryStatement",
2618                 "throwStatement",
2619                 "scopeGuardStatement",
2620                 "asmStatement",
2621                 "conditionalStatement",
2622                 "staticAssertStatement",
2623                 "versionSpecification",
2624                 "debugSpecification",
2625                 "expressionStatement"
2626             );
2627 
2628             foreach(s; stmnts)
2629                 mixin(mix(s));
2630         }
2631     }
2632 
2633     void format(const StaticAssertDeclaration staticAssertDeclaration, const Attribute[] attrs = null)
2634     {
2635         debug(verbose) writeln("StaticAssertDeclaration");
2636 
2637         newThing(What.other);
2638         putAttrs(attrs);
2639         format(staticAssertDeclaration.staticAssertStatement);
2640         put(";");
2641     }
2642 
2643     void format(const StaticAssertStatement staticAssertStatement)
2644     {
2645         debug(verbose) writeln("StaticAssertStatement");
2646 
2647         put("static ");
2648         format(staticAssertStatement.assertExpression);
2649     }
2650 
2651     void format(const StaticConstructor staticConstructor, const Attribute[] attrs = null)
2652     {
2653         debug(verbose) writeln("StaticConstructor");
2654 
2655         putAttrs(attrs);
2656         put("static this()");
2657         format(staticConstructor.functionBody);
2658     }
2659 
2660     void format(const StaticDestructor staticDestructor, const Attribute[] attrs = null)
2661     {
2662         debug(verbose) writeln("StaticDestructor");
2663 
2664         putAttrs(attrs);
2665         put("static ~this()");
2666         format(staticDestructor.functionBody);
2667     }
2668 
2669     void format(const StaticIfCondition staticIfCondition)
2670     {
2671         debug(verbose) writeln("StaticIfCondition");
2672 
2673         put("static if (");
2674         format(staticIfCondition.assignExpression);
2675         put(")");
2676     }
2677 
2678     void format(const StorageClass storageClass)
2679     {
2680         debug(verbose) writeln("StorageClass");
2681 
2682         /**
2683         AtAttribute atAttribute;
2684         Deprecated deprecated_;
2685         LinkageAttribute linkageAttribute;
2686         Token token;
2687         **/
2688 
2689         with(storageClass)
2690         {
2691             if (atAttribute) format(atAttribute);
2692             else if (deprecated_) format(deprecated_);
2693             else if (linkageAttribute) format(linkageAttribute);
2694             else format(token);
2695         }
2696     }
2697 
2698     void format(const StructBody structBody)
2699     {
2700         debug(verbose) writeln("StructBody");
2701 
2702         if (structBody.declarations.length > 0)
2703         {
2704             startBlock();
2705             foreach(count, decl; structBody.declarations)
2706                 format(decl);
2707             endBlock();
2708         }
2709         else
2710         {
2711             space();
2712             put("{}");
2713         }
2714     }
2715 
2716     void format(const StructDeclaration decl, const Attribute[] attrs = null)
2717     {
2718         debug(verbose) writeln("StructDeclaration");
2719 
2720         /**
2721         Token name;
2722         TemplateParameters templateParameters;
2723         Constraint constraint;
2724         StructBody structBody;
2725         string comment;
2726         **/
2727 
2728         newThing(What.aggregateDecl);
2729         putComment(decl.comment);
2730         putAttrs(attrs);
2731         put("struct ");
2732         format(decl.name);
2733 
2734         if (decl.templateParameters)
2735             format(decl.templateParameters);
2736 
2737         if (decl.constraint)
2738         {
2739             space();
2740             format(decl.constraint);
2741         }
2742 
2743         if (decl.structBody)
2744             format(decl.structBody);
2745         else
2746             put(";");
2747     }
2748 
2749     void format(const StructInitializer structInitializer)
2750     {
2751         debug(verbose) writeln("StructInitializer");
2752 
2753         put("{");
2754         format(structInitializer.structMemberInitializers);
2755         put("}");
2756     }
2757 
2758     void format(const StructMemberInitializer structMemberInitializer)
2759     {
2760         debug(verbose) writeln("StructMemberInitializer");
2761 
2762         /**
2763         Token identifier;
2764         NonVoidInitializer nonVoidInitializer;
2765         **/
2766 
2767         with(structMemberInitializer)
2768         {
2769             if (identifier != tok!"")
2770             {
2771                 format(identifier);
2772                 put(":");
2773             }
2774             format(nonVoidInitializer);
2775         }
2776     }
2777 
2778     void format(const StructMemberInitializers structMemberInitializers)
2779     {
2780         debug(verbose) writeln("StructMemberInitializers");
2781 
2782         foreach(count, mem; structMemberInitializers.structMemberInitializers)
2783         {
2784             if (count) put(", ");
2785             format(mem);
2786         }
2787     }
2788 
2789     void format(const SwitchStatement switchStatement, bool isFinal = false)
2790     {
2791         debug(verbose) writeln("SwitchStatement");
2792 
2793         /**
2794         Expression expression;
2795         Statement statement;
2796         **/
2797 
2798         with(switchStatement)
2799         {
2800             newThing(What.other);
2801             isFinal ? put(" final switch(") : put("switch(");
2802             format(expression);
2803             put(")");
2804 
2805             bool needBlock = statement.statementNoCaseNoDefault &&
2806                              !(statement.statementNoCaseNoDefault.withStatement ||
2807                                statement.statementNoCaseNoDefault.blockStatement );
2808 
2809             if (needBlock)
2810                 startBlock();
2811             format(statement);
2812             if (needBlock)
2813                 endBlock();
2814         }
2815     }
2816 
2817     void format(const Symbol symbol)
2818     {
2819         debug(verbose) writeln("Symbol");
2820 
2821         if (symbol.dot)
2822             put(".");
2823         format(symbol.identifierOrTemplateChain);
2824     }
2825 
2826     void format(const SynchronizedStatement synchronizedStatement)
2827     {
2828         debug(verbose) writeln("SynchronizedStatement");
2829 
2830         /**
2831         Expression expression;
2832         StatementNoCaseNoDefault statementNoCaseNoDefault;
2833         **/
2834 
2835         with(synchronizedStatement)
2836         {
2837             put("synchronized");
2838             if (expression)
2839             {
2840                 put("(");
2841                 format(expression);
2842                 put(")");
2843             }
2844             format(statementNoCaseNoDefault);
2845         }
2846     }
2847 
2848     void format(const TemplateAliasParameter templateAliasParameter)
2849     {
2850         debug(verbose) writeln("TemplateAliasParameter");
2851 
2852         /**
2853         Type type;
2854         Token identifier;
2855         Type colonType;
2856         AssignExpression colonExpression;
2857         Type assignType;
2858         AssignExpression assignExpression;
2859         **/
2860 
2861         with(templateAliasParameter)
2862         {
2863             put("alias ");
2864             if (type)
2865             {
2866                 format(type);
2867                 space();
2868             }
2869             format(identifier);
2870             if (colonType)
2871             {
2872                 put(" : ");
2873                 format(colonType);
2874             }
2875             else if (colonExpression)
2876             {
2877                 put(" : ");
2878                 format(colonExpression);
2879             }
2880             if (assignType)
2881             {
2882                 put(" = ");
2883                 format(assignType);
2884             }
2885             else if (assignExpression)
2886             {
2887                 put(" = ");
2888                 format(assignExpression);
2889             }
2890         }
2891     }
2892 
2893     void format(const TemplateArgument templateArgument)
2894     {
2895         debug(verbose) writeln("TemplateArgument");
2896 
2897         /**
2898         Type type;
2899         AssignExpression assignExpression;
2900         **/
2901 
2902         with(templateArgument)
2903         {
2904             if (type) format(type);
2905             if (assignExpression) format(assignExpression);
2906         }
2907     }
2908 
2909     void format(const TemplateArgumentList templateArgumentList, bool parens = true)
2910     {
2911         debug(verbose) writeln("TemplateArgumentList");
2912 
2913         if (parens) put("!(");
2914         foreach(count, arg; templateArgumentList.items)
2915         {
2916             if (count) put(", ");
2917             format(arg);
2918         }
2919         if (parens) put(")");
2920     }
2921 
2922     void format(const TemplateArguments templateArguments)
2923     {
2924         debug(verbose) writeln("TemplateArguments");
2925 
2926         /**
2927         TemplateArgumentList templateArgumentList;
2928         TemplateSingleArgument templateSingleArgument;
2929         **/
2930 
2931         with(templateArguments)
2932         {
2933             if (templateArgumentList) format(templateArgumentList);
2934             else if (templateSingleArgument) format(templateSingleArgument);
2935             else put("!()");
2936         }
2937     }
2938 
2939     void format(const TemplateDeclaration templateDeclaration, const Attribute[] attrs = null)
2940     {
2941         debug(verbose) writeln("TemplateDeclaration");
2942 
2943         /**
2944         Token name;
2945         TemplateParameters templateParameters;
2946         Constraint constraint;
2947         Declaration[] declarations;
2948         EponymousTemplateDeclaration eponymousTemplateDeclaration;
2949         string comment;
2950         **/
2951 
2952         with(templateDeclaration)
2953         {
2954             newThing(What.other);
2955             putComment(comment);
2956             putAttrs(attrs);
2957 
2958             put("template ");
2959             format(name);
2960 
2961             if (templateParameters)
2962                 format(templateParameters);
2963 
2964             if (constraint)
2965             {
2966                 space();
2967                 format(constraint);
2968             }
2969 
2970             startBlock();
2971             foreach(d; declarations)
2972                 format(d);
2973             endBlock();
2974         }
2975     }
2976 
2977     void format(const TemplateInstance templateInstance)
2978     {
2979         debug(verbose) writeln("TemplateInstance");
2980 
2981         /**
2982         Token identifier;
2983         TemplateArguments templateArguments;
2984         **/
2985 
2986         with(templateInstance)
2987         {
2988             format(identifier);
2989             if (templateArguments) format(templateArguments);
2990         }
2991     }
2992 
2993     void format(const TemplateMixinExpression templateMixinExpression)
2994     {
2995         debug(verbose) writeln("TemplateMixinExpression");
2996 
2997         /**
2998         Token identifier;
2999         TemplateArguments templateArguments;
3000         MixinTemplateName mixinTemplateName;
3001         **/
3002 
3003         with(templateMixinExpression)
3004         {
3005             put("mixin ");
3006             format(mixinTemplateName);
3007             if (templateArguments) format(templateArguments);
3008             space();
3009             format(identifier);
3010         }
3011     }
3012 
3013     void format(const TemplateParameter templateParameter)
3014     {
3015         debug(verbose) writeln("TemplateParameter");
3016 
3017         with(templateParameter)
3018         {
3019             if (templateTypeParameter)
3020                 format(templateTypeParameter);
3021             else if (templateValueParameter)
3022                 format(templateValueParameter);
3023             else if (templateAliasParameter)
3024                 format(templateAliasParameter);
3025             else if (templateTupleParameter)
3026                 format(templateTupleParameter);
3027             else if (templateThisParameter)
3028                 format(templateThisParameter);
3029         }
3030     }
3031 
3032     void format(const TemplateParameterList templateParameterList)
3033     {
3034         debug(verbose) writeln("TemplateParameterList");
3035 
3036         foreach(i, param; templateParameterList.items)
3037         {
3038             if (i) put(", ");
3039             format(param);
3040         }
3041     }
3042 
3043     void format(const TemplateParameters templateParameters)
3044     {
3045         debug(verbose) writeln("TemplateParameters");
3046 
3047         with(templateParameters)
3048         {
3049             put("(");
3050             if (templateParameterList)
3051                 format(templateParameterList);
3052             put(")");
3053         }
3054     }
3055 
3056     void format(const TemplateSingleArgument templateSingleArgument)
3057     {
3058         debug(verbose) writeln("TemplateSingleArgument");
3059 
3060         /**
3061         Token token;
3062         **/
3063 
3064         put("!");
3065         format(templateSingleArgument.token);
3066     }
3067 
3068     void format(const TemplateThisParameter templateThisParameter)
3069     {
3070         debug(verbose) writeln("TemplateThisParameter");
3071 
3072         with(templateThisParameter)
3073         {
3074             put("this ");
3075             if (templateTypeParameter)
3076                 format(templateTypeParameter);
3077         }
3078     }
3079 
3080     void format(const TemplateTupleParameter templateTupleParameter)
3081     {
3082         debug(verbose) writeln("TemplateTupleParameter");
3083 
3084         format(templateTupleParameter.identifier);
3085         put("...");
3086     }
3087 
3088     void format(const TemplateTypeParameter templateTypeParameter)
3089     {
3090         debug(verbose) writeln("TemplateTypeParameter");
3091 
3092         /**
3093         Token identifier;
3094         Type colonType;
3095         Type assignType;
3096         **/
3097 
3098         with(templateTypeParameter)
3099         {
3100             format(identifier);
3101             if (colonType)
3102             {
3103                 put(" : ");
3104                 format(colonType);
3105             }
3106             if (assignType)
3107             {
3108                 put(" = ");
3109                 format(assignType);
3110             }
3111         }
3112     }
3113 
3114     void format(const TemplateValueParameter templateValueParameter)
3115     {
3116         debug(verbose) writeln("TemplateValueParameter");
3117 
3118         /**
3119         Type type;
3120         Token identifier;
3121         Expression expression;
3122         TemplateValueParameterDefault templateValueParameterDefault;
3123         **/
3124 
3125         with(templateValueParameter)
3126         {
3127             if (type) format(type);
3128             space();
3129             format(identifier);
3130 
3131             if (assignExpression)
3132             {
3133                 put(" : ");
3134                 format(assignExpression);
3135             }
3136 
3137             if (templateValueParameterDefault)
3138             {
3139                 put(" = ");
3140                 format(templateValueParameterDefault);
3141             }
3142         }
3143     }
3144 
3145     void format(const TemplateValueParameterDefault templateValueParameterDefault)
3146     {
3147         debug(verbose) writeln("TemplateValueParameterDefault");
3148 
3149         with(templateValueParameterDefault)
3150             assignExpression ? format(assignExpression) : format(token);
3151     }
3152 
3153     void format(const TernaryExpression expr)
3154     {
3155         debug(verbose) writeln("TernaryExpression");
3156 
3157         /**
3158         ExpressionNode orOrExpression;
3159         ExpressionNode expression;
3160         ExpressionNode ternaryExpression;
3161         **/
3162 
3163         format(expr.orOrExpression);
3164 
3165         if (expr.expression && expr.ternaryExpression)
3166         {
3167             put(" ? ");
3168             format(expr.expression);
3169             put(" : ");
3170             format(expr.ternaryExpression);
3171         }
3172     }
3173 
3174     void format(const ThrowStatement throwStatement)
3175     {
3176         debug(verbose) writeln("ThrowStatement");
3177 
3178         put("throw ");
3179         assert(throwStatement.expression);
3180         format(throwStatement.expression);
3181         put(";");
3182     }
3183 
3184     void format(const Token token)
3185     {
3186         debug(verbose) writeln("Token ", tokenRep(token));
3187         put(tokenRep(token));
3188     }
3189 
3190     void format(const TraitsExpression traitExpr)
3191     {
3192         debug(verbose) writeln("TraitsExpression");
3193 
3194         /**
3195         Token identifier;
3196         TemplateArgumentList templateArgumentList;
3197         **/
3198 
3199         put("__traits(");
3200         format(traitExpr.identifier);
3201         put(", ");
3202         format(traitExpr.templateArgumentList, false);
3203         put(")");
3204     }
3205 
3206     void format(const TryStatement tryStatement)
3207     {
3208         debug(verbose) writeln("TryStatement");
3209 
3210         /**
3211         DeclarationOrStatement declarationOrStatement;
3212         Catches catches;
3213         Finally finally_;
3214         **/
3215 
3216         with(tryStatement)
3217         {
3218             newThing(What.other);
3219             put("try");
3220             maybeIndent(declarationOrStatement);
3221             if (catches) format(catches);
3222             if (finally_) format(finally_);
3223         }
3224     }
3225 
3226     void format(const Type type)
3227     {
3228         debug(verbose) writeln("Type(");
3229 
3230         /**
3231         IdType[] typeConstructors;
3232         TypeSuffix[] typeSuffixes;
3233         Type2 type2;
3234         **/
3235 
3236         foreach (count, constructor; type.typeConstructors)
3237         {
3238             if (count) space();
3239             put(tokenRep(constructor));
3240         }
3241 
3242         if (type.typeConstructors.length) space();
3243         format(type.type2);
3244 
3245         foreach (suffix; type.typeSuffixes)
3246             format(suffix);
3247 
3248         debug(verbose) writeln(")");
3249     }
3250 
3251     void format(const Type2 type2)
3252     {
3253         debug(verbose) writeln("Type2");
3254 
3255         /**
3256         IdType builtinType;
3257         Symbol symbol;
3258         TypeofExpression typeofExpression;
3259         IdentifierOrTemplateChain identifierOrTemplateChain;
3260         IdType typeConstructor;
3261         Type type;
3262         **/
3263 
3264         if (type2.symbol !is null)
3265         {
3266             format(type2.symbol);
3267         }
3268         else if (type2.typeofExpression !is null)
3269         {
3270             format(type2.typeofExpression);
3271             if (type2.identifierOrTemplateChain)
3272             {
3273                 put(".");
3274                 format(type2.identifierOrTemplateChain);
3275             }
3276             return;
3277         }
3278         else if (type2.typeConstructor != tok!"")
3279         {
3280             put(tokenRep(type2.typeConstructor));
3281             put("(");
3282             format(type2.type);
3283             put(")");
3284         }
3285         else
3286         {
3287             put(tokenRep(type2.builtinType));
3288         }
3289     }
3290 
3291     void format(const TypeSpecialization typeSpecialization)
3292     {
3293         debug(verbose) writeln("TypeSpecialization");
3294 
3295         /**
3296         Token token;
3297         Type type;
3298         **/
3299 
3300         with(typeSpecialization)
3301         {
3302             format(token);
3303             if (type) format(type);
3304         }
3305     }
3306 
3307     void format(const TypeSuffix typeSuffix)
3308     {
3309         debug(verbose) writeln("TypeSuffix");
3310 
3311         /**
3312         Token delegateOrFunction;
3313         bool star;
3314         bool array;
3315         Type type;
3316         AssignExpression low;
3317         AssignExpression high;
3318         Parameters parameters;
3319         MemberFunctionAttribute[] memberFunctionAttributes;
3320         **/
3321 
3322         if (typeSuffix.star.type != tok!"")
3323         {
3324             put("*");
3325             return;
3326         }
3327         else if (typeSuffix.array)
3328         {
3329             if (typeSuffix.type is null)
3330             {
3331                 if (typeSuffix.low is null)
3332                 {
3333                     put("[]");
3334                     return;
3335                 }
3336                 else
3337                 {
3338                     if (typeSuffix.high is null)
3339                     {
3340                         put("[");
3341                         format(typeSuffix.low);
3342                         put("]");
3343                         return;
3344                     }
3345                     else
3346                     {
3347                         put("[");
3348                         format(typeSuffix.low);
3349                         put("..");
3350                         format(typeSuffix.high);
3351                         put("]");
3352                         return;
3353                     }
3354                 }
3355             }
3356             else
3357             {
3358                 put("[");
3359                 format(typeSuffix.type);
3360                 put("]");
3361                 return;
3362             }
3363         }
3364         else
3365         {
3366             space();
3367             format(typeSuffix.delegateOrFunction);
3368             if (typeSuffix.parameters) format(typeSuffix.parameters);
3369             foreach(attr; typeSuffix.memberFunctionAttributes)
3370             {
3371                 space();
3372                 format(attr);
3373             }
3374             return;
3375         }
3376     }
3377 
3378     void format(const TypeidExpression idExpr)
3379     {
3380         debug(verbose) writeln("TypeidExpression");
3381 
3382         /**
3383         Type type;
3384         Expression expression;
3385         **/
3386 
3387         put("typeid (");
3388         idExpr.type ? format(idExpr.type) : format(idExpr.expression);
3389         put(")");
3390     }
3391 
3392     void format(const TypeofExpression typeofExpr)
3393     {
3394         debug(verbose) writeln("TypeofExpression");
3395 
3396         /**
3397         Expression expression;
3398         Token return_;
3399         **/
3400 
3401         put("typeof(");
3402         typeofExpr.expression ? format(typeofExpr.expression) : format(typeofExpr.return_);
3403         put(")");
3404     }
3405 
3406     void format(const UnaryExpression unary)
3407     {
3408         debug(verbose) writeln("UnaryExpression(");
3409 
3410         /**
3411         Type type;
3412         PrimaryExpression primaryExpression;
3413         Token prefix;
3414         Token suffix;
3415         UnaryExpression unaryExpression;
3416         NewExpression newExpression;
3417         DeleteExpression deleteExpression;
3418         CastExpression castExpression;
3419         FunctionCallExpression functionCallExpression;
3420         ArgumentList argumentList;
3421         IdentifierOrTemplateInstance identifierOrTemplateInstance;
3422         AssertExpression assertExpression;
3423         SliceExpression sliceExpression;
3424         IndexExpression indexExpression;
3425         **/
3426 
3427         with(unary)
3428         {
3429             if (prefix != tok!"") format(prefix);
3430 
3431             if (type)
3432             {
3433                 // handle things like (void*).sizeof
3434                 if (identifierOrTemplateInstance)
3435                 {
3436                     put("(");
3437                     format(type);
3438                     put(")");
3439                 }
3440                 else
3441                 {
3442                     format(type);
3443                     put("(");
3444                     if (argumentList)
3445                         format(argumentList);
3446                     put(")");
3447                 }
3448             }
3449 
3450             if (primaryExpression) format(primaryExpression);
3451             if (newExpression) format(newExpression);
3452             if (deleteExpression) format(deleteExpression);
3453             if (castExpression) format(castExpression);
3454             if (functionCallExpression) format(functionCallExpression);
3455             if (assertExpression) format(assertExpression);
3456             if (indexExpression) format(indexExpression);
3457 
3458             if (unaryExpression) format(unaryExpression);
3459             if (suffix != tok!"") format(suffix);
3460 
3461             if (identifierOrTemplateInstance)
3462             {
3463                 put(".");
3464                 format(identifierOrTemplateInstance);
3465             }
3466         }
3467 
3468         debug(verbose) writeln(")");
3469     }
3470 
3471     void format(const UnionDeclaration decl, const Attribute[] attrs = null)
3472     {
3473         debug(verbose) writeln("UnionDeclaration");
3474 
3475         /**
3476         Token name;
3477         TemplateParameters templateParameters;
3478         Constraint constraint;
3479         StructBody structBody;
3480         string comment;
3481         **/
3482 
3483         newThing(What.aggregateDecl);
3484         putComment(decl.comment);
3485         putAttrs(attrs);
3486         put("union ");
3487         format(decl.name);
3488         if (decl.templateParameters)
3489             format(decl.templateParameters);
3490         if (decl.constraint)
3491         {
3492             space();
3493             format(decl.constraint);
3494         }
3495         format(decl.structBody);
3496     }
3497 
3498     void format(const Unittest unittest_, const Attribute[] attrs = null)
3499     {
3500         debug(verbose) writeln("Unittest");
3501 
3502         /**
3503         BlockStatement blockStatement;
3504         string comment;
3505         **/
3506 
3507         newThing(What.functionDecl);
3508         putComment(unittest_.comment);
3509         putAttrs(attrs);
3510         put("unittest");
3511         format(unittest_.blockStatement);
3512     }
3513 
3514     void format(const VariableDeclaration decl, const Attribute[] attrs = null)
3515     {
3516         debug(verbose) writeln("VariableDeclaration");
3517 
3518         /**
3519         Type type;
3520         Declarator[] declarators;
3521         StorageClass storageClass;
3522         AutoDeclaration autoDeclaration;
3523         string comment;
3524         **/
3525 
3526         newThing(What.variableDecl);
3527         putComment(decl.comment);
3528         putAttrs(attrs);
3529 
3530         if (decl.autoDeclaration)
3531             format(decl.autoDeclaration);
3532         else
3533         {
3534             foreach (c; decl.storageClasses)
3535             {
3536                 format(c);
3537                 space();
3538             }
3539             if (decl.type) format(decl.type);
3540             if (decl.declarators.length) space();
3541             foreach(count, d; decl.declarators)
3542             {
3543                 if (count) put(", ");
3544                 format(d);
3545             }
3546         }
3547         put(";");
3548     }
3549 
3550     void format(const Vector vector)
3551     {
3552         debug(verbose) writeln("Vector");
3553 
3554         put("__vector(");
3555         format(vector.type);
3556         put(")");
3557     }
3558 
3559     void format(const VersionCondition versionCondition)
3560     {
3561         debug(verbose) writeln("VersionCondition");
3562 
3563         put("version (");
3564         format(versionCondition.token);
3565         put(")");
3566     }
3567 
3568     void format(const VersionSpecification ver, const Attribute[] attrs = null)
3569     {
3570         debug(verbose) writeln("VersionSpecification");
3571 
3572         newThing(What.other);
3573         putAttrs(attrs);
3574         put("version = ");
3575         format(ver.token);
3576         put(";");
3577     }
3578 
3579     void format(const WhileStatement stmt)
3580     {
3581         debug(verbose) writeln("WhileStatement");
3582 
3583         /**
3584         Expression expression;
3585         DeclarationOrStatement declarationOrStatement;
3586         **/
3587 
3588         newThing(What.other);
3589         put("while (");
3590         format(stmt.expression);
3591         put(")");
3592         maybeIndent(stmt.declarationOrStatement);
3593     }
3594 
3595     void format(const WithStatement stmt)
3596     {
3597         debug(verbose) writeln("WithStatement");
3598 
3599         /**
3600         Expression expression;
3601         StatementNoCaseNoDefault statementNoCaseNoDefault;
3602         **/
3603 
3604         space();
3605         put("with (");
3606         format(stmt.expression);
3607         put(")");
3608         format(stmt.statementNoCaseNoDefault);
3609     }
3610 
3611     void format(const XorExpression xorExpression)
3612     {
3613         debug(verbose) writeln("XorExpression");
3614         mixin(binary("xorExpression", "^"));
3615     }
3616 
3617     Sink sink;
3618 
3619 protected:
3620 
3621     import std.uni : isWhite;
3622 
3623     void indent()
3624     {
3625         indentLevel++;
3626     }
3627 
3628     void outdent()
3629     {
3630         if (indentLevel == 0)
3631             return;
3632         indentLevel--;
3633     }
3634 
3635     void putIndent()
3636     {
3637         if (!indentLevel) return;
3638         auto i = getIndent();
3639         put(i);
3640     }
3641 
3642     string getIndent()
3643     {
3644         if (useTabs)
3645         {
3646             char[] c = new char[indentLevel];
3647             c[] = '\t';
3648             return cast(string) c;
3649         }
3650         else
3651         {
3652             char[] c = new char[indentLevel * indentWidth];
3653             c[] = ' ';
3654             return cast(string) c;
3655         }
3656     }
3657 
3658     enum What
3659     {
3660         functionDecl,
3661         aggregateDecl,
3662         attributeDecl,
3663         conditionalDecl,
3664         variableDecl,
3665         importDecl,
3666         expr,
3667         loop,
3668         else_,
3669         catch_,
3670         other
3671     }
3672 
3673     void newThing(What thing)
3674     {
3675         lastThing = currentThing;
3676         currentThing = thing;
3677 
3678         with(What) {
3679 
3680             if (lastThing == importDecl && thing != importDecl)
3681             {
3682                 lineGap(1);
3683                 return;
3684             }
3685 
3686             if (lastThing == loop)
3687             {
3688                 lineGap(1);
3689                 return;
3690             }
3691 
3692             switch(thing)
3693             {
3694                 case other:
3695                     newline();
3696                     break;
3697                 case aggregateDecl:
3698                 case attributeDecl:
3699                 case functionDecl:
3700                     lineGap(1);
3701                     break;
3702                 case conditionalDecl:
3703                     lineGap(1);
3704                     break;
3705                 case variableDecl:
3706                     lineGap(1);
3707                     break;
3708                 case importDecl:
3709                     newlineIndent();
3710                     break;
3711                 case expr: break;
3712                 case catch_: goto case;
3713                 case else_:
3714                     final switch(style) with(IndentStyle)
3715                     {
3716                         case allman: newline(); break;
3717                         case otbs: space(); break;
3718                     }
3719                     break;
3720                 default: newlineIndent(); break;
3721             }
3722         }
3723     }
3724 
3725     void lineGap(int gap)
3726     {
3727         foreach (i; 0 .. gap + 1)
3728         {
3729             if (i == gap)
3730                 newlineIndent();
3731             else
3732                 newline();
3733         }
3734     }
3735 
3736     void newlineIndent()
3737     {
3738         if (ignoreNewlines)
3739         {
3740             space(); // don't do this when splitting lines
3741         }
3742         else
3743         {
3744             sink.put("\n");
3745             lineLength = 0;
3746             putIndent();
3747         }
3748     }
3749 
3750     void newline()
3751     {
3752         sink.put("\n");
3753         lineLength = 0;
3754     }
3755 
3756     void space()
3757     {
3758         put(" ");
3759     }
3760 
3761     static string binary(string symbol, string operator = null, bool nospace = false)
3762     {
3763         return "with(" ~ symbol ~ "){"
3764              ~ "format(left); if (right is null) return;"
3765              ~ (nospace ? "" : "put(` `);")
3766              ~ (operator ? "put(`" ~ operator ~ "`);" : "put(tokenRep(operator));")
3767              ~ (nospace ? "" : "put(` `);")
3768              ~ "format(right);}";
3769     }
3770 
3771     void startBlock()
3772     {
3773         final switch(style) with(IndentStyle)
3774         {
3775             case allman: newline(); break;
3776             case otbs: space(); break;
3777         }
3778         putIndent();
3779         put("{");
3780         indent();
3781     }
3782 
3783     void endBlock()
3784     {
3785         outdent();
3786         newline();
3787         putIndent();
3788         put("}");
3789     }
3790 
3791     string tokenRep(Token t)
3792     {
3793         return t.text.length ? t.text : tokenRep(t.type);
3794     }
3795 
3796     string tokenRep(IdType t)
3797     {
3798         return t ? str(t) : "";
3799     }
3800 
3801     void putComment(string c)
3802     {
3803         import std.string : splitLines;
3804         if (!c.length) return;
3805         put(c.splitLines().join("\n" ~ getIndent()));
3806         newlineIndent();
3807     }
3808 
3809     void putAttrs(const Attribute[] attrs)
3810     {
3811         if (attrs !is null)
3812         {
3813             foreach(count, attr; attrs)
3814             {
3815                 format(attr);
3816                 space();
3817             }
3818         }
3819     }
3820 
3821     void put(string s)
3822     {
3823         sink.put(s);
3824         lineLength += s.length; // TODO: tabs / spaces?
3825     }
3826 
3827     void formatCaseDecls(const DeclarationsAndStatements declsAndStmnts)
3828     {
3829         bool seenBlock = false;
3830         auto items = declsAndStmnts.declarationsAndStatements;
3831         foreach(item; items)
3832         {
3833             bool _indent = false;
3834             if (item.declaration) _indent = true;
3835             if (item.statement && item.statement.statementNoCaseNoDefault)
3836             {
3837                 if (item.statement.statementNoCaseNoDefault.blockStatement)
3838                     seenBlock = true;
3839                 else if (!item.statement.statementNoCaseNoDefault.labeledStatement)
3840                     _indent = true;
3841             }
3842             if (seenBlock) _indent = false;
3843             if (_indent) indent();
3844             format(item);
3845             if (_indent) outdent();
3846         }
3847     }
3848 
3849     bool needIndent(const Statement s)
3850     {
3851         return s.statementNoCaseNoDefault &&
3852                !s.statementNoCaseNoDefault.blockStatement;
3853     }
3854 
3855     bool needIndent(const Declaration d)
3856     {
3857         return !d.declarations.length;
3858     }
3859 
3860     bool needIndent(const DeclarationOrStatement dors)
3861     {
3862         return (dors.declaration && needIndent(dors.declaration)) ||
3863                (dors.statement && needIndent(dors.statement));
3864     }
3865 
3866     void maybeIndent(T)(const T t)
3867     {
3868         auto _indent = needIndent(t);
3869         if (_indent) indent();
3870         format(t);
3871         if (_indent) outdent();
3872     }
3873 
3874     bool isEmptyDeclaration(const Declaration decl)
3875     {
3876         with(decl)
3877         {
3878             string mix(string[] s) {
3879                 string r;
3880                 foreach(c, d; s)
3881                     r ~= (c > 0 ? "else " : "") ~ "if (" ~ d ~ ") return false;";
3882                 return r;
3883             }
3884             mixin(mix(possibleDeclarations));
3885             return attributes.length == 0 &&
3886                    declarations.length == 0;
3887         }
3888     }
3889 
3890     bool ignoreNewlines = false;
3891     bool useTabs;
3892     uint caseDepth;
3893     uint indentWidth;
3894     uint indentLevel;
3895     IndentStyle style;
3896 
3897 
3898     What lastThing, currentThing;
3899     uint lineLength;
3900     uint maxLineLength = 80;
3901 
3902     enum possibleDeclarations = [
3903         "attributeDeclaration",
3904         "importDeclaration",
3905         "functionDeclaration",
3906         "variableDeclaration",
3907         "aliasThisDeclaration",
3908         "structDeclaration",
3909         "classDeclaration",
3910         "interfaceDeclaration",
3911         "unionDeclaration",
3912         "enumDeclaration",
3913         "aliasDeclaration",
3914         "mixinDeclaration",
3915         "mixinTemplateDeclaration",
3916         "unittest_",
3917         "staticAssertDeclaration",
3918         "templateDeclaration",
3919         "constructor",
3920         "destructor",
3921         "staticConstructor",
3922         "staticDestructor",
3923         "sharedStaticDestructor",
3924         "sharedStaticConstructor",
3925         "conditionalDeclaration",
3926         "pragmaDeclaration",
3927         "versionSpecification",
3928         "invariant_",
3929         "postblit"
3930     ];
3931 }