dparse.formatter 0/1361(0%) line coverage

      
10
20
30
40
50
60
70
80
90
100
110
120
130
140
150
160
170
180
190
200
210
220
230
240
250
260
270
280
290
300
310
320
330
340
350
360
370
380
390
400
410
420
430
440
450
460
470
480
490
500
510
520
530
540
550
560
570
580
590
600
610
620
630
640
650
660
670
680
690
700
710
720
730
740
750
760
770
780
790
800
810
820
830
840
850
860
870
880
890
900
910
920
930
940
950
960
970
980
990
1000
1010
1020
1030
1040
1050
1060
1070
1080
1090
1100
1110
1120
1130
1140
1150
1160
1170
1180
1190
1200
1210
1220
1230
1240
1250
1260
1270
1280
1290
1300
1310
1320
1330
1340
1350
1360
1370
1380
1390
1400
1410
1420
1430
1440
1450
1460
1470
1480
1490
1500
1510
1520
1530
1540
1550
1560
1570
1580
1590
1600
1610
1620
1630
1640
1650
1660
1670
1680
1690
1700
1710
1720
1730
1740
1750
1760
1770
1780
1790
1800
1810
1820
1830
1840
1850
1860
1870
1880
1890
1900
1910
1920
1930
1940
1950
1960
1970
1980
1990
2000
2010
2020
2030
2040
2050
2060
2070
2080
2090
2100
2110
2120
2130
2140
2150
2160
2170
2180
2190
2200
2210
2220
2230
2240
2250
2260
2270
2280
2290
2300
2310
2320
2330
2340
2350
2360
2370
2380
2390
2400
2410
2420
2430
2440
2450
2460
2470
2480
2490
2500
2510
2520
2530
2540
2550
2560
2570
2580
2590
2600
2610
2620
2630
2640
2650
2660
2670
2680
2690
2700
2710
2720
2730
2740
2750
2760
2770
2780
2790
2800
2810
2820
2830
2840
2850
2860
2870
2880
2890
2900
2910
2920
2930
2940
2950
2960
2970
2980
2990
3000
3010
3020
3030
3040
3050
3060
3070
3080
3090
3100
3110
3120
3130
3140
3150
3160
3170
3180
3190
3200
3210
3220
3230
3240
3250
3260
3270
3280
3290
3300
3310
3320
3330
3340
3350
3360
3370
3380
3390
3400
3410
3420
3430
3440
3450
3460
3470
3480
3490
3500
3510
3520
3530
3540
3550
3560
3570
3580
3590
3600
3610
3620
3630
3640
3650
3660
3670
3680
3690
3700
3710
3720
3730
3740
3750
3760
3770
3780
3790
3800
3810
3820
3830
3840
3850
3860
3870
3880
3890
3900
3910
3920
3930
3940
3950
3960
3970
3980
3990
4000
4010
4020
4030
4040
4050
4060
4070
4080
4090
4100
4110
4120
4130
4140
4150
4160
4170
4180
4190
4200
4210
4220
4230
4240
4250
4260
4270
4280
4290
4300
4310
4320
4330
4340
4350
4360
4370
4380
4390
4400
4410
4420
4430
4440
4450
4460
4470
4480
4490
4500
4510
4520
4530
4540
4550
4560
4570
4580
4590
4600
4610
4620
4630
4640
4650
4660
4670
4680
4690
4700
4710
4720
4730
4740
4750
4760
4770
4780
4790
4800
4810
4820
4830
4840
4850
4860
4870
4880
4890
4900
4910
4920
4930
4940
4950
4960
4970
4980
4990
5000
5010
5020
5030
5040
5050
5060
5070
5080
5090
5100
5110
5120
5130
5140
5150
5160
5170
5180
5190
5200
5210
5220
5230
5240
5250
5260
5270
5280
5290
5300
5310
5320
5330
5340
5350
5360
5370
5380
5390
5400
5410
5420
5430
5440
5450
5460
5470
5480
5490
5500
5510
5520
5530
5540
5550
5560
5570
5580
5590
5600
5610
5620
5630
5640
5650
5660
5670
5680
5690
5700
5710
5720
5730
5740
5750
5760
5770
5780
5790
5800
5810
5820
5830
5840
5850
5860
5870
5880
5890
5900
5910
5920
5930
5940
5950
5960
5970
5980
5990
6000
6010
6020
6030
6040
6050
6060
6070
6080
6090
6100
6110
6120
6130
6140
6150
6160
6170
6180
6190
6200
6210
6220
6230
6240
6250
6260
6270
6280
6290
6300
6310
6320
6330
6340
6350
6360
6370
6380
6390
6400
6410
6420
6430
6440
6450
6460
6470
6480
6490
6500
6510
6520
6530
6540
6550
6560
6570
6580
6590
6600
6610
6620
6630
6640
6650
6660
6670
6680
6690
6700
6710
6720
6730
6740
6750
6760
6770
6780
6790
6800
6810
6820
6830
6840
6850
6860
6870
6880
6890
6900
6910
6920
6930
6940
6950
6960
6970
6980
6990
7000
7010
7020
7030
7040
7050
7060
7070
7080
7090
7100
7110
7120
7130
7140
7150
7160
7170
7180
7190
7200
7210
7220
7230
7240
7250
7260
7270
7280
7290
7300
7310
7320
7330
7340
7350
7360
7370
7380
7390
7400
7410
7420
7430
7440
7450
7460
7470
7480
7490
7500
7510
7520
7530
7540
7550
7560
7570
7580
7590
7600
7610
7620
7630
7640
7650
7660
7670
7680
7690
7700
7710
7720
7730
7740
7750
7760
7770
7780
7790
7800
7810
7820
7830
7840
7850
7860
7870
7880
7890
7900
7910
7920
7930
7940
7950
7960
7970
7980
7990
8000
8010
8020
8030
8040
8050
8060
8070
8080
8090
8100
8110
8120
8130
8140
8150
8160
8170
8180
8190
8200
8210
8220
8230
8240
8250
8260
8270
8280
8290
8300
8310
8320
8330
8340
8350
8360
8370
8380
8390
8400
8410
8420
8430
8440
8450
8460
8470
8480
8490
8500
8510
8520
8530
8540
8550
8560
8570
8580
8590
8600
8610
8620
8630
8640
8650
8660
8670
8680
8690
8700
8710
8720
8730
8740
8750
8760
8770
8780
8790
8800
8810
8820
8830
8840
8850
8860
8870
8880
8890
8900
8910
8920
8930
8940
8950
8960
8970
8980
8990
9000
9010
9020
9030
9040
9050
9060
9070
9080
9090
9100
9110
9120
9130
9140
9150
9160
9170
9180
9190
9200
9210
9220
9230
9240
9250
9260
9270
9280
9290
9300
9310
9320
9330
9340
9350
9360
9370
9380
9390
9400
9410
9420
9430
9440
9450
9460
9470
9480
9490
9500
9510
9520
9530
9540
9550
9560
9570
9580
9590
9600
9610
9620
9630
9640
9650
9660
9670
9680
9690
9700
9710
9720
9730
9740
9750
9760
9770
9780
9790
9800
9810
9820
9830
9840
9850
9860
9870
9880
9890
9900
9910
9920
9930
9940
9950
9960
9970
9980
9990
10000
10010
10020
10030
10040
10050
10060
10070
10080
10090
10100
10110
10120
10130
10140
10150
10160
10170
10180
10190
10200
10210
10220
10230
10240
10250
10260
10270
10280
10290
10300
10310
10320
10330
10340
10350
10360
10370
10380
10390
10400
10410
10420
10430
10440
10450
10460
10470
10480
10490
10500
10510
10520
10530
10540
10550
10560
10570
10580
10590
10600
10610
10620
10630
10640
10650
10660
10670
10680
10690
10700
10710
10720
10730
10740
10750
10760
10770
10780
10790
10800
10810
10820
10830
10840
10850
10860
10870
10880
10890
10900
10910
10920
10930
10940
10950
10960
10970
10980
10990
11000
11010
11020
11030
11040
11050
11060
11070
11080
11090
11100
11110
11120
11130
11140
11150
11160
11170
11180
11190
11200
11210
11220
11230
11240
11250
11260
11270
11280
11290
11300
11310
11320
11330
11340
11350
11360
11370
11380
11390
11400
11410
11420
11430
11440
11450
11460
11470
11480
11490
11500
11510
11520
11530
11540
11550
11560
11570
11580
11590
11600
11610
11620
11630
11640
11650
11660
11670
11680
11690
11700
11710
11720
11730
11740
11750
11760
11770
11780
11790
11800
11810
11820
11830
11840
11850
11860
11870
11880
11890
11900
11910
11920
11930
11940
11950
11960
11970
11980
11990
12000
12010
12020
12030
12040
12050
12060
12070
12080
12090
12100
12110
12120
12130
12140
12150
12160
12170
12180
12190
12200
12210
12220
12230
12240
12250
12260
12270
12280
12290
12300
12310
12320
12330
12340
12350
12360
12370
12380
12390
12400
12410
12420
12430
12440
12450
12460
12470
12480
12490
12500
12510
12520
12530
12540
12550
12560
12570
12580
12590
12600
12610
12620
12630
12640
12650
12660
12670
12680
12690
12700
12710
12720
12730
12740
12750
12760
12770
12780
12790
12800
12810
12820
12830
12840
12850
12860
12870
12880
12890
12900
12910
12920
12930
12940
12950
12960
12970
12980
12990
13000
13010
13020
13030
13040
13050
13060
13070
13080
13090
13100
13110
13120
13130
13140
13150
13160
13170
13180
13190
13200
13210
13220
13230
13240
13250
13260
13270
13280
13290
13300
13310
13320
13330
13340
13350
13360
13370
13380
13390
13400
13410
13420
13430
13440
13450
13460
13470
13480
13490
13500
13510
13520
13530
13540
13550
13560
13570
13580
13590
13600
13610
13620
13630
13640
13650
13660
13670
13680
13690
13700
13710
13720
13730
13740
13750
13760
13770
13780
13790
13800
13810
13820
13830
13840
13850
13860
13870
13880
13890
13900
13910
13920
13930
13940
13950
13960
13970
13980
13990
14000
14010
14020
14030
14040
14050
14060
14070
14080
14090
14100
14110
14120
14130
14140
14150
14160
14170
14180
14190
14200
14210
14220
14230
14240
14250
14260
14270
14280
14290
14300
14310
14320
14330
14340
14350
14360
14370
14380
14390
14400
14410
14420
14430
14440
14450
14460
14470
14480
14490
14500
14510
14520
14530
14540
14550
14560
14570
14580
14590
14600
14610
14620
14630
14640
14650
14660
14670
14680
14690
14700
14710
14720
14730
14740
14750
14760
14770
14780
14790
14800
14810
14820
14830
14840
14850
14860
14870
14880
14890
14900
14910
14920
14930
14940
14950
14960
14970
14980
14990
15000
15010
15020
15030
15040
15050
15060
15070
15080
15090
15100
15110
15120
15130
15140
15150
15160
15170
15180
15190
15200
15210
15220
15230
15240
15250
15260
15270
15280
15290
15300
15310
15320
15330
15340
15350
15360
15370
15380
15390
15400
15410
15420
15430
15440
15450
15460
15470
15480
15490
15500
15510
15520
15530
15540
15550
15560
15570
15580
15590
15600
15610
15620
15630
15640
15650
15660
15670
15680
15690
15700
15710
15720
15730
15740
15750
15760
15770
15780
15790
15800
15810
15820
15830
15840
15850
15860
15870
15880
15890
15900
15910
15920
15930
15940
15950
15960
15970
15980
15990
16000
16010
16020
16030
16040
16050
16060
16070
16080
16090
16100
16110
16120
16130
16140
16150
16160
16170
16180
16190
16200
16210
16220
16230
16240
16250
16260
16270
16280
16290
16300
16310
16320
16330
16340
16350
16360
16370
16380
16390
16400
16410
16420
16430
16440
16450
16460
16470
16480
16490
16500
16510
16520
16530
16540
16550
16560
16570
16580
16590
16600
16610
16620
16630
16640
16650
16660
16670
16680
16690
16700
16710
16720
16730
16740
16750
16760
16770
16780
16790
16800
16810
16820
16830
16840
16850
16860
16870
16880
16890
16900
16910
16920
16930
16940
16950
16960
16970
16980
16990
17000
17010
17020
17030
17040
17050
17060
17070
17080
17090
17100
17110
17120
17130
17140
17150
17160
17170
17180
17190
17200
17210
17220
17230
17240
17250
17260
17270
17280
17290
17300
17310
17320
17330
17340
17350
17360
17370
17380
17390
17400
17410
17420
17430
17440
17450
17460
17470
17480
17490
17500
17510
17520
17530
17540
17550
17560
17570
17580
17590
17600
17610
17620
17630
17640
17650
17660
17670
17680
17690
17700
17710
17720
17730
17740
17750
17760
17770
17780
17790
17800
17810
17820
17830
17840
17850
17860
17870
17880
17890
17900
17910
17920
17930
17940
17950
17960
17970
17980
17990
18000
18010
18020
18030
18040
18050
18060
18070
18080
18090
18100
18110
18120
18130
18140
18150
18160
18170
18180
18190
18200
18210
18220
18230
18240
18250
18260
18270
18280
18290
18300
18310
18320
18330
18340
18350
18360
18370
18380
18390
18400
18410
18420
18430
18440
18450
18460
18470
18480
18490
18500
18510
18520
18530
18540
18550
18560
18570
18580
18590
18600
18610
18620
18630
18640
18650
18660
18670
18680
18690
18700
18710
18720
18730
18740
18750
18760
18770
18780
18790
18800
18810
18820
18830
18840
18850
18860
18870
18880
18890
18900
18910
18920
18930
18940
18950
18960
18970
18980
18990
19000
19010
19020
19030
19040
19050
19060
19070
19080
19090
19100
19110
19120
19130
19140
19150
19160
19170
19180
19190
19200
19210
19220
19230
19240
19250
19260
19270
19280
19290
19300
19310
19320
19330
19340
19350
19360
19370
19380
19390
19400
19410
19420
19430
19440
19450
19460
19470
19480
19490
19500
19510
19520
19530
19540
19550
19560
19570
19580
19590
19600
19610
19620
19630
19640
19650
19660
19670
19680
19690
19700
19710
19720
19730
19740
19750
19760
19770
19780
19790
19800
19810
19820
19830
19840
19850
19860
19870
19880
19890
19900
19910
19920
19930
19940
19950
19960
19970
19980
19990
20000
20010
20020
20030
20040
20050
20060
20070
20080
20090
20100
20110
20120
20130
20140
20150
20160
20170
20180
20190
20200
20210
20220
20230
20240
20250
20260
20270
20280
20290
20300
20310
20320
20330
20340
20350
20360
20370
20380
20390
20400
20410
20420
20430
20440
20450
20460
20470
20480
20490
20500
20510
20520
20530
20540
20550
20560
20570
20580
20590
20600
20610
20620
20630
20640
20650
20660
20670
20680
20690
20700
20710
20720
20730
20740
20750
20760
20770
20780
20790
20800
20810
20820
20830
20840
20850
20860
20870
20880
20890
20900
20910
20920
20930
20940
20950
20960
20970
20980
20990
21000
21010
21020
21030
21040
21050
21060
21070
21080
21090
21100
21110
21120
21130
21140
21150
21160
21170
21180
21190
21200
21210
21220
21230
21240
21250
21260
21270
21280
21290
21300
21310
21320
21330
21340
21350
21360
21370
21380
21390
21400
21410
21420
21430
21440
21450
21460
21470
21480
21490
21500
21510
21520
21530
21540
21550
21560
21570
21580
21590
21600
21610
21620
21630
21640
21650
21660
21670
21680
21690
21700
21710
21720
21730
21740
21750
21760
21770
21780
21790
21800
21810
21820
21830
21840
21850
21860
21870
21880
21890
21900
21910
21920
21930
21940
21950
21960
21970
21980
21990
22000
22010
22020
22030
22040
22050
22060
22070
22080
22090
22100
22110
22120
22130
22140
22150
22160
22170
22180
22190
22200
22210
22220
22230
22240
22250
22260
22270
22280
22290
22300
22310
22320
22330
22340
22350
22360
22370
22380
22390
22400
22410
22420
22430
22440
22450
22460
22470
22480
22490
22500
22510
22520
22530
22540
22550
22560
22570
22580
22590
22600
22610
22620
22630
22640
22650
22660
22670
22680
22690
22700
22710
22720
22730
22740
22750
22760
22770
22780
22790
22800
22810
22820
22830
22840
22850
22860
22870
22880
22890
22900
22910
22920
22930
22940
22950
22960
22970
22980
22990
23000
23010
23020
23030
23040
23050
23060
23070
23080
23090
23100
23110
23120
23130
23140
23150
23160
23170
23180
23190
23200
23210
23220
23230
23240
23250
23260
23270
23280
23290
23300
23310
23320
23330
23340
23350
23360
23370
23380
23390
23400
23410
23420
23430
23440
23450
23460
23470
23480
23490
23500
23510
23520
23530
23540
23550
23560
23570
23580
23590
23600
23610
23620
23630
23640
23650
23660
23670
23680
23690
23700
23710
23720
23730
23740
23750
23760
23770
23780
23790
23800
23810
23820
23830
23840
23850
23860
23870
23880
23890
23900
23910
23920
23930
23940
23950
23960
23970
23980
23990
24000
24010
24020
24030
24040
24050
24060
24070
24080
24090
24100
24110
24120
24130
24140
24150
24160
24170
24180
24190
24200
24210
24220
24230
24240
24250
24260
24270
24280
24290
24300
24310
24320
24330
24340
24350
24360
24370
24380
24390
24400
24410
24420
24430
24440
24450
24460
24470
24480
24490
24500
24510
24520
24530
24540
24550
24560
24570
24580
24590
24600
24610
24620
24630
24640
24650
24660
24670
24680
24690
24700
24710
24720
24730
24740
24750
24760
24770
24780
24790
24800
24810
24820
24830
24840
24850
24860
24870
24880
24890
24900
24910
24920
24930
24940
24950
24960
24970
24980
24990
25000
25010
25020
25030
25040
25050
25060
25070
25080
25090
25100
25110
25120
25130
25140
25150
25160
25170
25180
25190
25200
25210
25220
25230
25240
25250
25260
25270
25280
25290
25300
25310
25320
25330
25340
25350
25360
25370
25380
25390
25400
25410
25420
25430
25440
25450
25460
25470
25480
25490
25500
25510
25520
25530
25540
25550
25560
25570
25580
25590
25600
25610
25620
25630
25640
25650
25660
25670
25680
25690
25700
25710
25720
25730
25740
25750
25760
25770
25780
25790
25800
25810
25820
25830
25840
25850
25860
25870
25880
25890
25900
25910
25920
25930
25940
25950
25960
25970
25980
25990
26000
26010
26020
26030
26040
26050
26060
26070
26080
26090
26100
26110
26120
26130
26140
26150
26160
26170
26180
26190
26200
26210
26220
26230
26240
26250
26260
26270
26280
26290
26300
26310
26320
26330
26340
26350
26360
26370
26380
26390
26400
26410
26420
26430
26440
26450
26460
26470
26480
26490
26500
26510
26520
26530
26540
26550
26560
26570
26580
26590
26600
26610
26620
26630
26640
26650
26660
26670
26680
26690
26700
26710
26720
26730
26740
26750
26760
26770
26780
26790
26800
26810
26820
26830
26840
26850
26860
26870
26880
26890
26900
26910
26920
26930
26940
26950
26960
26970
26980
26990
27000
27010
27020
27030
27040
27050
27060
27070
27080
27090
27100
27110
27120
27130
27140
27150
27160
27170
27180
27190
27200
27210
27220
27230
27240
27250
27260
27270
27280
27290
27300
27310
27320
27330
27340
27350
27360
27370
27380
27390
27400
27410
27420
27430
27440
27450
27460
27470
27480
27490
27500
27510
27520
27530
27540
27550
27560
27570
27580
27590
27600
27610
27620
27630
27640
27650
27660
27670
27680
27690
27700
27710
27720
27730
27740
27750
27760
27770
27780
27790
27800
27810
27820
27830
27840
27850
27860
27870
27880
27890
27900
27910
27920
27930
27940
27950
27960
27970
27980
27990
28000
28010
28020
28030
28040
28050
28060
28070
28080
28090
28100
28110
28120
28130
28140
28150
28160
28170
28180
28190
28200
28210
28220
28230
28240
28250
28260
28270
28280
28290
28300
28310
28320
28330
28340
28350
28360
28370
28380
28390
28400
28410
28420
28430
28440
28450
28460
28470
28480
28490
28500
28510
28520
28530
28540
28550
28560
28570
28580
28590
28600
28610
28620
28630
28640
28650
28660
28670
28680
28690
28700
28710
28720
28730
28740
28750
28760
28770
28780
28790
28800
28810
28820
28830
28840
28850
28860
28870
28880
28890
28900
28910
28920
28930
28940
28950
28960
28970
28980
28990
29000
29010
29020
29030
29040
29050
29060
29070
29080
29090
29100
29110
29120
29130
29140
29150
29160
29170
29180
29190
29200
29210
29220
29230
29240
29250
29260
29270
29280
29290
29300
29310
29320
29330
29340
29350
29360
29370
29380
29390
29400
29410
29420
29430
29440
29450
29460
29470
29480
29490
29500
29510
29520
29530
29540
29550
29560
29570
29580
29590
29600
29610
29620
29630
29640
29650
29660
29670
29680
29690
29700
29710
29720
29730
29740
29750
29760
29770
29780
29790
29800
29810
29820
29830
29840
29850
29860
29870
29880
29890
29900
29910
29920
29930
29940
29950
29960
29970
29980
29990
30000
30010
30020
30030
30040
30050
30060
30070
30080
30090
30100
30110
30120
30130
30140
30150
30160
30170
30180
30190
30200
30210
30220
30230
30240
30250
30260
30270
30280
30290
30300
30310
30320
30330
30340
30350
30360
30370
30380
30390
30400
30410
30420
30430
30440
30450
30460
30470
30480
30490
30500
30510
30520
30530
30540
30550
30560
30570
30580
30590
30600
30610
30620
30630
30640
30650
30660
30670
30680
30690
30700
30710
30720
30730
30740
30750
30760
30770
30780
30790
30800
30810
30820
30830
30840
30850
30860
30870
30880
30890
30900
30910
30920
30930
30940
30950
30960
30970
30980
30990
31000
31010
31020
31030
31040
31050
31060
31070
31080
31090
31100
31110
31120
31130
31140
31150
31160
31170
31180
31190
31200
31210
31220
31230
31240
31250
31260
31270
31280
31290
31300
31310
31320
31330
31340
31350
31360
31370
31380
31390
31400
31410
31420
31430
31440
31450
31460
31470
31480
31490
31500
31510
31520
31530
31540
31550
31560
31570
31580
31590
31600
31610
31620
31630
31640
31650
31660
31670
31680
31690
31700
31710
31720
31730
31740
31750
31760
31770
31780
31790
31800
31810
31820
31830
31840
31850
31860
31870
31880
31890
31900
31910
31920
31930
31940
31950
31960
31970
31980
31990
32000
32010
32020
32030
32040
32050
32060
32070
32080
32090
32100
32110
32120
32130
32140
32150
32160
32170
32180
32190
32200
32210
32220
32230
32240
32250
32260
32270
32280
32290
32300
32310
32320
32330
32340
32350
32360
32370
32380
32390
32400
32410
32420
32430
32440
32450
32460
32470
32480
32490
32500
32510
32520
32530
32540
32550
32560
32570
32580
32590
32600
32610
32620
32630
32640
32650
32660
32670
32680
32690
32700
32710
32720
32730
32740
32750
32760
32770
32780
32790
32800
32810
32820
32830
32840
32850
32860
32870
32880
32890
32900
32910
32920
32930
32940
32950
32960
32970
32980
32990
33000
33010
33020
33030
33040
33050
33060
33070
33080
33090
33100
33110
33120
33130
33140
33150
33160
33170
33180
33190
33200
33210
33220
33230
33240
33250
33260
33270
33280
33290
33300
33310
33320
33330
33340
33350
33360
33370
33380
33390
33400
33410
33420
33430
33440
33450
33460
33470
33480
33490
33500
33510
33520
33530
33540
33550
33560
33570
33580
33590
33600
33610
33620
33630
33640
33650
33660
33670
33680
33690
33700
33710
33720
33730
33740
33750
33760
33770
33780
33790
33800
33810
33820
33830
33840
33850
33860
33870
33880
33890
33900
33910
33920
33930
33940
33950
33960
33970
33980
33990
34000
34010
34020
34030
34040
34050
34060
34070
34080
34090
34100
34110
34120
34130
34140
34150
34160
34170
34180
34190
34200
34210
34220
34230
34240
34250
34260
34270
34280
34290
34300
34310
34320
34330
34340
34350
34360
34370
34380
34390
34400
34410
34420
34430
34440
34450
34460
34470
34480
34490
34500
34510
34520
34530
34540
34550
34560
34570
34580
34590
34600
34610
34620
34630
34640
34650
34660
34670
34680
34690
34700
34710
34720
34730
34740
34750
34760
34770
34780
34790
34800
34810
34820
34830
34840
34850
34860
34870
34880
34890
34900
34910
34920
34930
34940
34950
34960
34970
34980
34990
35000
35010
35020
35030
35040
35050
35060
35070
35080
35090
35100
35110
35120
35130
35140
35150
35160
35170
35180
35190
35200
35210
35220
35230
35240
35250
35260
35270
35280
35290
35300
35310
35320
35330
35340
35350
35360
35370
35380
35390
35400
35410
35420
35430
35440
35450
35460
35470
35480
35490
35500
35510
35520
35530
35540
35550
35560
35570
35580
35590
35600
35610
35620
35630
35640
35650
35660
35670
35680
35690
35700
35710
35720
35730
35740
35750
35760
35770
35780
35790
35800
35810
35820
35830
35840
35850
35860
35870
35880
35890
35900
35910
35920
35930
35940
35950
35960
35970
35980
35990
36000
36010
36020
36030
36040
36050
36060
36070
36080
36090
36100
36110
36120
36130
36140
36150
36160
36170
36180
36190
36200
36210
36220
36230
36240
36250
36260
36270
36280
36290
36300
36310
36320
36330
36340
36350
36360
36370
36380
36390
36400
36410
36420
36430
36440
36450
36460
36470
36480
36490
36500
36510
36520
36530
36540
36550
36560
36570
36580
36590
36600
36610
36620
36630
36640
36650
36660
36670
36680
36690
36700
36710
36720
36730
36740
36750
36760
36770
36780
36790
36800
36810
36820
36830
36840
36850
36860
36870
36880
36890
36900
36910
36920
36930
36940
36950
36960
36970
36980
36990
37000
37010
37020
37030
37040
37050
37060
37070
37080
37090
37100
37110
37120
37130
37140
37150
37160
37170
37180
37190
37200
37210
37220
37230
37240
37250
37260
37270
37280
37290
37300
37310
37320
37330
37340
37350
37360
37370
37380
37390
37400
37410
37420
37430
37440
37450
37460
37470
37480
37490
37500
37510
37520
37530
37540
37550
37560
37570
37580
37590
37600
37610
37620
37630
37640
37650
37660
37670
37680
37690
37700
37710
37720
37730
37740
37750
37760
37770
37780
37790
37800
37810
37820
37830
37840
37850
37860
37870
37880
37890
37900
37910
37920
37930
37940
37950
37960
37970
37980
37990
38000
38010
38020
38030
38040
38050
38060
38070
38080
38090
38100
38110
38120
38130
38140
38150
38160
38170
38180
38190
38200
38210
38220
38230
38240
38250
38260
38270
38280
38290
38300
38310
38320
38330
38340
38350
38360
38370
38380
38390
38400
38410
38420
38430
38440
38450
38460
38470
38480
38490
38500
38510
38520
38530
38540
38550
38560
38570
38580
38590
38600
38610
38620
38630
38640
38650
38660
38670
38680
38690
38700
38710
38720
38730
38740
38750
38760
38770
38780
38790
38800
38810
38820
38830
38840
38850
38860
38870
38880
38890
38900
38910
38920
38930
38940
38950
38960
38970
38980
38990
39000
39010
39020
39030
39040
39050
39060
39070
39080
39090
39100
39110
39120
39130
39140
39150
39160
39170
39180
39190
39200
39210
39220
39230
39240
39250
39260
39270
39280
39290
39300
39310
39320
39330
39340
39350
39360
39370
39380
39390
39400
39410
39420
39430
39440
39450
39460
39470
39480
39490
39500
39510
39520
39530
39540
39550
39560
39570
39580
39590
39600
39610
39620
39630
39640
39650
39660
39670
39680
39690
39700
39710
39720
39730
39740
39750
39760
39770
39780
39790
39800
39810
39820
39830
39840
39850
39860
39870
39880
39890
39900
39910
39920
39930
39940
39950
39960
39970
39980
39990
40000
40010
40020
40030
40040
40050
40060
40070
40080
40090
40100
40110
40120
40130
40140
40150
40160
40170
40180
40190
40200
40210
40220
40230
40240
40250
40260
40270
40280
40290
40300
40310
40320
40330
40340
40350
40360
40370
40380
40390
40400
40410
40420
40430
40440
40450
40460
40470
40480
40490
40500
40510
40520
40530
40540
40550
40560
40570
40580
40590
40600
40610
40620
40630
40640
40650
40660
40670
40680
40690
40700
40710
40720
40730
40740
40750
40760
40770
40780
40790
40800
40810
40820
40830
40840
40850
40860
40870
40880
40890
40900
40910
40920
40930
40940
40950
40960
40970
40980
40990
41000
41010
41020
41030
41040
41050
41060
41070
41080
41090
41100
41110
41120
41130
41140
41150
41160
41170
41180
41190
41200
41210
41220
41230
41240
41250
41260
41270
41280
41290
41300
41310
41320
41330
41340
41350
41360
41370
41380
41390
41400
41410
41420
41430
41440
41450
41460
41470
41480
41490
41500
41510
41520
41530
41540
41550
41560
41570
41580
41590
41600
41610
41620
41630
41640
41650
41660
41670
41680
41690
41700
41710
41720
41730
41740
41750
41760
41770
41780
41790
41800
41810
41820
41830
41840
41850
41860
41870
41880
41890
41900
41910
41920
41930
41940
41950
41960
41970
41980
41990
42000
42010
42020
42030
42040
42050
42060
42070
42080
42090
42100
42110
42120
42130
42140
42150
42160
42170
42180
42190
42200
42210
42220
42230
42240
42250
42260
42270
42280
42290
42300
42310
42320
42330
42340
42350
42360
42370
42380
42390
42400
42410
42420
42430
42440
42450
42460
42470
42480
42490
42500
42510
42520
42530
42540
42550
42560
42570
42580
42590
42600
42610
42620
42630
#!dmd -g module dparse.formatter; import std.algorithm; import std.range; import std.stdio; import std.typetuple:TypeTuple; import dparse.ast; import dparse.lexer; version (unittest) { import dparse.parser; import dparse.rollback_allocator; import std.array : Appender; import std.algorithm : canFind; } //debug = verbose; /** * The only brace styles worth using. */ enum IndentStyle { /** * --- * if (something) * { * foo(); * bar(); * } * else * { * bar(); * baz(); * } * --- */ allman, /** * --- * if (something) { * foo(); * bar(); * } else { * bar(); * baz(); * } * --- */ otbs, } /** * */ void format(Sink, T)(Sink sink, T node, bool useTabs = false, IndentStyle style = IndentStyle.allman, uint indentWith = 4) { Formatter!Sink formatter = new Formatter!(Sink)(sink, useTabs, style, indentWith); formatter.format(node); } /// class Formatter(Sink) { /** * Params: * sink = the output range that the formatted source code is placed in * useTabs = if true, tabs are used for indent levels instead of spaces * style = the brace style * indentWidth = the number of spaces used for indentation if useTabs is false */ this(Sink sink, bool useTabs = false, IndentStyle style = IndentStyle.allman, uint indentWidth = 4) { this.sink = sink; this.useTabs = useTabs; this.style = style; this.indentWidth = indentWidth; } /// void format(const AddExpression addExpression) { debug(verbose) writeln("AddExpression"); mixin(binary("addExpression")); } /// void format(const AliasDeclaration aliasDeclaration, const Attribute[] attrs = null) { debug(verbose) writeln("AliasDeclaration"); /** LinkageAttribute linkageAttribute; Type type; Token name; AliasInitializer[] initializers; string comment; Parameters parameters; MemberFunctionAttribute[] memberFunctionAttributes; **/ with(aliasDeclaration) { newThing(What.other); putComment(comment); putAttrs(attrs); put("alias "); if (initializers.length) // alias ident = a, ident2 = b, etc { foreach(count, init; initializers) { if (count) put(", "); format(init); } } else { foreach (storageClass; storageClasses) { format(storageClass); space(); } if (type) { format(type); space(); } if (declaratorIdentifierList) { format(declaratorIdentifierList); } if (parameters) { format(parameters); } foreach(a; memberFunctionAttributes) { space(); format(a); } } put(";"); } } void format(const AliasInitializer aliasInitializer) { debug(verbose) writeln("AliasInitializer"); /** Token name; StorageClass[] storageClasses; TemplateParameters templateParameters; Type type; FunctionLiteralExpression functionLiteralExpression; Parameters parameters; MemberFunctionAttribute[] memberFunctionAttributes; */ with(aliasInitializer) { format(name); if (templateParameters) format(templateParameters); put(" = "); if (type) format(type); if (functionLiteralExpression) format(functionLiteralExpression); if (parameters) format(parameters); foreach(att; memberFunctionAttributes) { space(); format(att); } } } void format(const AliasThisDeclaration decl, const Attribute[] attrs = null) { debug(verbose) writeln("AliasThisDeclaration"); /** Token identifier; **/ putAttrs(attrs); put("alias "); format(decl.identifier); put(" this;"); } void format(const AlignAttribute alignAttribute) { debug(verbose) writeln("AlignAttribute"); /** Token intLiteral; **/ put("align"); if (alignAttribute.assignExpression !is null) { put("("); format(alignAttribute.assignExpression); put(")"); } } void format(const AndAndExpression andAndExpression) { debug(verbose) writeln("AndAndExpression"); with(andAndExpression) { format(left); if (right) { put(" && "); format(right); } } } void format(const AndExpression andExpression) { debug(verbose) writeln("AndExpression"); with(andExpression) { format(left); if (right) { put(" & "); format(right); } } } void format(const ArgumentList argumentList) { debug(verbose) writeln("ArgumentList"); foreach(count, arg; argumentList.items) { if (count) put(", "); format(arg); } } void format(const Arguments arguments) { debug(verbose) writeln("Arguments"); put("("); if (arguments.argumentList) format(arguments.argumentList); put(")"); } void format(const ArrayInitializer arrayInitializer) { debug(verbose) writeln("ArrayInitializer"); /** ArrayMemberInitialization[] arrayMemberInitializations; **/ put("["); foreach(count, init; arrayInitializer.arrayMemberInitializations) { format(init); if (count < arrayInitializer.arrayMemberInitializations.length - 1) put(", "); } put("]"); } void format(const ArrayLiteral arrayLiteral) { debug(verbose) writeln("ArrayLiteral"); /** ArgumentList argumentList; **/ put("["); if (arrayLiteral.argumentList) format(arrayLiteral.argumentList); put("]"); } void format(const ArrayMemberInitialization arrayMemberInitialization) { debug(verbose) writeln("ArrayMemberInitialization"); /** AssignExpression assignExpression; NonVoidInitializer nonVoidInitializer; **/ with(arrayMemberInitialization) { if (assignExpression) { format(assignExpression); put(":"); } if (nonVoidInitializer) format(nonVoidInitializer); } } void format(const AsmAddExp asmAddExp) { assert(false); } void format(const AsmAndExp asmAndExp) { assert(false); } void format(const AsmBrExp asmBrExp) { assert(false); } void format(const AsmEqualExp asmEqualExp) { assert(false); } void format(const AsmExp asmExp) { assert(false); } void format(const AsmInstruction asmInstruction) { assert(false); } void format(const AsmLogAndExp asmLogAndExp) { assert(false); } void format(const AsmLogOrExp asmLogOrExp) { assert(false); } void format(const AsmMulExp asmMulExp) { assert(false); } void format(const AsmOrExp asmOrExp) { assert(false); } void format(const AsmPrimaryExp asmPrimaryExp) { assert(false); } void format(const AsmRelExp asmRelExp) { assert(false); } void format(const AsmShiftExp asmShiftExp) { assert(false); } void format(const AsmStatement asmStatement) { assert(false); } void format(const AsmTypePrefix asmTypePrefix) { assert(false); } void format(const AsmUnaExp asmUnaExp) { assert(false); } void format(const AsmXorExp asmXorExp) { assert(false); } void format(const AssertArguments assertArguments) { debug(verbose) writeln("AssertExpression"); /** AssignExpression assertion; AssignExpression message; **/ with(assertArguments) { format(assertion); if (message) { put(", "); format(message); } } } void format(const AssertExpression assertExpression) { debug(verbose) writeln("AssertExpression"); /** AssertArguments assertArguments; **/ with(assertExpression) { put("assert ("); format(assertArguments); put(")"); } } void format(const AssignExpression assignExpression) { debug(verbose) writeln("AssignExpression"); /** ExpressionNode ternaryExpression; ExpressionNode assignExpression; IdType operator; **/ if (assignExpression.ternaryExpression) format(assignExpression.ternaryExpression); if(assignExpression.expression) { space(); put(tokenRep(assignExpression.operator)); space(); format(assignExpression.expression); } } void format(const AssocArrayLiteral assocArrayLiteral) { debug(verbose) writeln("AssocArrayLiteral"); /** KeyValuePairs keyValuePairs; **/ put("["); format(assocArrayLiteral.keyValuePairs); put("]"); } void format(const AtAttribute atAttribute) { debug(verbose) writeln("AtAttribute"); /** FunctionCallExpression functionCallExpression; ArgumentList argumentList; Token identifier; **/ with(atAttribute) { put("@"); format(identifier); if(argumentList) format(argumentList); } } void format(const Attribute att) { debug(verbose) writeln("Attribute"); /** LinkageAttribute linkageAttribute; AlignAttribute alignAttribute; PragmaExpression pragmaExpression; StorageClass storageClass; IdType attribute; **/ with(att) { if (pragmaExpression) format(pragmaExpression); if (attribute.type != tok!"") put(tokenRep(attribute.type)); if (identifierChain) { put("("); format(identifierChain); put(")"); } if (deprecated_) format(deprecated_); if (atAttribute) format(atAttribute); if (linkageAttribute) format(linkageAttribute); } } void format(const AttributeDeclaration decl, const Attribute[] attrs = null) { debug(verbose) writeln("AttributeDeclaration"); auto cIndent = indentLevel; outdent(); newThing(What.attributeDecl); putAttrs(attrs); format(decl.attribute); put(":"); indentLevel = cIndent; } void format(const AutoDeclaration decl) { debug(verbose) writeln("AutoDeclaration"); /** StorageClasses[] storageClasses; Token[] identifiers; Initializer[] initializers; **/ foreach(sc; decl.storageClasses) { format(sc); space(); } // zip doesn't work here, dmd 2.064.2 foreach(i, part; decl.parts) { if (i > 0) put(", "); format(part.identifier); if (part.templateParameters) format(part.templateParameters); put(" = "); format(part.initializer); } put(";"); } void format(const BlockStatement blockStatement) { debug(verbose) writeln("BlockStatement"); if (blockStatement.declarationsAndStatements is null) { space(); put("{}"); } else { startBlock(); format(blockStatement.declarationsAndStatements); endBlock(); } } void format(const BreakStatement breakStatement) { debug(verbose) writeln("BreakStatement"); put("break"); if (breakStatement.label != tok!"") { space(); format(breakStatement.label); } put(";"); } void format(const BaseClass baseClass) { debug(verbose) writeln("BaseClass"); with(baseClass) { if (type2) format(type2); } } void format(const BaseClassList baseClassList) { debug(verbose) writeln("BaseClassList"); put(" : "); foreach(count, item; baseClassList.items) { format(item); if (count < baseClassList.items.length - 1) put(", "); } } void format(const CaseRangeStatement caseRangeStatement) { debug(verbose) writeln("CaseRangeStatement"); /** AssignExpression low; AssignExpression high; DeclarationsAndStatements declarationsAndStatements; **/ with(caseRangeStatement) { if (low) { put("case "); format(low); put(": .. "); } put("case "); format(high); put(":"); formatCaseDecls(declarationsAndStatements); } } void format(const CaseStatement caseStatement) { debug(verbose) writeln("CaseStatement"); /** ArgumentList argumentList; DeclarationsAndStatements declarationsAndStatements; **/ with(caseStatement) { if (argumentList) { put("case "); format(argumentList); put(":"); } formatCaseDecls(declarationsAndStatements); } } void format(const CastExpression castExpression) { debug(verbose) writeln("CastExpression"); /** Type type; CastQualifier castQualifier; UnaryExpression unaryExpression; **/ with(castExpression) { put("cast("); if (castQualifier) { format(castQualifier); space(); } if (type) format(type); put(")"); if (unaryExpression) format(unaryExpression); } } void format(const CastQualifier qual) { debug(verbose) writeln("CastQualifier"); /** Token first; Token second; **/ format(qual.first); if (qual.second != tok!"") { space(); format(qual.second); } } void format(const Catch catch_) { debug(verbose) writeln("Catch"); /** Type type; Token identifier; DeclarationOrStatement declarationOrStatement; **/ with(catch_) { newThing(What.catch_); put("catch("); format(type); if (identifier != tok!"") { space(); format(identifier); } put(")"); if (declarationOrStatement) maybeIndent(declarationOrStatement); } } void format(const Catches catches) { debug(verbose) writeln("Catches"); /** Catch[] catches; LastCatch lastCatch; **/ foreach(c; catches.catches) format(c); if (catches.lastCatch) format(catches.lastCatch); } void format(const ClassDeclaration decl, const Attribute[] attrs = null) { debug(verbose) writeln("ClassDeclaration"); /** Token name; TemplateParameters templateParameters; Constraint constraint; BaseClassList baseClassList; StructBody structBody; string comment; **/ newThing(What.aggregateDecl); putComment(decl.comment); putAttrs(attrs); put("class "); format(decl.name); if (decl.templateParameters) format(decl.templateParameters); if (decl.constraint) { space(); format(decl.constraint); } if (decl.baseClassList) { format(decl.baseClassList); } format(decl.structBody); } void format(const CmpExpression cmpExpression) { debug(verbose) writeln("CmpExpression"); /** ExpressionNode shiftExpression; ExpressionNode equalExpression; ExpressionNode identityExpression; ExpressionNode relExpression; ExpressionNode inExpression; **/ with(cmpExpression) { if (shiftExpression) format(shiftExpression); else if (equalExpression) format(equalExpression); else if (identityExpression) format(identityExpression); else if (relExpression) format(relExpression); else if (inExpression) format(inExpression); } } void format(const CompileCondition compileCondition) { debug(verbose) writeln("CompileCondition"); /** VersionCondition versionCondition; DebugCondition debugCondition; StaticIfCondition staticIfCondition; **/ with(compileCondition) { if (versionCondition) format(versionCondition); else if (debugCondition) format(debugCondition); else if (staticIfCondition) format(staticIfCondition); } } void format(const ConditionalDeclaration decl, const Attribute[] attrs = null) { debug(verbose) writeln("ConditionalDeclaration"); /** CompileCondition compileCondition; Declaration[] trueDeclarations; Declaration[] falseDeclaration; **/ newThing(What.conditionalDecl); putAttrs(attrs); format(decl.compileCondition); if (decl.trueDeclarations.length > 1) { startBlock(); foreach (d; decl.trueDeclarations) format(d); endBlock(); } else if (decl.trueDeclarations.length == 1) maybeIndent(decl.trueDeclarations[0]); else put("{}"); if (decl.falseDeclarations.length > 0) put("else"); if (decl.falseDeclarations.length > 1) { startBlock(); foreach (d; decl.falseDeclarations) format(d); endBlock(); } else if (decl.falseDeclarations.length == 1) maybeIndent(decl.falseDeclarations[0]); } void format(const ConditionalStatement stmnt) { debug(verbose) writeln("ConditionalStatement"); /** CompileCondition compileCondition; DeclarationOrStatement trueStatement; DeclarationOrStatement falseStatement; **/ newThing(What.conditionalDecl); if (stmnt.compileCondition) format(stmnt.compileCondition); if (stmnt.trueStatement) maybeIndent(stmnt.trueStatement); if (stmnt.falseStatement) { newThing(What.else_); put("else "); // else if... if (stmnt.falseStatement.statement && stmnt.falseStatement.statement.statementNoCaseNoDefault && stmnt.falseStatement.statement.statementNoCaseNoDefault.conditionalStatement) { format(stmnt.falseStatement.statement.statementNoCaseNoDefault.conditionalStatement); return; } maybeIndent(stmnt.falseStatement); } } void format(const Constraint constraint) { debug(verbose) writeln("Constraint"); if (constraint.expression) { indent(); newline(); put("if("); format(constraint.expression); put(")"); outdent(); } } void format(const Constructor constructor, const Attribute[] attrs = null) { debug(verbose) writeln("Constructor"); /** Parameters parameters; FunctionBody functionBody; Constraint constraint; MemberFunctionAttribute[] memberFunctionAttributes; TemplateParameters templateParameters; size_t location; string comment; **/ newThing(What.functionDecl); putComment(constructor.comment); putAttrs(attrs); put("this"); if (constructor.templateParameters) format(constructor.templateParameters); if (constructor.parameters) format(constructor.parameters); foreach(att; constructor.memberFunctionAttributes) { space(); format(att); } if (constructor.constraint) { space(); format(constructor.constraint); } if (constructor.functionBody) format(constructor.functionBody); else put(";"); } void format(const ContinueStatement continueStatement) { debug(verbose) writeln("ContinueStatement"); put("continue"); if (continueStatement.label != tok!"") { space(); format(continueStatement.label); } put(";"); } void format(const DebugCondition debugCondition) { debug(verbose) writeln("DebugCondition"); put("debug"); if (debugCondition.identifierOrInteger != tok!"") { put("("); format(debugCondition.identifierOrInteger); put(")"); } } void format(const DebugSpecification debugSpecification) { debug(verbose) writeln("DebugSpecification"); newThing(What.other); put("debug = "); format(debugSpecification.identifierOrInteger); put(";"); } void format(const Declaration declaration) { debug(verbose) writeln("Declaration"); with(declaration) { string mix(string[] s) { string r; foreach(c, d; s) r ~= (c > 0 ? "else " : "") ~ "if (" ~ d ~ ") { format(" ~ d ~ ", attributes); }"; return r; } mixin(mix(possibleDeclarations)); if (declarations.length) { putAttrs(attributes); startBlock(); foreach(d; declarations) format(d); endBlock(); } } } void format(const DeclarationOrStatement declarationsOrStatement) { debug(verbose) writeln("DeclarationOrStatement"); with(declarationsOrStatement) declaration !is null ? format(declaration) : format(statement); } void format(const DeclarationsAndStatements declarationsAndStatements) { debug(verbose) writeln("DeclarationsAndStatements"); foreach(ds; declarationsAndStatements.declarationsAndStatements) format(ds); } void format(const Declarator declarator) { debug(verbose) writeln("Declarator"); /** Token name; Initializer initializer; **/ format(declarator.name); foreach(suffix; declarator.cstyle) format(suffix); if (declarator.templateParameters) format(declarator.templateParameters); if (declarator.initializer) { put(" = "); format(declarator.initializer); } } void format(const DefaultStatement defaultStatement) { debug(verbose) writeln("DefaultStatement"); /** DeclarationsAndStatements declarationsAndStatements; **/ put("default:"); formatCaseDecls(defaultStatement.declarationsAndStatements); } void format(const DeleteExpression deleteExpression) { debug(verbose) writeln("DeleteExpression"); put("delete "); format(deleteExpression.unaryExpression); } void format(const DeleteStatement deleteStatement) { debug(verbose) writeln("DeleteStatement"); format(deleteStatement.deleteExpression); put(";"); } void format(const Deprecated deprecated_) { debug (verbose) writeln("Deprecated"); put("deprecated"); if (deprecated_.assignExpression !is null) { put("("); format(deprecated_.assignExpression); put(")"); } } void format(const Destructor destructor, const Attribute[] attrs = null) { debug(verbose) writeln("Destructor"); /** FunctionBody functionBody; **/ newThing(What.functionDecl); putAttrs(attrs); put("~this()"); if (destructor.functionBody) format(destructor.functionBody); else put(";"); } void format(const DoStatement doStatement) { debug(verbose) writeln("DoStatement"); /** StatementNoCaseNoDefault statementNoCaseNoDefault; Expression expression; **/ with(doStatement) { newThing(What.other); put("do"); if (statementNoCaseNoDefault) format(statementNoCaseNoDefault); space(); put("while ("); format(expression); put(");"); } } void format(const EnumBody enumBody) { debug(verbose) writeln("EnumBody"); newline(); startBlock(); foreach(count, member; enumBody.enumMembers) { format(member); if (count < enumBody.enumMembers.length - 1) put(","); if (member.comment.length) { space(); put(member.comment); } } endBlock(); } void format(const EnumDeclaration enumDeclaration, const Attribute[] attrs = null) { debug(verbose) writeln("EnumDeclaration"); /** Token name; Type type; EnumBody enumBody; string comment; **/ with(enumDeclaration) { newThing(What.aggregateDecl); putComment(comment); putAttrs(attrs); put("enum "); if (name != tok!"") { format(name); space(); } if (type) { put(": "); format(type); space(); } if (enumBody) format(enumBody); } } void format(const EnumMember enumMember) { debug(verbose) writeln("EnumMember"); /** Token name; Type type; AssignExpression assignExpression; string comment; **/ with(enumMember) { enumMemberAttributes.each!(a => format(a)); newline(); if (type) format(type); format(name); if (assignExpression) { put(" = "); format(assignExpression); } } } void format(const EnumMemberAttribute ema) { if (ema.atAttribute) format(ema.atAttribute); else if (ema.deprecated_) format(ema.deprecated_); } void format(const EponymousTemplateDeclaration decl) { debug(verbose) writeln("EponymousTemplateDeclaration"); /** Token name; TemplateParameters templateParameters; AssignExpression assignExpression; **/ put("enum "); put(tokenRep(decl.name)); if (decl.templateParameters) format(decl.templateParameters); if (decl.assignExpression) { put(" = "); format(decl.assignExpression); } put(";"); } void format(const EqualExpression equalExpression) { debug(verbose) writeln("EqualExpression"); mixin(binary("equalExpression")); } void format(const Expression expression) { debug(verbose) writeln("Expression"); foreach(count, item; expression.items) { if (count) put(", "); format(item); } } void format(const ExpressionNode n) { debug(verbose) writeln("ExpressionNode"); if (cast(AddExpression) n) format(cast(AddExpression) n); else if (cast(AndAndExpression) n) format(cast(AndAndExpression) n); else if (cast(AndExpression) n) format(cast(AndExpression) n); else if (cast(AsmAddExp) n) format(cast(AsmAddExp) n); else if (cast(AsmAndExp) n) format(cast(AsmAndExp) n); else if (cast(AsmEqualExp) n) format(cast(AsmEqualExp) n); else if (cast(AsmLogAndExp) n) format(cast(AsmLogAndExp) n); else if (cast(AsmLogOrExp) n) format(cast(AsmLogOrExp) n); else if (cast(AsmMulExp) n) format(cast(AsmMulExp) n); else if (cast(AsmOrExp) n) format(cast(AsmOrExp) n); else if (cast(AsmRelExp) n) format(cast(AsmRelExp) n); else if (cast(AsmShiftExp) n) format(cast(AsmShiftExp) n); else if (cast(AssertExpression) n) format(cast(AssertExpression) n); else if (cast(AssignExpression) n) format(cast(AssignExpression) n); else if (cast(CmpExpression) n) format(cast(CmpExpression) n); else if (cast(DeleteExpression) n) format(cast(DeleteExpression) n); else if (cast(EqualExpression) n) format(cast(EqualExpression) n); else if (cast(Expression) n) format(cast(Expression) n); else if (cast(FunctionCallExpression) n) format(cast(FunctionCallExpression) n); else if (cast(FunctionLiteralExpression) n) format(cast(FunctionLiteralExpression) n); else if (cast(IdentityExpression) n) format(cast(IdentityExpression) n); else if (cast(ImportExpression) n) format(cast(ImportExpression) n); else if (cast(IndexExpression) n) format(cast(IndexExpression) n); else if (cast(InExpression) n) format(cast(InExpression) n); else if (cast(IsExpression) n) format(cast(IsExpression) n); else if (cast(MixinExpression) n) format(cast(MixinExpression) n); else if (cast(MulExpression) n) format(cast(MulExpression) n); else if (cast(NewAnonClassExpression) n) format(cast(NewAnonClassExpression) n); else if (cast(NewExpression) n) format(cast(NewExpression) n); else if (cast(OrExpression) n) format(cast(OrExpression) n); else if (cast(OrOrExpression) n) format(cast(OrOrExpression) n); else if (cast(PowExpression) n) format(cast(PowExpression) n); else if (cast(PragmaExpression) n) format(cast(PragmaExpression) n); else if (cast(PrimaryExpression) n) format(cast(PrimaryExpression) n); else if (cast(RelExpression) n) format(cast(RelExpression) n); else if (cast(ShiftExpression) n) format(cast(ShiftExpression) n); else if (cast(TemplateMixinExpression) n) format(cast(TemplateMixinExpression) n); else if (cast(TernaryExpression) n) format(cast(TernaryExpression) n); else if (cast(TraitsExpression) n) format(cast(TraitsExpression) n); else if (cast(TypeidExpression) n) format(cast(TypeidExpression) n); else if (cast(TypeofExpression) n) format(cast(TypeofExpression) n); else if (cast(UnaryExpression) n) format(cast(UnaryExpression) n); else if (cast(XorExpression) n) format(cast(XorExpression) n); } void format(const ExpressionStatement expressionStatement) { debug(verbose) writeln("ExpressionStatement"); if (expressionStatement.expression) format(expressionStatement.expression); put(";"); } void format(const FinalSwitchStatement finalSwitchStatement) { debug(verbose) writeln("FinalSwitchStatement"); format(finalSwitchStatement.switchStatement, true); } void format(const Finally finally_) { debug(verbose) writeln("Finally"); put("finally"); format(finally_.declarationOrStatement); } void format(const ForStatement forStatement) { debug(verbose) writeln("ForStatement"); /** DeclarationOrStatement initialization; ExpressionStatement test; Expression increment; DeclarationOrStatement declarationOrStatement; **/ with(forStatement) { newThing(What.other); put("for ("); if (initialization) format(initialization); else put(";"); space(); if (test) format(test); put(";"); space(); if (increment) format(increment); put(")"); if (declarationOrStatement) maybeIndent(declarationOrStatement); } } void format(const ForeachStatement foreachStatement) { debug(verbose) writeln("ForeachStatement"); /** IdType type; ForeachTypeList foreachTypeList; ForeachType foreachType; Expression low; Expression high; DeclarationOrStatement declarationOrStatement; size_t startIndex; **/ with(foreachStatement) { newThing(What.loop); if (type) put(tokenRep(type)); else assert(false); put(" ("); if (foreachTypeList) format(foreachTypeList); else if (foreachType) format(foreachType); put("; "); if (low) format(low); if (high) { put(".."); format(high); } put(")"); format(declarationOrStatement); } } void format(const ForeachType foreachType) { debug(verbose) writeln("ForeachType"); /** IdType[] typeConstructors; Type type; Token identifier; **/ with(foreachType) { foreach(tp; typeConstructors) { if (tp) put(tokenRep(tp)); space(); } if (type) { format(type); space(); } format(identifier); } } void format(const ForeachTypeList foreachTypeList) { debug(verbose) writeln("ForeachTypeList"); /** ForeachType[] items; **/ foreach(count, item; foreachTypeList.items) { format(item); if (count < foreachTypeList.items.length - 1) put(", "); } } void format(const FunctionAttribute functionAttribute) { debug(verbose) writeln("FunctionAttribute"); /** Token token; AtAttribute atAttribute; **/ with(functionAttribute) { if (token != tok!"") { format(token); space(); } if (atAttribute) format(atAttribute); } } void format(const FunctionBody functionBody) { debug(verbose) writeln("FunctionBody"); with(functionBody) { if (specifiedFunctionBody) format(specifiedFunctionBody); if (missingFunctionBody) format(missingFunctionBody); } } void format(const FunctionCallExpression functionCallExpression) { debug(verbose) writeln("FunctionCallExpression"); /** Type type; UnaryExpression unaryExpression; TemplateArguments templateArguments; Arguments arguments; **/ with(functionCallExpression) { if (type) format(type); if (unaryExpression) format(unaryExpression); if (templateArguments) format(templateArguments); if (arguments) format(arguments); } } void format(const FunctionContract functionContract) { debug(verbose) writeln("FunctionContract"); /** InOutContractExpression inOutContractExpression; InOutStatement inOutStatement; **/ with(functionContract) { if (inOutContractExpression) format(inOutContractExpression); if (inOutStatement) format(inOutStatement); } } void format(const FunctionDeclaration decl, const Attribute[] attrs = null) { debug(verbose) writeln("FunctionDeclaration"); /** bool hasAuto; bool hasRef; **/ newThing(What.functionDecl); putComment(decl.comment); putAttrs(attrs); foreach (sc; decl.storageClasses) format(sc); if (decl.returnType) format(decl.returnType); space(); format(decl.name); if (decl.templateParameters) format(decl.templateParameters); if (decl.parameters) format(decl.parameters); foreach(attr; decl.memberFunctionAttributes) { space(); format(attr); } if (decl.constraint) { space(); format(decl.constraint); } if (decl.functionBody) format(decl.functionBody); else put(";"); } void format(const FunctionLiteralExpression functionLiteralExpression) { debug(verbose) writeln("FunctionLiteralExpression"); /** ExpressionNode assignExpression; FunctionAttribute[] functionAttributes; SpecifiedFunctionBody specifiedFunctionBody; IdType functionOrDelegate; MemberFunctionAttribute[] memberFunctionAttributes; Parameters parameters; Token identifier; Type returnType; bool isReturnRef; **/ with(functionLiteralExpression) { put(tokenRep(functionOrDelegate)); if (isReturnRef) put("ref "); //if (returnType || parameters) // space(); if (returnType) format(returnType); if (parameters) format(parameters); foreach(att; memberFunctionAttributes) { space(); format(att); } ignoreNewlines = true; if (specifiedFunctionBody) format(specifiedFunctionBody); else { format(identifier); put(" => "); format(assignExpression); } ignoreNewlines = false; } } void format(const GotoStatement gotoStatement) { debug(verbose) writeln("GotoStatement"); put("goto "); gotoStatement.label != tok!"" ? put(tokenRep(gotoStatement.label)) : format(gotoStatement.expression); put(";"); } void format(const IdentifierChain identifierChain) { debug(verbose) writeln("IdentifierChain"); foreach(count, ident; identifierChain.identifiers) { if (count) put("."); put(ident.text); } } void format(const DeclaratorIdentifierList declaratorIdentifierList) { debug(verbose) writeln("DeclaratorIdentifierList"); foreach(count, ident; declaratorIdentifierList.identifiers) { if (count) put(", "); put(ident.text); } } void format(const TypeIdentifierPart typeIdentifierPart) { debug(verbose) writeln("TypeIdentifierPart"); if (typeIdentifierPart.dot) { put("."); } if (typeIdentifierPart.identifierOrTemplateInstance) { format(typeIdentifierPart.identifierOrTemplateInstance); } if (typeIdentifierPart.indexer) { put("["); format(typeIdentifierPart.indexer); put("]"); } if (typeIdentifierPart.typeIdentifierPart) { put("."); format(typeIdentifierPart.typeIdentifierPart); } } void format(const IdentifierOrTemplateChain identifierOrTemplateChain) { debug(verbose) writeln("IdentifierOrTemplateChain"); with(identifierOrTemplateChain) { foreach(count, ident; identifiersOrTemplateInstances) { if (count) put("."); format(ident); } } } void format(const IdentifierOrTemplateInstance identifierOrTemplateInstance) { debug(verbose) writeln("IdentifierOrTemplateInstance"); with(identifierOrTemplateInstance) { format(identifier); if (templateInstance) format(templateInstance); } } void format(const IdentityExpression identityExpression) { debug(verbose) writeln("IdentityExpression"); with(identityExpression) { if (left) format(left); put(negated ? " !is " : " is "); if (right) format(right); } } void format(const IfStatement ifStatement) { debug(verbose) writeln("IfStatement"); /** IdType[] typeCtors; Type type; Token identifier; Expression expression; DeclarationOrStatement thenStatement; DeclarationOrStatement elseStatement; **/ with(ifStatement) { bool isAuto = identifier != tok!"" && !type; bool isAssign = isAuto || type || typeCtors.length; put("if ("); if (isAuto) put("auto "); foreach(tct; typeCtors) { put(str(tct)); space(); } if (type) { format(type); space(); } if (identifier != tok!"") { format(identifier); space(); } if (isAssign) put("= "); if (expression) format(expression); put(")"); if (thenStatement) maybeIndent(thenStatement); if (elseStatement) { newThing(What.else_); put("else "); if (elseStatement.statement && elseStatement.statement.statementNoCaseNoDefault && elseStatement.statement.statementNoCaseNoDefault.ifStatement) { // this is to stop automatic newlineIndent format(elseStatement.statement.statementNoCaseNoDefault.ifStatement); } else maybeIndent(elseStatement); } } } void format(const ImportBind importBind) { debug(verbose) writeln("ImportBind"); format(importBind.left); if (importBind.right != tok!"") { put(" = "); format(importBind.right); } } void format(const ImportBindings importBindings) { debug(verbose) writeln("ImportBindings"); /** SingleImport singleImport; ImportBind[] importBinds; **/ with(importBindings) { format(singleImport); put(" : "); foreach(count, bind; importBinds) { if (count) put(", "); format(bind); } } } void format(const ImportDeclaration importDeclaration, const Attribute[] attrs = null) { debug(verbose) writeln("ImportDeclaration"); /** SingleImport[] singleImports; ImportBindings importBindings; **/ with(importDeclaration) { newThing(What.importDecl); putAttrs(attrs); put("import "); if (singleImports.length == 1) { format(singleImports[0]); } else if (singleImports.length > 1) { indent(); newlineIndent(); foreach(count, imp; singleImports) { format(imp); if (count < singleImports.length - 1) { put(", "); newlineIndent(); } } outdent(); } if (importBindings) { if (singleImports.length) put(", "); format(importBindings); } put(";"); } } void format(const ImportExpression importExpression) { debug(verbose) writeln("ImportExpression"); put("import ("); format(importExpression.assignExpression); put(");"); } void format(const Index index) { format(index.low); if (index.high !is null) { put(" .. "); format(index.high); } } void format(const IndexExpression indexExpression) { debug(verbose) writeln("IndexExpression"); /** UnaryExpression unaryExpression; ArgumentList argumentList; **/ with(indexExpression) { format(indexExpression.unaryExpression); put("["); foreach (i, index; indexes) { if (i != 0) put(", "); format(index); } put("]"); } } void format(const InContractExpression expression) { debug(verbose) writeln("InContractExpression"); newlineIndent(); put("in ("); format(expression.assertArguments); put(")"); } void format(const InExpression inExpression) { debug(verbose) writeln("InExpression"); with(inExpression) { if (left) format(left); put(negated ? " !in " : " in "); if (right) format(right); } } void format(const InOutContractExpression inOutContractExpression) { debug(verbose) writeln("InOutContractExpression"); with(inOutContractExpression) { if (inContractExpression) format(inContractExpression); if (outContractExpression) format(outContractExpression); } } void format(const InOutStatement inOutStatement) { debug(verbose) writeln("InOutStatement"); with(inOutStatement) { if (inStatement) format(inStatement); if (outStatement) format(outStatement); } } void format(const InStatement inStatement) { debug(verbose) writeln("InStatement"); newlineIndent(); put("in"); format(inStatement.blockStatement); } void format(const Initialize initialize) { debug(verbose) writeln("Initialize"); assert(false); } void format(const Initializer initializer) { debug(verbose) writeln("Initializer"); initializer.nonVoidInitializer ? format(initializer.nonVoidInitializer) : put("void"); } void format(const InterfaceDeclaration interfaceDeclaration, const Attribute[] attrs = null) { debug(verbose) writeln("InterfaceDeclaration"); /** Token name; TemplateParameters templateParameters; Constraint constraint; BaseClassList baseClassList; StructBody structBody; string comment; **/ with(interfaceDeclaration) { newThing(What.aggregateDecl); putComment(comment); putAttrs(attrs); put("interface "); format(name); if (templateParameters) format(templateParameters); if (constraint) { space(); format(constraint); } if (baseClassList) { format(baseClassList); } if (structBody) format(structBody); else put(";"); } } void format(const Invariant invariant_, const Attribute[] attrs = null) { debug(verbose) writeln("Invariant"); /** BlockStatement blockStatement; string comment; **/ putComment(invariant_.comment); putAttrs(attrs); put("invariant("); if (invariant_.blockStatement !is null) { put(")"); format(invariant_.blockStatement); } else { format(invariant_.assertArguments); put(")"); } } void format(const IsExpression isExpression) { debug(verbose) writeln("IsExpression"); /** Type type; Token identifier; TypeSpecialization typeSpecialization; TemplateParameterList templateParameterList; IdType equalsOrColon; **/ with(isExpression) { put("is("); if (type) format(type); if (identifier != tok!"") { space(); format(identifier); } if (equalsOrColon) { space(); put(tokenRep(equalsOrColon)); space(); } if (typeSpecialization) format(typeSpecialization); if (templateParameterList) { put(", "); format(templateParameterList); } put(")"); } } void format(const KeyValuePair keyValuePair) { debug(verbose) writeln("KeyValuePair"); /** AssignExpression key; AssignExpression value; **/ format(keyValuePair.key); put(":"); format(keyValuePair.value); } void format(const KeyValuePairs keyValuePairs) { debug(verbose) writeln("KeyValuePairs"); /** KeyValuePair[] keyValuePairs; **/ foreach(count, pair; keyValuePairs.keyValuePairs) { format(pair); if (count + 1 < keyValuePairs.keyValuePairs.length) put(", "); } } void format(const LabeledStatement stmt) { debug(verbose) writeln("LabeledStatement"); /** Token identifier; DeclarationOrStatement declarationOrStatement; **/ format(stmt.identifier); put(":"); if (stmt.declarationOrStatement) format(stmt.declarationOrStatement); } void format(const LastCatch lastCatch) { debug(verbose) writeln("LastCatch"); put("catch"); format(lastCatch.statementNoCaseNoDefault); } void format(const LinkageAttribute linkageAttribute) { debug(verbose) writeln("LinkageAttribute"); /** Token identifier; bool hasPlusPlus; IdentifierChain identifierChain; **/ put("extern ("); format(linkageAttribute.identifier); if (linkageAttribute.identifier.text == "Objective") put("-C"); if (linkageAttribute.hasPlusPlus) { put("++"); if (linkageAttribute.typeIdentifierPart) { put(", "); format(linkageAttribute.typeIdentifierPart); } else if (linkageAttribute.classOrStruct == tok!"class") put(", class"); else if (linkageAttribute.classOrStruct == tok!"struct") put(", struct"); } put(")"); } void format(const MemberFunctionAttribute memberFunctionAttribute) { debug(verbose) writeln("MemberFunctionAttribute"); /** IdType tokenType; AtAttribute atAttribute; **/ with(memberFunctionAttribute) { if (tokenType) put(tokenRep(tokenType)); else format(atAttribute); } } void format(const MissingFunctionBody missingFunctionBody) { debug(verbose) writeln("MissingFunctionBody"); with(missingFunctionBody) { foreach (contract; functionContracts) format(contract); put(";"); } } void format(const MixinDeclaration mixinDeclaration, const Attribute[] attrs = null) { debug(verbose) writeln("MixinDeclaration"); /** MixinExpression mixinExpression; TemplateMixinExpression templateMixinExpression; **/ with(mixinDeclaration) { putAttrs(attrs); if (mixinExpression) format(mixinExpression); else format(templateMixinExpression); put(";"); } } void format(const MixinExpression mixinExpression) { debug(verbose) writeln("MixinExpression"); put("mixin ("); format(mixinExpression.argumentList); put(")"); } void format(const MixinTemplateDeclaration mixinTemplateDeclaration, const Attribute[] attrs = null) { debug(verbose) writeln("MixinTemplateDeclaration"); putAttrs(attrs); put("mixin "); format(mixinTemplateDeclaration.templateDeclaration); } void format(const MixinTemplateName mixinTemplateName) { debug(verbose) writeln("MixinTemplateName"); /** Symbol symbol; IdentifierOrTemplateChain identifierOrTemplateChain; TypeofExpression typeofExpression; **/ with(mixinTemplateName) { if (symbol) format(symbol); else { format(typeofExpression); put("."); format(identifierOrTemplateChain); } } } void format(const Module module_) { debug(verbose) writeln("Module"); /** ModuleDeclaration moduleDeclaration; Declaration[] declarations; **/ format(module_.moduleDeclaration); foreach(decl; module_.declarations) format(decl); } void format(const ModuleDeclaration moduleDeclaration) { debug(verbose) writeln("ModuleDeclaration"); if (moduleDeclaration is null) return; /** IdentifierChain moduleName; **/ put("module "); format(moduleDeclaration.moduleName); put(";"); newlineIndent(); newlineIndent(); } void format(const MulExpression mulExpression) { debug(verbose) writeln("MulExpression"); mixin(binary("mulExpression")); } void format(const NewAnonClassExpression newAnonClassExpression) { debug(verbose) writeln("NewAnonClassExpression"); /** Arguments allocatorArguments; Arguments constructorArguments; BaseClassList baseClassList; StructBody structBody; **/ with(newAnonClassExpression) { if (allocatorArguments) { format(allocatorArguments); space(); } put("class"); if (constructorArguments) format(constructorArguments); if (baseClassList) { space(); format(baseClassList); } format(structBody); } } void format(const NewExpression newExpression) { debug(verbose) writeln("NewExpression"); /** Type type; NewAnonClassExpression newAnonClassExpression; Arguments arguments; AssignExpression assignExpression; **/ with(newExpression) { put("new "); if (newAnonClassExpression) format(newAnonClassExpression); else { if (type) format(type); if (arguments) format(arguments); if (assignExpression) { put("["); format(assignExpression); put("]"); } } } } void format(const NonVoidInitializer nonVoidInitializer) { debug(verbose) writeln("NonVoidInitializer"); /** AssignExpression assignExpression; ArrayInitializer arrayInitializer; StructInitializer structInitializer; **/ with(nonVoidInitializer) { if (assignExpression) format(assignExpression); else if (arrayInitializer) format(arrayInitializer); else if (structInitializer) format(structInitializer); } } void format(const Operands operands) { debug(verbose) writeln("Operands"); assert(false); } void format(const OrExpression orExpression) { debug(verbose) writeln("OrExpression"); mixin(binary("orExpression", "|")); } void format(const OrOrExpression orOrExpression) { debug(verbose) writeln("OrOrExpression"); mixin(binary("orOrExpression", "||")); } void format(const OutContractExpression expression) { debug(verbose) writeln("OutContractExpression"); newlineIndent(); put("out ("); if (expression.parameter != tok!"") format(expression.parameter); put("; "); format(expression.assertArguments); put(")"); } void format(const OutStatement stmnt) { debug(verbose) writeln("OutStatement"); /** Token parameter; BlockStatement blockStatement; **/ newlineIndent(); put("out"); if (stmnt.parameter != tok!"") { put(" ("); format(stmnt.parameter); put(")"); } format(stmnt.blockStatement); } void format(const ParameterAttribute pa) { debug(verbose) writeln("ParameterAttribute"); if (pa.atAttribute) format(pa.atAttribute); else put(tokenRep(pa.idType)); } void format(const Parameter parameter) { debug(verbose) writeln("Parameter"); /** ParameterAttribute[] parameterAttributes; Type type; Token name; bool vararg; AssignExpression default_; TypeSuffix[] cstyle; **/ foreach (count, attribute; parameter.parameterAttributes) { if (count) space(); format(attribute); } if (parameter.parameterAttributes.length > 0) space(); if (parameter.type !is null) format(parameter.type); if (parameter.name.type != tok!"") { space(); put(parameter.name.text); } foreach(suffix; parameter.cstyle) format(suffix); if (parameter.default_) { put(" = "); format(parameter.default_); } if (parameter.vararg) put("..."); } void format(const Parameters parameters) { debug(verbose) writeln("Parameters"); /** Parameter[] parameters; bool hasVarargs; **/ put("("); foreach (count, param; parameters.parameters) { if (count) put(", "); format(param); } if (parameters.hasVarargs) { if (parameters.parameters.length) put(", "); put("..."); } put(")"); } void format(const Postblit postblit, const Attribute[] attrs = null) { debug(verbose) writeln("Postblit"); /** FunctionBody functionBody; **/ newThing(What.functionDecl); putAttrs(attrs); put("this(this)"); foreach(attr; postblit.memberFunctionAttributes) { space(); format(attr); } if (postblit.functionBody) format(postblit.functionBody); else put(";"); } void format(const PowExpression powExpression) { debug(verbose) writeln("PowExpression"); mixin(binary("powExpression", "^^", true)); } void format(const PragmaDeclaration pragmaDeclaration, const Attribute[] attrs = null) { debug(verbose) writeln("PragmaDeclaration"); /** PragmaExpression pragmaExpression; **/ putAttrs(attrs); format(pragmaDeclaration.pragmaExpression); put(";"); } void format(const PragmaExpression pragmaExpression) { debug(verbose) writeln("PragmaExpression"); /** Token identifier; ArgumentList argumentList; **/ put("pragma("); format(pragmaExpression.identifier); if (pragmaExpression.argumentList) { put(", "); format(pragmaExpression.argumentList); } put(")"); } void format(const PrimaryExpression primaryExpression) { debug(verbose) writeln("PrimaryExpression"); /** Token dot; Token primary; IdentifierOrTemplateInstance identifierOrTemplateInstance; Token basicType; TypeofExpression typeofExpression; TypeidExpression typeidExpression; ArrayLiteral arrayLiteral; AssocArrayLiteral assocArrayLiteral; Expression expression; IsExpression isExpression; FunctionLiteralExpression functionLiteralExpression; TraitsExpression traitsExpression; MixinExpression mixinExpression; ImportExpression importExpression; Vector vector; Type type; Token typeConstructor; Arguments arguments; **/ with(primaryExpression) { if (dot != tok!"") put("."); if (basicType != tok!"") format(basicType); if (primary != tok!"") { if (basicType != tok!"") put("."); // i.e. : uint.max format(primary); } if (expression) { put("("); format(expression); put(")"); } else if (identifierOrTemplateInstance) { format(identifierOrTemplateInstance); } else if (typeofExpression) format(typeofExpression); else if (typeidExpression) format(typeidExpression); else if (arrayLiteral) format(arrayLiteral); else if (assocArrayLiteral) format(assocArrayLiteral); else if (isExpression) format(isExpression); else if (functionLiteralExpression) format(functionLiteralExpression); else if (traitsExpression) format(traitsExpression); else if (mixinExpression) format(mixinExpression); else if (importExpression) format(importExpression); else if (vector) format(vector); else if (type) format(type); else if (arguments) format(arguments); } } void format(const Register register) { debug(verbose) writeln("Register"); assert(false); } void format(const RelExpression relExpression) { debug(verbose) writeln("RelExpression"); mixin(binary("relExpression")); } void format(const ReturnStatement returnStatement) { debug(verbose) writeln("ReturnStatement"); put("return"); if (returnStatement.expression) { space(); format(returnStatement.expression); } put(";"); } void format(const ScopeGuardStatement scopeGuardStatement) { debug(verbose) writeln("ScopeGuardStatement"); /** Token identifier; StatementNoCaseNoDefault statementNoCaseNoDefault; **/ with(scopeGuardStatement) { put("scope("); format(identifier); put(")"); indent(); format(statementNoCaseNoDefault); outdent(); } } void format(const SharedStaticConstructor sharedStaticConstructor, const Attribute[] attrs = null) { debug(verbose) writeln("SharedStaticConstructor"); with(sharedStaticConstructor) { newThing(What.functionDecl); putComment(comment); putAttrs(attrs); put("shared static this()"); format(functionBody); } } void format(const SharedStaticDestructor sharedStaticDestructor, const Attribute[] attrs = null) { debug(verbose) writeln("SharedStaticDestructor"); with(sharedStaticDestructor) { newThing(What.functionDecl); putComment(comment); putAttrs(attrs); put("shared static ~this()"); format(functionBody); } } void format(const ShiftExpression shiftExpression) { debug(verbose) writeln("ShiftExpression"); mixin(binary("shiftExpression")); } void format(const ShortenedFunctionBody shortenedFunctionBody) { debug(verbose) writeln("ShortenedFunctionBody"); put("=> "); format(shortenedFunctionBody.expression); put(";"); } void format(const SingleImport singleImport) { debug(verbose) writeln("SingleImport"); /** Token rename; IdentifierChain identifierChain; **/ if (singleImport.rename != tok!"") { format(singleImport.rename); put(" = "); } format(singleImport.identifierChain); } void format(const SpecifiedFunctionBody specifiedFunctionBody) { debug(verbose) writeln("SpecifiedFunctionBody"); with(specifiedFunctionBody) { foreach (contract; functionContracts) format(contract); if (specifiedFunctionBody.hasDo) { newlineIndent(); put("do"); } if (blockStatement) format(blockStatement); } } void format(const Statement statement) { debug(verbose) writeln("Statement"); /** StatementNoCaseNoDefault statementNoCaseNoDefault; CaseStatement caseStatement; CaseRangeStatement caseRangeStatement; DefaultStatement defaultStatement; **/ with(statement) { if (statementNoCaseNoDefault) { format(statementNoCaseNoDefault); return; } newlineIndent(); if (caseStatement) format(caseStatement); else if (caseRangeStatement) format(caseRangeStatement); else if (defaultStatement) format(defaultStatement); } } void format(const StatementNoCaseNoDefault statementNoCaseNoDefault) { debug(verbose) writeln("StatementNoCaseNoDefault"); string mix(string s) { return "if (" ~ s ~ ") format(" ~ s ~ ");"; } with(statementNoCaseNoDefault) { if (!blockStatement) newlineIndent(); enum stmnts = TypeTuple!( "labeledStatement", "blockStatement", "ifStatement", "whileStatement", "doStatement", "forStatement", "foreachStatement", "switchStatement", "finalSwitchStatement", "continueStatement", "breakStatement", "returnStatement", "gotoStatement", "withStatement", "synchronizedStatement", "tryStatement", "scopeGuardStatement", "asmStatement", "conditionalStatement", "staticAssertStatement", "versionSpecification", "debugSpecification", "expressionStatement" ); foreach(s; stmnts) mixin(mix(s)); } } void format(const StaticAssertDeclaration staticAssertDeclaration, const Attribute[] attrs = null) { debug(verbose) writeln("StaticAssertDeclaration"); newThing(What.other); putAttrs(attrs); format(staticAssertDeclaration.staticAssertStatement); put(";"); } void format(const StaticAssertStatement staticAssertStatement) { debug(verbose) writeln("StaticAssertStatement"); put("static "); format(staticAssertStatement.assertExpression); } void format(const StaticConstructor staticConstructor, const Attribute[] attrs = null) { debug(verbose) writeln("StaticConstructor"); putAttrs(attrs); put("static this()"); format(staticConstructor.functionBody); } void format(const StaticDestructor staticDestructor, const Attribute[] attrs = null) { debug(verbose) writeln("StaticDestructor"); putAttrs(attrs); put("static ~this()"); format(staticDestructor.functionBody); } void format(const StaticIfCondition staticIfCondition) { debug(verbose) writeln("StaticIfCondition"); put("static if ("); format(staticIfCondition.assignExpression); put(")"); } void format(const StorageClass storageClass) { debug(verbose) writeln("StorageClass"); /** AtAttribute atAttribute; Deprecated deprecated_; LinkageAttribute linkageAttribute; Token token; **/ with(storageClass) { if (atAttribute) format(atAttribute); else if (deprecated_) format(deprecated_); else if (linkageAttribute) format(linkageAttribute); else format(token); } } void format(const StructBody structBody) { debug(verbose) writeln("StructBody"); if (structBody.declarations.length > 0) { startBlock(); foreach(count, decl; structBody.declarations) format(decl); endBlock(); } else { space(); put("{}"); } } void format(const StructDeclaration decl, const Attribute[] attrs = null) { debug(verbose) writeln("StructDeclaration"); /** Token name; TemplateParameters templateParameters; Constraint constraint; StructBody structBody; string comment; **/ newThing(What.aggregateDecl); putComment(decl.comment); putAttrs(attrs); put("struct "); format(decl.name); if (decl.templateParameters) format(decl.templateParameters); if (decl.constraint) { space(); format(decl.constraint); } if (decl.structBody) format(decl.structBody); else put(";"); } void format(const StructInitializer structInitializer) { debug(verbose) writeln("StructInitializer"); put("{"); format(structInitializer.structMemberInitializers); put("}"); } void format(const StructMemberInitializer structMemberInitializer) { debug(verbose) writeln("StructMemberInitializer"); /** Token identifier; NonVoidInitializer nonVoidInitializer; **/ with(structMemberInitializer) { if (identifier != tok!"") { format(identifier); put(":"); } format(nonVoidInitializer); } } void format(const StructMemberInitializers structMemberInitializers) { debug(verbose) writeln("StructMemberInitializers"); foreach(count, mem; structMemberInitializers.structMemberInitializers) { if (count) put(", "); format(mem); } } void format(const SwitchStatement switchStatement, bool isFinal = false) { debug(verbose) writeln("SwitchStatement"); /** Expression expression; Statement statement; **/ with(switchStatement) { newThing(What.other); isFinal ? put(" final switch(") : put("switch("); format(expression); put(")"); bool needBlock = statement.statementNoCaseNoDefault && !(statement.statementNoCaseNoDefault.withStatement || statement.statementNoCaseNoDefault.blockStatement ); if (needBlock) startBlock(); format(statement); if (needBlock) endBlock(); } } void format(const Symbol symbol) { debug(verbose) writeln("Symbol"); if (symbol.dot) put("."); format(symbol.identifierOrTemplateChain); } void format(const SynchronizedStatement synchronizedStatement) { debug(verbose) writeln("SynchronizedStatement"); /** Expression expression; StatementNoCaseNoDefault statementNoCaseNoDefault; **/ with(synchronizedStatement) { put("synchronized"); if (expression) { put("("); format(expression); put(")"); } format(statementNoCaseNoDefault); } } void format(const TemplateAliasParameter templateAliasParameter) { debug(verbose) writeln("TemplateAliasParameter"); /** Type type; Token identifier; Type colonType; AssignExpression colonExpression; Type assignType; AssignExpression assignExpression; **/ with(templateAliasParameter) { put("alias "); if (type) { format(type); space(); } format(identifier); if (colonType) { put(" : "); format(colonType); } else if (colonExpression) { put(" : "); format(colonExpression); } if (assignType) { put(" = "); format(assignType); } else if (assignExpression) { put(" = "); format(assignExpression); } } } void format(const TemplateArgument templateArgument) { debug(verbose) writeln("TemplateArgument"); /** Type type; AssignExpression assignExpression; **/ with(templateArgument) { if (type) format(type); if (assignExpression) format(assignExpression); } } void format(const TemplateArgumentList templateArgumentList, bool parens = true) { debug(verbose) writeln("TemplateArgumentList"); if (parens) put("!("); foreach(count, arg; templateArgumentList.items) { if (count) put(", "); format(arg); } if (parens) put(")"); } void format(const TemplateArguments templateArguments) { debug(verbose) writeln("TemplateArguments"); /** TemplateArgumentList templateArgumentList; TemplateSingleArgument templateSingleArgument; **/ with(templateArguments) { if (templateArgumentList) format(templateArgumentList); else if (templateSingleArgument) format(templateSingleArgument); else put("!()"); } } void format(const TemplateDeclaration templateDeclaration, const Attribute[] attrs = null) { debug(verbose) writeln("TemplateDeclaration"); /** Token name; TemplateParameters templateParameters; Constraint constraint; Declaration[] declarations; EponymousTemplateDeclaration eponymousTemplateDeclaration; string comment; **/ with(templateDeclaration) { newThing(What.other); putComment(comment); putAttrs(attrs); put("template "); format(name); if (templateParameters) format(templateParameters); if (constraint) { space(); format(constraint); } startBlock(); foreach(d; declarations) format(d); endBlock(); } } void format(const TemplateInstance templateInstance) { debug(verbose) writeln("TemplateInstance"); /** Token identifier; TemplateArguments templateArguments; **/ with(templateInstance) { format(identifier); if (templateArguments) format(templateArguments); } } void format(const TemplateMixinExpression templateMixinExpression) { debug(verbose) writeln("TemplateMixinExpression"); /** Token identifier; TemplateArguments templateArguments; MixinTemplateName mixinTemplateName; **/ with(templateMixinExpression) { put("mixin "); format(mixinTemplateName); if (templateArguments) format(templateArguments); space(); format(identifier); } } void format(const TemplateParameter templateParameter) { debug(verbose) writeln("TemplateParameter"); with(templateParameter) { if (templateTypeParameter) format(templateTypeParameter); else if (templateValueParameter) format(templateValueParameter); else if (templateAliasParameter) format(templateAliasParameter); else if (templateTupleParameter) format(templateTupleParameter); else if (templateThisParameter) format(templateThisParameter); } } void format(const TemplateParameterList templateParameterList) { debug(verbose) writeln("TemplateParameterList"); foreach(i, param; templateParameterList.items) { if (i) put(", "); format(param); } } void format(const TemplateParameters templateParameters) { debug(verbose) writeln("TemplateParameters"); with(templateParameters) { put("("); if (templateParameterList) format(templateParameterList); put(")"); } } void format(const TemplateSingleArgument templateSingleArgument) { debug(verbose) writeln("TemplateSingleArgument"); /** Token token; **/ put("!"); format(templateSingleArgument.token); } void format(const TemplateThisParameter templateThisParameter) { debug(verbose) writeln("TemplateThisParameter"); with(templateThisParameter) { put("this "); if (templateTypeParameter) format(templateTypeParameter); } } void format(const TemplateTupleParameter templateTupleParameter) { debug(verbose) writeln("TemplateTupleParameter"); format(templateTupleParameter.identifier); put("..."); } void format(const TemplateTypeParameter templateTypeParameter) { debug(verbose) writeln("TemplateTypeParameter"); /** Token identifier; Type colonType; Type assignType; **/ with(templateTypeParameter) { format(identifier); if (colonType) { put(" : "); format(colonType); } if (assignType) { put(" = "); format(assignType); } } } void format(const TemplateValueParameter templateValueParameter) { debug(verbose) writeln("TemplateValueParameter"); /** Type type; Token identifier; Expression expression; TemplateValueParameterDefault templateValueParameterDefault; **/ with(templateValueParameter) { if (type) format(type); space(); format(identifier); if (assignExpression) { put(" : "); format(assignExpression); } if (templateValueParameterDefault) { put(" = "); format(templateValueParameterDefault); } } } void format(const TemplateValueParameterDefault templateValueParameterDefault) { debug(verbose) writeln("TemplateValueParameterDefault"); with(templateValueParameterDefault) assignExpression ? format(assignExpression) : format(token); } void format(const TernaryExpression expr) { debug(verbose) writeln("TernaryExpression"); /** ExpressionNode orOrExpression; ExpressionNode expression; ExpressionNode ternaryExpression; **/ format(expr.orOrExpression); if (expr.expression && expr.ternaryExpression) { put(" ? "); format(expr.expression); put(" : "); format(expr.ternaryExpression); } } void format(const ThrowExpression throwExpression) { debug(verbose) writeln("ThrowExpression"); put("throw "); assert(throwExpression.expression); format(throwExpression.expression); } void format(const Token token) { debug(verbose) writeln("Token ", tokenRep(token)); put(tokenRep(token)); } void format(const TraitsExpression traitExpr) { debug(verbose) writeln("TraitsExpression"); /** Token identifier; TemplateArgumentList templateArgumentList; **/ put("__traits("); format(traitExpr.identifier); put(", "); format(traitExpr.templateArgumentList, false); put(")"); } void format(const TryStatement tryStatement) { debug(verbose) writeln("TryStatement"); /** DeclarationOrStatement declarationOrStatement; Catches catches; Finally finally_; **/ with(tryStatement) { newThing(What.other); put("try"); maybeIndent(declarationOrStatement); if (catches) format(catches); if (finally_) format(finally_); } } void format(const Type type) { debug(verbose) writeln("Type("); /** IdType[] typeConstructors; TypeSuffix[] typeSuffixes; Type2 type2; **/ foreach (count, constructor; type.typeConstructors) { if (count) space(); put(tokenRep(constructor)); } if (type.typeConstructors.length) space(); if (type.type2) format(type.type2); foreach (suffix; type.typeSuffixes) format(suffix); debug(verbose) writeln(")"); } void format(const Type2 type2) { debug(verbose) writeln("Type2"); /** IdType builtinType; TypeofExpression typeofExpression; IdentifierList identifierList; IdType typeConstructor; Type type; TraitsExpression traitsExpression; MixinExpression mixinExpression; **/ if (type2.typeIdentifierPart !is null) { format(type2.typeIdentifierPart); } else if (type2.typeofExpression !is null) { format(type2.typeofExpression); if (type2.typeIdentifierPart) { put("."); format(type2.typeIdentifierPart); } return; } else if (type2.typeConstructor != tok!"") { put(tokenRep(type2.typeConstructor)); put("("); format(type2.type); put(")"); } else if (type2.traitsExpression) { format(type2.traitsExpression); } else if (type2.mixinExpression) { format(type2.mixinExpression); } else { put(tokenRep(type2.builtinType)); if (type2.typeIdentifierPart) { put("."); format(type2.typeIdentifierPart); } } } void format(const TypeSpecialization typeSpecialization) { debug(verbose) writeln("TypeSpecialization"); /** Token token; Type type; **/ with(typeSpecialization) { format(token); if (type) format(type); } } void format(const TypeSuffix typeSuffix) { debug(verbose) writeln("TypeSuffix"); /** Token delegateOrFunction; bool star; bool array; Type type; AssignExpression low; AssignExpression high; Parameters parameters; MemberFunctionAttribute[] memberFunctionAttributes; **/ if (typeSuffix.star.type != tok!"") { put("*"); return; } else if (typeSuffix.array) { if (typeSuffix.type is null) { if (typeSuffix.low is null) { put("[]"); return; } else { if (typeSuffix.high is null) { put("["); format(typeSuffix.low); put("]"); return; } else { put("["); format(typeSuffix.low); put(".."); format(typeSuffix.high); put("]"); return; } } } else { put("["); format(typeSuffix.type); put("]"); return; } } else { space(); format(typeSuffix.delegateOrFunction); if (typeSuffix.parameters) format(typeSuffix.parameters); foreach(attr; typeSuffix.memberFunctionAttributes) { space(); format(attr); } return; } } void format(const TypeidExpression idExpr) { debug(verbose) writeln("TypeidExpression"); /** Type type; Expression expression; **/ put("typeid ("); idExpr.type ? format(idExpr.type) : format(idExpr.expression); put(")"); } void format(const TypeofExpression typeofExpr) { debug(verbose) writeln("TypeofExpression"); /** Expression expression; Token return_; **/ put("typeof("); typeofExpr.expression ? format(typeofExpr.expression) : format(typeofExpr.return_); put(")"); } void format(const UnaryExpression unary) { debug(verbose) writeln("UnaryExpression("); /** Type type; PrimaryExpression primaryExpression; Token prefix; Token suffix; UnaryExpression unaryExpression; NewExpression newExpression; DeleteExpression deleteExpression; CastExpression castExpression; FunctionCallExpression functionCallExpression; ArgumentList argumentList; IdentifierOrTemplateInstance identifierOrTemplateInstance; AssertExpression assertExpression; SliceExpression sliceExpression; IndexExpression indexExpression; **/ with(unary) { if (prefix != tok!"") format(prefix); if (type) { // handle things like (void*).sizeof if (identifierOrTemplateInstance) { put("("); format(type); put(")"); } else { format(type); put("("); if (argumentList) format(argumentList); put(")"); } } if (primaryExpression) format(primaryExpression); if (newExpression) format(newExpression); if (deleteExpression) format(deleteExpression); if (castExpression) format(castExpression); if (functionCallExpression) format(functionCallExpression); if (assertExpression) format(assertExpression); if (throwExpression) format(throwExpression); if (indexExpression) format(indexExpression); if (unaryExpression) format(unaryExpression); if (suffix != tok!"") format(suffix); if (identifierOrTemplateInstance) { put("."); format(identifierOrTemplateInstance); } } debug(verbose) writeln(")"); } void format(const UnionDeclaration decl, const Attribute[] attrs = null) { debug(verbose) writeln("UnionDeclaration"); /** Token name; TemplateParameters templateParameters; Constraint constraint; StructBody structBody; string comment; **/ newThing(What.aggregateDecl); putComment(decl.comment); putAttrs(attrs); put("union "); format(decl.name); if (decl.templateParameters) format(decl.templateParameters); if (decl.constraint) { space(); format(decl.constraint); } format(decl.structBody); } void format(const Unittest unittest_, const Attribute[] attrs = null) { debug(verbose) writeln("Unittest"); /** BlockStatement blockStatement; string comment; **/ newThing(What.functionDecl); putComment(unittest_.comment); putAttrs(attrs); put("unittest"); format(unittest_.blockStatement); } void format(const VariableDeclaration decl, const Attribute[] attrs = null) { debug(verbose) writeln("VariableDeclaration"); /** Type type; Declarator[] declarators; StorageClass storageClass; AutoDeclaration autoDeclaration; string comment; **/ newThing(What.variableDecl); putComment(decl.comment); putAttrs(attrs); if (decl.autoDeclaration) format(decl.autoDeclaration); else { foreach (c; decl.storageClasses) { format(c); space(); } if (decl.type) format(decl.type); if (decl.declarators.length) space(); foreach(count, d; decl.declarators) { if (count) put(", "); format(d); } } put(";"); } void format(const Vector vector) { debug(verbose) writeln("Vector"); put("__vector"); if (vector.type) { put("("); format(vector.type); put(")"); } } void format(const VersionCondition versionCondition) { debug(verbose) writeln("VersionCondition"); put("version ("); format(versionCondition.token); put(")"); } void format(const VersionSpecification ver, const Attribute[] attrs = null) { debug(verbose) writeln("VersionSpecification"); newThing(What.other); putAttrs(attrs); put("version = "); format(ver.token); put(";"); } void format(const WhileStatement stmt) { debug(verbose) writeln("WhileStatement"); /** Expression expression; DeclarationOrStatement declarationOrStatement; **/ newThing(What.other); put("while ("); format(stmt.expression); put(")"); maybeIndent(stmt.declarationOrStatement); } void format(const WithStatement stmt) { debug(verbose) writeln("WithStatement"); /** Expression expression; DeclarationsOrStatement declarationOrStatement; **/ space(); put("with ("); format(stmt.expression); put(")"); if (stmt.declarationOrStatement) format(stmt.declarationOrStatement); } void format(const XorExpression xorExpression) { debug(verbose) writeln("XorExpression"); mixin(binary("xorExpression", "^")); } Sink sink; protected: import std.uni : isWhite; void indent() { indentLevel++; } void outdent() { if (indentLevel == 0) return; indentLevel--; } void putIndent() { if (!indentLevel) return; auto i = getIndent(); put(i); } string getIndent() { if (useTabs) { char[] c = new char[indentLevel]; c[] = '\t'; return cast(string) c; } else { char[] c = new char[indentLevel * indentWidth]; c[] = ' '; return cast(string) c; } } enum What { functionDecl, aggregateDecl, attributeDecl, conditionalDecl, variableDecl, importDecl, expr, loop, else_, catch_, other } void newThing(What thing) { lastThing = currentThing; currentThing = thing; with(What) { if (lastThing == importDecl && thing != importDecl) { lineGap(1); return; } if (lastThing == loop) { lineGap(1); return; } switch(thing) { case other: newline(); break; case aggregateDecl: case attributeDecl: case functionDecl: lineGap(1); break; case conditionalDecl: //lineGap(1); break; case variableDecl: lineGap(1); break; case importDecl: newlineIndent(); break; case expr: break; case catch_: goto case; case else_: final switch(style) with(IndentStyle) { case allman: newline(); break; case otbs: space(); break; } break; default: newlineIndent(); break; } } } void lineGap(int gap) { foreach (i; 0 .. gap + 1) { if (i == gap) newlineIndent(); else newline(); } } void newlineIndent() { if (ignoreNewlines) { space(); // don't do this when splitting lines } else { sink.put("\n"); lineLength = 0; putIndent(); } } void newline() { sink.put("\n"); lineLength = 0; } void space() { put(" "); } static string binary(string symbol, string operator = null, bool nospace = false) { return "with(" ~ symbol ~ "){" ~ "format(left); if (right is null) return;" ~ (nospace ? "" : "put(` `);") ~ (operator ? "put(`" ~ operator ~ "`);" : "put(tokenRep(operator));") ~ (nospace ? "" : "put(` `);") ~ "format(right);}"; } void startBlock() { final switch(style) with(IndentStyle) { case allman: newline(); break; case otbs: space(); break; } putIndent(); put("{"); indent(); } void endBlock() { outdent(); newline(); putIndent(); put("}"); } string tokenRep(Token t) { return t.text.length ? t.text : tokenRep(t.type); } string tokenRep(IdType t) { return t ? str(t) : ""; } void putComment(string c) { import std.string : splitLines; if (!c.length) return; put(c.splitLines().join("\n" ~ getIndent())); newlineIndent(); } void putAttrs(const Attribute[] attrs) { if (attrs !is null) { foreach(count, attr; attrs) { format(attr); space(); } } } void put(string s) { sink.put(s); lineLength += s.length; // TODO: tabs / spaces? } void formatCaseDecls(const DeclarationsAndStatements declsAndStmnts) { bool seenBlock = false; auto items = declsAndStmnts.declarationsAndStatements; foreach(item; items) { bool _indent = false; if (item.declaration) _indent = true; if (item.statement && item.statement.statementNoCaseNoDefault) { if (item.statement.statementNoCaseNoDefault.blockStatement) seenBlock = true; else if (!item.statement.statementNoCaseNoDefault.labeledStatement) _indent = true; } if (seenBlock) _indent = false; if (_indent) indent(); format(item); if (_indent) outdent(); } } bool needIndent(const Statement s) { return s.statementNoCaseNoDefault && !s.statementNoCaseNoDefault.blockStatement; } bool needIndent(const Declaration d) { return !d.declarations.length; } bool needIndent(const DeclarationOrStatement dors) { return (dors.declaration && needIndent(dors.declaration)) || (dors.statement && needIndent(dors.statement)); } void maybeIndent(T)(const T t) { auto _indent = needIndent(t); if (_indent) indent(); format(t); if (_indent) outdent(); } bool isEmptyDeclaration(const Declaration decl) { with(decl) { string mix(string[] s) { string r; foreach(c, d; s) r ~= (c > 0 ? "else " : "") ~ "if (" ~ d ~ ") return false;"; return r; } mixin(mix(possibleDeclarations)); return attributes.length == 0 && declarations.length == 0; } } bool ignoreNewlines = false; bool useTabs; uint caseDepth; uint indentWidth; uint indentLevel; IndentStyle style; What lastThing, currentThing; uint lineLength; uint maxLineLength = 80; enum possibleDeclarations = [ "attributeDeclaration", "importDeclaration", "functionDeclaration", "variableDeclaration", "aliasThisDeclaration", "structDeclaration", "classDeclaration", "interfaceDeclaration", "unionDeclaration", "enumDeclaration", "aliasDeclaration", "mixinDeclaration", "mixinTemplateDeclaration", "unittest_", "staticAssertDeclaration", "templateDeclaration", "constructor", "destructor", "staticConstructor", "staticDestructor", "sharedStaticDestructor", "sharedStaticConstructor", "conditionalDeclaration", "pragmaDeclaration", "versionSpecification", "invariant_", "postblit" ]; } version (unittest) void testFormatNode(Node)(string sourceCode, string expected = "") { Appender!string fmt; ubyte[] code = cast(ubyte[]) sourceCode; class CatchInterestingStuff : ASTVisitor { alias visit = ASTVisitor.visit; override void visit(const(Node) stuff) { stuff.accept(this); format(&fmt, stuff); const exp = expected.length ? expected : sourceCode; const act = fmt.data(); if (!act.canFind(exp)) { string msg = "Formatted code didn't contain the expected output!"; msg ~= "\n=============== Expected ===================\n"; msg ~= exp; msg ~= "\n=============== Actual ===================\n"; msg ~= act; msg ~= "\n=========================================="; assert(false, msg); } } } static void errorFunc(string,size_t,size_t,string msg, bool) {assert(0, "The AST to format contains error(s) : " ~ msg);} LexerConfig config; StringCache cache = StringCache(32); RollbackAllocator rba; auto toks = getTokensForParser(code, config, &cache); Module mod = parseModule(ParserConfig(toks, "stdin", &rba, &errorFunc)); (new CatchInterestingStuff).visit(mod); } unittest { testFormatNode!(VariableDeclaration)("__traits(getMember, Foo, \"Bar\") fooBar;"); testFormatNode!(VariableDeclaration)("const(__traits(getMember, Foo, \"Bar\")) fooBar;"); testFormatNode!(VariableDeclaration)("T.T y;"); testFormatNode!(VariableDeclaration)("T[] y;"); testFormatNode!(VariableDeclaration)("T* y;"); testFormatNode!(VariableDeclaration)("T[0].Y y;"); testFormatNode!(VariableDeclaration)("T.T[] y;"); testFormatNode!(VariableDeclaration)("T.T[8] y;"); testFormatNode!(VariableDeclaration)("T.T[8].T y;"); testFormatNode!(VariableDeclaration)(`.T!"af" taf;`); testFormatNode!(VariableDeclaration)(`.T!0[] t;`); testFormatNode!(VariableDeclaration)(`T!(0)[] t;`); testFormatNode!(VariableDeclaration)(`T!(0)[dim] t;`); testFormatNode!(VariableDeclaration)(`const shared t = [0, 1];`); testFormatNode!(OutStatement)( ` void foo() out{static if (true) {baz();}} do{} `, `out { static if (true) { baz(); } }`); testFormatNode!(AutoDeclaration)("auto f = a;"); testFormatNode!(AutoDeclaration)("auto f = ref () => a;"); testFormatNode!(AliasDeclaration)("alias f = ref () => a;"); testFormatNode!(AliasDeclaration)("alias int F(int);"); testFormatNode!(AliasDeclaration)("alias const int F(int);"); testFormatNode!(AliasDeclaration)("alias const int F(int) nothrow;"); testFormatNode!(AliasDeclaration)("alias f(T) = void(T t);"); testFormatNode!(AliasDeclaration)("alias f(T) = void(int, int, int) const pure nothrow;"); testFormatNode!(AliasDeclaration)("alias MT = mixin (strEnum1, strEnum2);"); testFormatNode!(Module)("static assert(() @trusted { return bar()(3); }() == 4);", `static assert (() @trusted { return bar()(3); }() == 4)` ); testFormatNode!(Module)("int foo() { return 2; }", `int foo() { return 2; }` ); testFormatNode!(Module)("int foo() do { return 2; }", `int foo() do { return 2; }` ); testFormatNode!(Module)("int foo(int i) in(i > 0) do { return 2; }", `int foo(int i) in (i > 0) do { return 2; }` ); testFormatNode!(Module)("int foo(int i) in { assert(i > 0); } do { return 2; }", `int foo(int i) in { assert (i > 0); } do { return 2; }` ); testFormatNode!(Module)("int foo() out(j; j > 0) do { return 2; }", `int foo() out (j; j > 0) do { return 2; }` ); testFormatNode!(Module)("int foo() out(j) { assert(j > 0); } do { return 2; }", `int foo() out (j) { assert (j > 0); } do { return 2; }` ); testFormatNode!(Module)("version(BAR) { int foo(int i) in(i > 0) in { assert(i > 0); } out(j; j > 0) out(j) { assert(j>0); } do { return 2; } int i; } ", `version (BAR) { int foo(int i) in (i > 0) in { assert (i > 0); } out (j; j > 0) out (j) { assert (j > 0); } do { return 2; } int i; }` ); testFormatNode!(Declaration)(q{int i = throw new Ex();}); testFormatNode!(FunctionDeclaration)(q{void someFunction() { foo(a, throw b, c); return throw new Exception("", ""); }}); }