102030405060708090100110120130140150160170180190200210220230240250260270280290300310320330340350360370380390400410420430440450460470480490500510520530540550560570580590600610620630640650660670680690700710720730740750760770780790800810820830840850860870880890900910920930940950960970980990100010101020103010401050106010701080109011001110112011301140115011601170118011901200121012201230124012501260127012801290130013101320133013401350136013701380139014001410142014301440145014601470148014901500151015201530154015501560157015801590160016101620163016401650166016701680169017001710172017301740175017601770178017901800181018201830184018501860187018801890190019101920193019401950196019701980199020002010202020302040205020602070208020902100211021202130214021502160217021802190220022102220223022402250226022702280229023002310232023302340235023602370238023902400241024202430244024502460247024802490250025102520253025402550256025702580259026002610262026302640265026602670268026902700271027202730274027502760277027802790280028102820283028402850286028702880289029002910292029302940295029602970298029903000301030203030304030503060307030803090310031103120313031403150316031703180319032003210322032303240325032603270328032903300331033203330334033503360337033803390340034103420343034403450346034703480349035003510352035303540355035603570358035903600361036203630364036503660367036803690370037103720373037403750376037703780379038003810382038303840385038603870388038903900391039203930394039503960397039803990400040104020403040404050406040704080409041004110412041304140415041604170418041904200421042204230424042504260427042804290430043104320433043404350436043704380439044004410442044304440445044604470448044904500451045204530454045504560457045804590460046104620463046404650466046704680469047004710472047304740475047604770478047904800481048204830484048504860487048804890490049104920493049404950496049704980499050005010502050305040505050605070508050905100511051205130514051505160517051805190520052105220523052405250526052705280529053005310532053305340535053605370538053905400541054205430544054505460547054805490550055105520553055405550556055705580559056005610562056305640565056605670568056905700571057205730574057505760577057805790580058105820583058405850586058705880589059005910592059305940595059605970598059906000601060206030604060506060607060806090610061106120613061406150616061706180619062006210622062306240625062606270628062906300631063206330634063506360637063806390640064106420643064406450646064706480649065006510652065306540655065606570658065906600661066206630664066506660667066806690670067106720673067406750676067706780679068006810682068306840685068606870688068906900691069206930694069506960697069806990700070107020703070407050706070707080709071007110712071307140715071607170718071907200721072207230724072507260727072807290730073107320733073407350736073707380739074007410742074307440745074607470748074907500751075207530754075507560757075807590760076107620763076407650766076707680769077007710772077307740775077607770778077907800781078207830784078507860787078807890790079107920793079407950796079707980799080008010802080308040805080608070808080908100811081208130814081508160817081808190820082108220823082408250826082708280829083008310832083308340835083608370838083908400841084208430844084508460847084808490850085108520853085408550856085708580859086008610862086308640865086608670868086908700871087208730874087508760877087808790880088108820883088408850886088708880889089008910892089308940895089608970898089909000901090209030904090509060907090809090910091109120913091409150916091709180919092009210922092309240925092609270928092909300931093209330934093509360937093809390940094109420943094409450946094709480949095009510952095309540955095609570958095909600961096209630964096509660967096809690970097109720973097409750976097709780979098009810982098309840985098609870988098909900991099209930994099509960997099809990100001001010020100301004010050100601007010080100901010010110101201013010140101501016010170101801019010200102101022010230102401025010260102701028010290103001031010320103301034010350103601037010380103901040010410104201043010440104501046010470104801049010500105101052010530105401055010560105701058010590106001061010620106301064010650106601067010680106901070010710107201073010740107501076010770107801079010800108101082010830108401085010860108701088010890109001091010920109301094010950109601097010980109901100011010110201103011040110501106011070110801109011100111101112011130111401115011160111701118011190112001121011220112301124011250112601127011280112901130011310113201133011340113501136011370113801139011400114101142011430114401145011460114701148011490115001151011520115301154011550115601157011580115901160011610116201163011640116501166011670116801169011700117101172011730117401175011760117701178011790118001181011820118301184011850118601187011880118901190011910119201193011940119501196011970119801199012000120101202012030120401205012060120701208012090121001211012120121301214012150121601217012180121901220012210122201223012240122501226012270122801229012300123101232012330123401235012360123701238012390124001241012420124301244012450124601247012480124901250012510125201253012540125501256012570125801259012600126101262012630126401265012660126701268012690127001271012720127301274012750127601277012780127901280012810128201283012840128501286012870128801289012900129101292012930129401295012960129701298012990130001301013020130301304013050130601307013080130901310013110131201313013140131501316013170131801319013200132101322013230132401325013260132701328013290133001331013320133301334013350133601337013380133901340013410134201343013440134501346013470134801349013500135101352013530135401355013560135701358013590136001361013620136301364013650136601367013680136901370013710137201373013740137501376013770137801379013800138101382013830138401385013860138701388013890139001391013920139301394013950139601397013980139901400014010140201403014040140501406014070140801409014100141101412014130141401415014160141701418014190142001421014220142301424014250142601427014280142901430014310143201433014340143501436014370143801439014400144101442014430144401445014460144701448014490145001451014520145301454014550145601457014580145901460014610146201463014640146501466014670146801469014700147101472014730147401475014760147701478014790148001481014820148301484014850148601487014880148901490014910149201493014940149501496014970149801499015000150101502015030150401505015060150701508015090151001511015120151301514015150151601517015180151901520015210152201523015240152501526015270152801529015300153101532015330153401535015360153701538015390154001541015420154301544015450154601547015480154901550015510155201553015540155501556015570155801559015600156101562015630156401565015660156701568015690157001571015720157301574015750157601577015780157901580015810158201583015840158501586015870158801589015900159101592015930159401595015960159701598015990160001601016020160301604016050160601607016080160901610016110161201613016140161501616016170161801619016200162101622016230162401625016260162701628016290163001631016320163301634016350163601637016380163901640016410164201643016440164501646016470164801649016500165101652016530165401655016560165701658016590166001661016620166301664016650166601667016680166901670016710167201673016740167501676016770167801679016800168101682016830168401685016860168701688016890169001691016920169301694016950169601697016980169901700017010170201703017040170501706017070170801709017100171101712017130171401715017160171701718017190172001721017220172301724017250172601727017280172901730017310173201733017340173501736017370173801739017400174101742017430174401745017460174701748017490175001751017520175301754017550175601757017580175901760017610176201763017640176501766017670176801769017700177101772017730177401775017760177701778017790178001781017820178301784017850178601787017880178901790017910179201793017940179501796017970179801799018000180101802018030180401805018060180701808018090181001811018120181301814018150181601817018180181901820018210182201823018240182501826018270182801829018300183101832018330183401835018360183701838018390184001841018420184301844018450184601847018480184901850018510185201853018540185501856018570185801859018600186101862018630186401865018660186701868018690187001871018720187301874018750187601877018780187901880018810188201883018840188501886018870188801889018900189101892018930189401895018960189701898018990190001901019020190301904019050190601907019080190901910019110191201913019140191501916019170191801919019200192101922019230192401925019260192701928019290193001931019320193301934019350193601937019380193901940019410194201943019440194501946019470194801949019500195101952019530195401955019560195701958019590196001961019620196301964019650196601967019680196901970019710197201973019740197501976019770197801979019800198101982019830198401985019860198701988019890199001991019920199301994019950199601997019980199902000020010200202003020040200502006020070200802009020100201102012020130201402015020160201702018020190202002021020220202302024020250202602027020280202902030020310203202033020340203502036020370203802039020400204102042020430204402045020460204702048020490205002051020520205302054020550205602057020580205902060020610206202063020640206502066020670206802069020700207102072020730207402075020760207702078020790208002081020820208302084020850208602087020880208902090020910209202093020940209502096020970209802099021000210102102021030210402105021060210702108021090211002111021120211302114021150211602117021180211902120021210212202123021240212502126021270212802129021300213102132021330213402135021360213702138021390214002141021420214302144021450214602147021480214902150021510215202153021540215502156021570215802159021600216102162021630216402165021660216702168021690217002171021720217302174021750217602177021780217902180021810218202183021840218502186021870218802189021900219102192021930219402195021960219702198021990220002201022020220302204022050220602207022080220902210022110221202213022140221502216022170221802219022200222102222022230222402225022260222702228022290223002231022320223302234022350223602237022380223902240022410224202243022440224502246022470224802249022500225102252022530225402255022560225702258022590226002261022620226302264022650226602267022680226902270022710227202273022740227502276022770227802279022800228102282022830228402285022860228702288022890229002291022920229302294022950229602297022980229902300023010230202303023040230502306023070230802309023100231102312023130231402315023160231702318023190232002321023220232302324023250232602327023280232902330023310233202333023340233502336023370233802339023400234102342023430234402345023460234702348023490235002351023520235302354023550235602357023580235902360023610236202363023640236502366023670236802369023700237102372023730237402375023760237702378023790238002381023820238302384023850238602387023880238902390023910239202393023940239502396023970239802399024000240102402024030240402405024060240702408024090241002411024120241302414024150241602417024180241902420024210242202423024240242502426024270242802429024300243102432024330243402435024360243702438024390244002441024420244302444024450244602447024480244902450024510245202453024540245502456024570245802459024600246102462024630246402465024660246702468024690247002471024720247302474024750247602477024780247902480024810248202483024840248502486024870248802489024900249102492024930249402495024960249702498024990250002501025020250302504025050250602507025080250902510025110251202513025140251502516025170251802519025200252102522025230252402525025260252702528025290253002531025320253302534025350253602537025380253902540025410254202543025440254502546025470254802549025500255102552025530255402555025560255702558025590256002561025620256302564025650256602567025680256902570025710257202573025740257502576025770257802579025800258102582025830258402585025860258702588025890259002591025920259302594025950259602597025980259902600026010260202603026040260502606026070260802609026100261102612026130261402615026160261702618026190262002621026220262302624026250262602627026280262902630026310263202633026340263502636026370263802639026400264102642026430264402645026460264702648026490265002651026520265302654026550265602657026580265902660026610266202663026640266502666026670266802669026700267102672026730267402675026760267702678026790268002681026820268302684026850268602687026880268902690026910269202693026940269502696026970269802699027000270102702027030270402705027060270702708027090271002711027120271302714027150271602717027180271902720027210272202723027240272502726027270272802729027300273102732027330273402735027360273702738027390274002741027420274302744027450274602747027480274902750027510275202753027540275502756027570275802759027600276102762027630276402765027660276702768027690277002771027720277302774027750277602777027780277902780027810278202783027840278502786027870278802789027900279102792027930279402795027960279702798027990280002801028020280302804028050280602807028080280902810028110281202813028140281502816028170281802819028200282102822028230282402825028260282702828028290283002831028320283302834028350283602837028380283902840028410284202843028440284502846028470284802849028500285102852028530285402855028560285702858028590286002861028620286302864028650286602867028680286902870028710287202873028740287502876028770287802879028800288102882028830288402885028860288702888028890289002891028920289302894028950289602897028980289902900029010290202903029040290502906029070290802909029100291102912029130291402915029160291702918029190292002921029220292302924029250292602927029280292902930029310293202933029340293502936029370293802939029400294102942029430294402945029460294702948029490295002951029520295302954029550295602957029580295902960029610296202963029640296502966029670296802969029700297102972029730297402975029760297702978029790298002981029820298302984029850298602987029880298902990029910299202993029940299502996029970299802999030000300103002030030300403005030060300703008030090301003011030120301303014030150301603017030180301903020030210302203023030240302503026030270302803029030300303103032030330303403035030360303703038030390304003041030420304303044030450304603047030480304903050030510305203053030540305503056030570305803059030600306103062030630306403065030660306703068030690307003071030720307303074030750307603077030780307903080030810308203083030840308503086030870308803089030900309103092030930309403095030960309703098030990310003101031020310303104031050310603107031080310903110031110311203113031140311503116031170311803119031200312103122031230312403125031260312703128031290313003131031320313303134031350313603137031380313903140031410314203143031440314503146031470314803149031500315103152031530315403155031560315703158031590316003161031620316303164031650316603167031680316903170031710317203173031740317503176031770317803179031800318103182031830318403185031860318703188031890319003191031920319303194031950319603197031980319903200032010320203203032040320503206032070320803209032100321103212032130321403215032160321703218032190322003221032220322303224032250322603227032280322903230032310323203233032340323503236032370323803239032400324103242032430324403245032460324703248032490325003251032520325303254032550325603257032580325903260032610326203263032640326503266032670326803269032700327103272032730327403275032760327703278032790328003281032820328303284032850328603287032880328903290032910329203293032940329503296032970329803299033000330103302033030330403305033060330703308033090331003311033120331303314033150331603317033180331903320033210332203323033240332503326033270332803329033300333103332033330333403335033360333703338033390334003341033420334303344033450334603347033480334903350033510335203353033540335503356033570335803359033600336103362033630336403365033660336703368033690337003371033720337303374033750337603377033780337903380033810338203383033840338503386033870338803389033900339103392033930339403395033960339703398033990340003401034020340303404034050340603407034080340903410034110341203413034140341503416034170341803419034200342103422034230342403425034260342703428034290343003431034320343303434034350343603437034380343903440034410344203443034440344503446034470344803449034500345103452034530345403455034560345703458034590346003461034620346303464034650346603467034680346903470034710347203473034740347503476034770347803479034800348103482034830348403485034860348703488034890349003491034920349303494034950349603497034980349903500035010350203503035040350503506035070350803509035100351103512035130351403515035160351703518035190352003521035220352303524035250352603527035280352903530035310353203533035340353503536035370353803539035400354103542035430354403545035460354703548035490355003551035520355303554035550355603557035580355903560035610356203563035640356503566035670356803569035700357103572035730357403575035760357703578035790358003581035820358303584035850358603587035880358903590035910359203593035940359503596035970359803599036000360103602036030360403605036060360703608036090361003611036120361303614036150361603617036180361903620036210362203623036240362503626036270362803629036300363103632036330363403635036360363703638036390364003641036420364303644036450364603647036480364903650036510365203653036540365503656036570365803659036600366103662036630366403665036660366703668036690367003671036720367303674036750367603677036780367903680036810368203683036840368503686036870368803689036900369103692036930369403695036960369703698036990370003701037020370303704037050370603707037080370903710037110371203713037140371503716037170371803719037200372103722037230372403725037260372703728037290373003731037320373303734037350373603737037380373903740037410374203743037440374503746037470374803749037500375103752037530375403755037560375703758037590376003761037620376303764037650376603767037680376903770037710377203773037740377503776037770377803779037800378103782037830378403785037860378703788037890379003791037920379303794037950379603797037980379903800038010380203803038040380503806038070380803809038100381103812038130381403815038160381703818038190382003821038220382303824038250382603827038280382903830038310383203833038340383503836038370383803839038400384103842038430384403845038460384703848038490385003851038520385303854038550385603857038580385903860038610386203863038640386503866038670386803869038700387103872038730387403875038760387703878038790388003881038820388303884038850388603887038880388903890038910389203893038940389503896038970389803899039000390103902039030390403905039060390703908039090391003911039120391303914039150391603917039180391903920039210392203923039240392503926039270392803929039300393103932039330393403935039360393703938039390394003941039420394303944039450394603947039480394903950039510395203953039540395503956039570395803959039600396103962039630396403965039660396703968039690397003971039720397303974039750397603977039780397903980039810398203983039840398503986039870398803989039900399103992039930399403995039960399703998039990400004001040020400304004040050400604007040080400904010040110401204013040140401504016040170401804019040200402104022040230402404025040260402704028040290403004031040320403304034040350403604037040380403904040040410404204043040440404504046040470404804049040500405104052040530405404055040560405704058040590406004061040620406304064040650406604067040680406904070040710407204073040740407504076040770407804079040800408104082040830408404085040860408704088040890409004091040920409304094040950409604097040980409904100041010410204103041040410504106041070410804109041100411104112041130411404115041160411704118041190412004121041220412304124041250412604127041280412904130041310413204133041340413504136041370413804139041400414104142041430414404145041460414704148041490415004151041520415304154041550415604157041580415904160041610416204163041640416504166041670416804169041700417104172041730417404175041760417704178041790418004181041820418304184041850418604187041880418904190041910419204193041940419504196041970419804199042000420104202042030420404205042060420704208042090421004211042120421304214042150421604217042180421904220042210422204223042240422504226042270422804229042300423104232042330423404235042360423704238042390424004241042420424304244042450424604247042480424904250042510425204253042540425504256042570425804259042600426104262042630 #!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("", ""); }}); }
#!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("", ""); }}); }