1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876 |
- #include "BfAst.h"
- #include "BfReducer.h"
- #include "BfParser.h"
- #include "BfSystem.h"
- #include "BfUtil.h"
- #include "BeefySysLib/util/BeefPerf.h"
- #include "BeefySysLib/util/StackHelper.h"
- #include "BeefySysLib/util/AllocDebug.h"
- #include <functional>
- USING_NS_BF;
- #define MEMBER_SET(dest, member, src) \
- { dest->member = src; \
- MoveNode(src, dest); }
- #define MEMBER_SET_CHECKED(dest, member, src) \
- { if (src == NULL) return dest; \
- dest->member = src; \
- MoveNode(src, dest); }
- #define MEMBER_SET_CHECKED_BOOL(dest, member, src) \
- { if (src == NULL) return false; \
- dest->member = src; \
- MoveNode(src, dest); }
- BfReducer::BfReducer()
- {
- mCurTypeDecl = NULL;
- mLastTypeDecl = NULL;
- mCurMethodDecl = NULL;
- mLastBlockNode = NULL;
- mSource = NULL;
- mClassDepth = 0;
- mAlloc = NULL;
- mStmtHasError = false;
- mPrevStmtHadError = false;
- mPassInstance = NULL;
- mCompatMode = false;
- mAllowTypeWildcard = false;
- mIsFieldInitializer = false;
- mInParenExpr = false;
- mSkipCurrentNodeAssert = false;
- mAssertCurrentNodeIdx = 0;
- mSystem = NULL;
- mResolvePassData = NULL;
- mMethodDepth = 0;
- mDocumentCheckIdx = 0;
- mTypeMemberNodeStart = NULL;
- mCurTypeState = NULL;
- mLastErrorSrcEnd = -1;
- }
- bool BfReducer::IsSemicolon(BfAstNode* node)
- {
- auto tokenNode = BfNodeDynCast<BfTokenNode>(node);
- return (tokenNode != NULL) && (tokenNode->GetToken() == BfToken_Semicolon);
- }
- bool BfReducer::StringEquals(BfAstNode* node, BfAstNode* node2)
- {
- int len = node->GetSrcLength();
- int len2 = node2->GetSrcLength();
- if (len != len2)
- return false;
- int start = node->GetSrcStart();
- int start2 = node2->GetSrcStart();
- const char* srcStr = node->GetSourceData()->mSrc;
- for (int i = 0; i < len; i++)
- {
- if (srcStr[start + i] != srcStr[start2 + i])
- return false;
- }
- return true;
- }
- int gAssertCurrentNodeIdx = 0;
- bool BfReducer::AssertCurrentNode(BfAstNode* node)
- {
- if (mSkipCurrentNodeAssert)
- return true;
-
- bool success = true;
- auto currentNode = mVisitorPos.GetCurrent();
- if (currentNode == NULL)
- return success;
- if ((!node->LocationEndEquals(currentNode)) && (mLastErrorSrcEnd != currentNode->mSrcEnd))
- {
- const char* lastCPtr = &node->GetSourceData()->mSrc[node->GetSrcEnd() - 1];
- // We have an "exceptional" case where breaking a double chevron will look like a position error
- if ((lastCPtr[0] != '>') || (lastCPtr[1] != '>'))
- {
- //BF_FATAL("Internal parsing error");
- Fail("Internal parsing error", currentNode);
- AddErrorNode(currentNode);
- success = false;
- }
- }
- gAssertCurrentNodeIdx++;
- mAssertCurrentNodeIdx++;
- return success;
- }
- // For autocomplete we only do a reduce on nodes the cursor is in
- bool BfReducer::IsNodeRelevant(BfAstNode* astNode)
- {
- BfParser* bfParser = astNode->GetSourceData()->ToParser();
- if (bfParser == NULL)
- return true;
- int cursorPos = bfParser->mCursorIdx;
- if ((cursorPos == -1) || (astNode->Contains(cursorPos, 1, 0)))
- return true;
- BF_ASSERT(bfParser->mParserData->mRefCount == -1);
- return false;
- }
- bool BfReducer::IsCursorInside(BfAstNode* astNode)
- {
- BfParser* bfParser = astNode->GetSourceData()->ToParser();
- if (bfParser == NULL)
- return false;
- int cursorPos = bfParser->mCursorIdx;
- if (cursorPos == -1)
- return false;
- if (astNode->Contains(cursorPos, 1, 0))
- return true;
- BF_ASSERT(bfParser->mParserData->mRefCount == -1);
- return false;
- }
- bool BfReducer::IsNodeRelevant(BfAstNode* startNode, BfAstNode* endNode)
- {
- if (startNode == NULL)
- return IsNodeRelevant(endNode);
- BfParser* bfParser = startNode->GetSourceData()->ToParser();
- if (bfParser == NULL)
- return true;
- int cursorPos = bfParser->mCursorIdx;
- int lenAdd = 1;
- if ((cursorPos == -1) ||
- ((cursorPos >= startNode->GetSrcStart()) && (cursorPos < endNode->GetSrcEnd() + lenAdd)))
- return true;
- BF_ASSERT(bfParser->mParserData->mRefCount == -1);
- return false;
- }
- void BfReducer::MoveNode(BfAstNode* srcNode, BfAstNode* newOwner)
- {
- #ifdef BF_AST_HAS_PARENT_MEMBER
- srcNode->mParent = newOwner;
- #endif
- int srcStart = srcNode->mSrcStart;
- int srcEnd = srcNode->mSrcEnd;
- if (srcStart < newOwner->mSrcStart)
- newOwner->mSrcStart = srcStart;
- if (srcEnd > newOwner->mSrcEnd)
- newOwner->mSrcEnd = srcEnd;
- }
- // Replaces prevNode with new node and adds prevNode to newNode's children
- // It can be considered that newNode encapsulated prevNode.
- void BfReducer::ReplaceNode(BfAstNode* prevNode, BfAstNode* newNode)
- {
- #ifdef BF_AST_HAS_PARENT_MEMBER
- newNode->mParent = prevNode->mParent;
- #endif
- if (!newNode->IsInitialized())
- {
- #ifdef BF_AST_COMPACT
- if (prevNode->mIsCompact)
- {
- newNode->mIsCompact = prevNode->mIsCompact;
- newNode->mCompact_SrcStart = prevNode->mCompact_SrcStart;
- newNode->mCompact_SrcLen = prevNode->mCompact_SrcLen;
- newNode->mCompact_TriviaLen = prevNode->mCompact_TriviaLen;
- }
- else
- {
- int prevTriviaStart;
- int prevSrcStart;
- int prevSrcEnd;
- prevNode->GetSrcPositions(prevTriviaStart, prevSrcStart, prevSrcEnd);
- newNode->Init(prevTriviaStart, prevSrcStart, prevSrcEnd);
- }
- #else
- newNode->mTriviaStart = prevNode->mTriviaStart;
- newNode->mSrcStart = prevNode->mSrcStart;
- newNode->mSrcEnd = prevNode->mSrcEnd;
- #endif
- }
- else
- {
- int newTriviaStart;
- int newSrcStart;
- int newSrcEnd;
- newNode->GetSrcPositions(newTriviaStart, newSrcStart, newSrcEnd);
- int prevTriviaStart;
- int prevSrcStart;
- int prevSrcEnd;
- prevNode->GetSrcPositions(prevTriviaStart, prevSrcStart, prevSrcEnd);
- if (prevTriviaStart < newTriviaStart)
- newNode->SetTriviaStart(prevTriviaStart);
- if (prevSrcStart < newSrcStart)
- newNode->SetSrcStart(prevSrcStart);
- if (prevSrcEnd > newSrcEnd)
- newNode->SetSrcEnd(prevSrcEnd);
- }
- #ifdef BF_AST_HAS_PARENT_MEMBER
- prevNode->mParent = newNode;
- #endif
- }
- BfAstNode* BfReducer::Fail(const StringImpl& errorMsg, BfAstNode* refNode)
- {
- mStmtHasError = true;
- if (mPassInstance->HasLastFailedAt(refNode)) // No duplicate failures
- return NULL;
- auto error = mPassInstance->Fail(errorMsg, refNode);
- if ((error != NULL) && (mSource != NULL))
- error->mProject = mSource->mProject;
- return NULL;
- }
- BfAstNode* BfReducer::FailAfter(const StringImpl& errorMsg, BfAstNode* prevNode)
- {
- mStmtHasError = true;
- auto error = mPassInstance->FailAfter(errorMsg, prevNode);
- if ((error != NULL) && (mSource != NULL))
- error->mProject = mSource->mProject;
- return NULL;
- }
- void BfReducer::AddErrorNode(BfAstNode* astNode, bool removeNode)
- {
- if (mSource != NULL)
- mSource->AddErrorNode(astNode);
- if (removeNode)
- astNode->RemoveSelf();
- mLastErrorSrcEnd = BF_MAX(mLastErrorSrcEnd, astNode->mSrcEnd);
- }
- bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int endNode, int* retryNode, int* outEndNode, bool* couldBeExpr, bool* isGenericType, bool* isTuple)
- {
- if (!AssertCurrentNode(checkNode))
- return false;
- if (couldBeExpr != NULL)
- *couldBeExpr = true;
- if (outEndNode != NULL)
- *outEndNode = -1;
- auto firstNode = checkNode;
- if (checkNode == NULL)
- return false;
- int checkIdx = mVisitorPos.mReadPos;
- if ((!checkNode->IsA<BfIdentifierNode>()) && (!checkNode->IsA<BfMemberReferenceExpression>()))
- {
- if (auto checkTokenNode = BfNodeDynCast<BfTokenNode>(checkNode))
- {
- BfToken checkToken = checkTokenNode->GetToken();
- if ((checkToken == BfToken_Ref) || (checkToken == BfToken_Mut))
- {
- checkIdx++;
- if (mVisitorPos.Get(checkIdx) == NULL)
- return false;
- }
- else if ((checkToken == BfToken_Var) || (checkToken == BfToken_Let))
- {
- checkIdx++;
- checkNode = mVisitorPos.Get(checkIdx);
- checkTokenNode = BfNodeDynCast<BfTokenNode>(checkNode);
- if (outEndNode)
- *outEndNode = checkIdx;
- if (successToken == BfToken_None)
- return true;
- return (checkToken == successToken);
- }
- else if (checkToken == BfToken_Unsigned)
- {
- // Unsigned val start
- }
- else if (checkToken == BfToken_LParen)
- {
- // Tuple start
- }
- else if ((checkToken == BfToken_Comptype) || (checkToken == BfToken_Decltype) || (checkToken == BfToken_AllocType) || (checkToken == BfToken_RetType) || (checkToken == BfToken_Nullable))
- {
- // Decltype start
- }
- else if ((checkToken == BfToken_Delegate) || (checkToken == BfToken_Function))
- {
- int startNode = mVisitorPos.mReadPos;
- mVisitorPos.mReadPos++;
- int endNode = -1;
- bool failed = false;
- // Return type
- auto checkNode = mVisitorPos.GetCurrent();
- if (auto checkToken = BfNodeDynCast<BfTokenNode>(checkNode))
- {
- if (checkToken->mToken == BfToken_LBracket)
- {
- while (true)
- {
- mVisitorPos.mReadPos++;
- checkNode = mVisitorPos.GetCurrent();
- if (checkNode == NULL)
- {
- failed = true;
- break;
- }
- if (BfNodeIsA<BfBlock>(checkNode))
- {
- failed = true;
- break;
- }
- if (checkToken = BfNodeDynCast<BfTokenNode>(checkNode))
- {
- if (checkToken->mToken == BfToken_RBracket)
- {
- mVisitorPos.mReadPos++;
- checkNode = mVisitorPos.GetCurrent();
- break;
- }
- if ((checkToken->mToken != BfToken_Comma) &&
- (checkToken->mToken != BfToken_Dot) &&
- (checkToken->mToken != BfToken_LParen) &&
- (checkToken->mToken != BfToken_RParen))
- {
- failed = true;
- break;
- }
- }
- }
- }
- }
- if ((failed) || (checkNode == NULL) || (!IsTypeReference(checkNode, BfToken_LParen, -1, &endNode, couldBeExpr, isGenericType, isTuple)))
- {
- if (outEndNode != NULL)
- *outEndNode = endNode;
- mVisitorPos.mReadPos = startNode;
- return false;
- }
- // Take in params as a tuple
- mVisitorPos.mReadPos = endNode;
- auto currentNode = mVisitorPos.GetCurrent();
- bool hasParams = false;
- if (currentNode != NULL)
- {
- if (auto openToken = BfNodeDynCast<BfTokenNode>(currentNode))
- {
- if (openToken->GetToken() == BfToken_LParen)
- {
- int parenDepth = 1;
- // Do a smarter check?
- checkIdx = endNode + 1;
- while (true)
- {
- auto checkNode = mVisitorPos.Get(checkIdx);
- if (checkNode == NULL)
- break;
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(checkNode))
- {
- bool done = false;
- switch (tokenNode->GetToken())
- {
- case BfToken_LParen:
- parenDepth++;
- break;
- case BfToken_RParen:
- parenDepth--;
- if (parenDepth == 0)
- {
- endNode = checkIdx + 1;
- done = true;
- }
- break;
- case BfToken_Semicolon:
- // Failed
- done = true;
- break;
- default: break;
- }
- if (done)
- break;
- }
- checkIdx++;
- }
- hasParams = parenDepth == 0;
- }
- }
- }
- if (!hasParams)
- {
- if (outEndNode != NULL)
- *outEndNode = endNode;
- mVisitorPos.mReadPos = startNode;
- return false;
- }
- if (outEndNode != NULL)
- *outEndNode = endNode;
- mVisitorPos.mReadPos = startNode;
- return true;
- }
- else if (BfTokenIsTypeDecl(checkToken))
- {
- checkIdx++;
- auto nextNode = mVisitorPos.Get(checkIdx);
- if (auto block = BfNodeDynCast<BfBlock>(nextNode))
- {
- if (outEndNode != NULL)
- *outEndNode = checkIdx;
- return true;
- }
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (tokenNode->mToken == BfToken_Colon)
- {
- while (true)
- {
- checkIdx++;
- auto checkNode = mVisitorPos.Get(checkIdx);
- if (checkNode == NULL)
- return false;
- if (auto block = BfNodeDynCast<BfBlock>(checkNode))
- {
- if (outEndNode != NULL)
- *outEndNode = checkIdx;
- return true;
- }
- }
- }
- }
- return false;
- }
- else
- return false;
- }
- else
- return false;
- }
- int chevronDepth = 0;
- bool identifierExpected = true;
- int endBracket = -1;
- int bracketDepth = 0;
- int parenDepth = 0;
- bool hadTupleComma = false;
- bool hadIdentifier = false;
- bool foundSuccessToken = false;
- bool hadUnexpectedIdentifier = false;
- BfTokenNode* lastToken = NULL;
- SizedArray<BfToken, 8> tokenStack;
- while (true)
- {
- if ((endNode != -1) && (checkIdx >= endNode))
- break;
- auto checkNode = mVisitorPos.Get(checkIdx);
- if (checkNode == NULL)
- break;
- auto checkTokenNode = BfNodeDynCast<BfTokenNode>(checkNode);
- if (checkTokenNode != NULL)
- {
- if (endBracket != -1)
- {
- if (outEndNode)
- *outEndNode = endBracket;
- return false;
- }
- BfToken checkToken = checkTokenNode->GetToken();
- if (bracketDepth > 0)
- {
- if ((checkToken == BfToken_LBracket) || (checkToken == BfToken_QuestionLBracket))
- {
- bracketDepth++;
- }
- else if (checkToken == BfToken_RBracket)
- {
- bracketDepth--;
- }
- }
- else
- {
- bool doEnding = (checkToken == successToken) && (checkTokenNode != firstNode) && (tokenStack.size() <= 1);
- if ((doEnding) && (tokenStack.size() == 1))
- doEnding = checkToken == tokenStack.back();
- if (doEnding)
- {
- bool success = false;
- if ((lastToken != NULL) && ((lastToken->GetToken() == BfToken_RChevron) || (lastToken->GetToken() == BfToken_RDblChevron)))
- {
- if (couldBeExpr != NULL)
- *couldBeExpr = false;
- }
- if (successToken == BfToken_RParen)
- {
- success = (chevronDepth == 0) && (bracketDepth == 0) && (parenDepth == 1);
- if (success)
- {
- // Check identifierExpected - this catches (.) casts
- if ((identifierExpected) && (couldBeExpr != NULL))
- *couldBeExpr = false;
- }
- }
- else if ((successToken == BfToken_Comma) ||
- (successToken == BfToken_LBracket))
- {
- success = (chevronDepth == 0) && (bracketDepth == 0) && (parenDepth == 0);
- }
- if ((success) || (doEnding))
- {
- if ((!hadTupleComma) && (hadUnexpectedIdentifier)) // Looked like a tuple but wasn't
- return false;
- }
- if (success)
- {
- if (outEndNode != NULL)
- *outEndNode = checkIdx;
- return true;
- }
- if (doEnding)
- {
- if (outEndNode != NULL)
- *outEndNode = checkIdx;
- return (chevronDepth == 0) && (bracketDepth == 0) && (parenDepth == 0);
- }
- }
- bool isDone = false;
- if (checkToken == BfToken_LParen)
- {
- if (chevronDepth > 0)
- {
- SetAndRestoreValue<int> prevIdx(mVisitorPos.mReadPos, checkIdx);
- int endToken = 0;
- if (!IsTypeReference(checkNode, BfToken_RParen, -1, &endToken, NULL, NULL, NULL))
- return false;
- checkIdx = endToken + 1;
- continue;
- }
- else if ((hadIdentifier) && (chevronDepth == 0) && (bracketDepth == 0) && (parenDepth == 0))
- isDone = true;
- else
- {
- tokenStack.Add(BfToken_RParen);
- parenDepth++;
- }
- }
- else if (checkToken == BfToken_RParen)
- {
- if ((parenDepth == 0) || (tokenStack.back() != BfToken_RParen))
- {
- if (outEndNode != NULL)
- *outEndNode = checkIdx;
- return false;
- }
- tokenStack.pop_back();
- parenDepth--;
- if (parenDepth > 0)
- {
- // if we are embedded in a multi-tuple like (A, (B, C), D) then we expect a , or ) after
- // closing an inner tuple. Otherwise this is an expression like ((Type)a)
- auto nextNode = mVisitorPos.Get(checkIdx + 1);
- bool isOkay = false;
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- isOkay = (nextToken->mToken == BfToken_Comma) || (nextToken->mToken == BfToken_RParen);
- if ((!tokenStack.IsEmpty()) && (nextToken->mToken == tokenStack.back()))
- isOkay = true;
- }
- if (!isOkay)
- {
- if (outEndNode != NULL)
- *outEndNode = checkIdx;
- return false;
- }
- }
- if ((parenDepth < 0) ||
- // Probably a cast
- ((successToken == BfToken_None) && (parenDepth == 0) && (!hadTupleComma)))
- {
- if (successToken == BfToken_RParen)
- {
- foundSuccessToken = true;
- break;
- }
- else
- {
- if (outEndNode != NULL)
- *outEndNode = checkIdx;
- return false;
- }
- }
- }
- else if ((checkToken == BfToken_Const) && (chevronDepth > 0))
- {
- if (mCompatMode)
- {
- identifierExpected = true;
- }
- else
- {
- int prevReadPos = mVisitorPos.mReadPos;
- auto nextNode = mVisitorPos.Get(checkIdx + 1);
- if (nextNode != NULL)
- {
- mVisitorPos.mReadPos = checkIdx + 1;
- auto expr = CreateExpression(nextNode, CreateExprFlags_BreakOnRChevron);
- int endExprReadPos = mVisitorPos.mReadPos;
- mVisitorPos.mReadPos = prevReadPos;
- if (expr == NULL)
- {
- if (outEndNode != NULL)
- *outEndNode = checkIdx;
- return false;
- }
- checkIdx = endExprReadPos;
- }
- }
- }
- else if ((checkToken == BfToken_Minus) && (mCompatMode) && (chevronDepth > 0) && (parenDepth == 0) && (bracketDepth == 0))
- {
- // Allow
- }
- else if (checkToken == BfToken_Unsigned)
- {
- identifierExpected = true;
- }
- else if ((checkToken == BfToken_Ref) || (checkToken == BfToken_Mut))
- {
- identifierExpected = true;
- }
- else if (checkToken == BfToken_LChevron)
- {
- identifierExpected = true;
- chevronDepth++;
- tokenStack.Add(BfToken_RChevron);
- *retryNode = checkIdx;
- }
- else if ((checkToken == BfToken_RChevron) || (checkToken == BfToken_RDblChevron))
- {
- *retryNode = -1;
- if (tokenStack.IsEmpty())
- break;
- for (int i = 0; i < ((checkToken == BfToken_RDblChevron) ? 2 : 1); i++)
- {
- if (tokenStack.back() != BfToken_RChevron)
- {
- if (outEndNode != NULL)
- *outEndNode = checkIdx;
- return false;
- }
- tokenStack.pop_back();
- chevronDepth--;
- }
- identifierExpected = false;
- if (chevronDepth < 0)
- {
- if (outEndNode != NULL)
- *outEndNode = checkIdx;
- return false;
- }
- if (chevronDepth == 0)
- {
- if (isGenericType != NULL)
- *isGenericType = true;
- }
- }
- else if (checkToken == BfToken_RDblChevron)
- chevronDepth -= 2;
- else if (checkToken == BfToken_Comma)
- {
- if ((bracketDepth == 0) && (tokenStack.IsEmpty()))
- {
- if (outEndNode != NULL)
- *outEndNode = checkIdx;
- return false;
- }
- if ((!tokenStack.IsEmpty()) && (tokenStack.back() == BfToken_RParen))
- {
- hadTupleComma = true;
- if (isTuple != NULL)
- {
- *isTuple = true;
- }
- }
- identifierExpected = true;
- }
- else if (checkToken == BfToken_Dot)
- {
- auto prevNode = mVisitorPos.Get(checkIdx - 1);
- if (auto prevToken = BfNodeDynCast<BfTokenNode>(prevNode))
- {
- if (couldBeExpr != NULL)
- {
- // UH- NO, it could be referencing a static member
- // a ">." can only be a reference to an inner type of a generic type
- //if ((prevToken->GetToken() == BfToken_RChevron) || (prevToken->GetToken() == BfToken_RDblChevron))
- //*couldBeExpr = false;
- }
- // a ".[" can only be a member reference after an indexer expression
- if (prevToken->GetToken() == BfToken_RBracket)
- {
- if (outEndNode != NULL)
- *outEndNode = checkIdx;
- return false;
- }
- }
- identifierExpected = true;
- }
- else if (checkToken == BfToken_RBracket)
- {
- if (bracketDepth == 0)
- {
- // Not even an array
- return false;
- }
- endBracket = checkIdx;
- }
- else if ((checkToken == BfToken_Star) || (checkToken == BfToken_Question))
- {
- bool keepParsing = false;
- if (checkToken == BfToken_Star)
- {
- auto prevNode = mVisitorPos.Get(checkIdx - 1);
- if (auto prevToken = BfNodeDynCast<BfTokenNode>(prevNode))
- {
- switch (prevToken->GetToken())
- {
- case BfToken_RParen:
- case BfToken_RBracket:
- case BfToken_RChevron:
- case BfToken_RDblChevron:
- break;
- default:
- // These are definitely dereferences
- return false;
- }
- }
- while (true)
- {
- auto nextNode = mVisitorPos.Get(checkIdx + 1);
- auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode);
- if ((nextToken != NULL) && (nextToken->GetToken() == BfToken_LBracket))
- {
- keepParsing = true;
- break;
- }
- if ((nextToken == NULL) || (nextToken->GetToken() != BfToken_Star))
- break;
- checkTokenNode = nextToken;
- checkToken = checkTokenNode->GetToken();
- checkIdx++;
- }
- }
- else
- {
- auto prevNode = mVisitorPos.Get(checkIdx - 1);
- if (auto prevToken = BfNodeDynCast<BfTokenNode>(prevNode))
- {
- // If this is just a 'loose' comma then it can't be part of a nullable
- if (((prevToken->GetToken() == BfToken_Comma) && (chevronDepth == 0)) ||
- (prevToken->GetToken() == BfToken_LParen))
- {
- return false;
- }
- }
- }
- // Star or Question normally end a TypeRef
- if (keepParsing)
- {
- // Keep going
- }
- else if ((chevronDepth == 0) && (parenDepth == 0) && (bracketDepth == 0))
- {
- if (hadTupleComma)
- return false;
- if (couldBeExpr != NULL)
- *couldBeExpr = false;
- if (outEndNode != NULL)
- *outEndNode = checkIdx + 1;
- if (successToken == BfToken_None)
- return true;
- auto nextNode = mVisitorPos.Get(checkIdx + 1);
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (nextToken->GetToken() == successToken)
- {
- if (outEndNode != NULL)
- *outEndNode = checkIdx + 1;
- return true;
- }
- if (nextToken->GetToken() == BfToken_LBracket)
- {
- // A rare case of something like "char*[...]", let the bracket information through
- }
- else
- break;
- }
- else
- return false;
- }
- }
- else if ((checkToken == BfToken_LBracket) || (checkToken == BfToken_QuestionLBracket))
- {
- auto prevNode = mVisitorPos.Get(checkIdx - 1);
- if (auto prevToken = BfNodeDynCast<BfTokenNode>(prevNode))
- {
- // .[ - that's not a valid type, but could be an attributed member reference
- if ((prevToken->GetToken() == BfToken_Dot) || (prevToken->GetToken() == BfToken_DotDot))
- {
- if (outEndNode != NULL)
- *outEndNode = checkIdx - 1;
- return false;
- }
- }
- bracketDepth++;
- }
- else if (checkToken == BfToken_This)
- {
- if ((parenDepth == 1) && (hadIdentifier))
- {
- // If this looks like it's from a '(<type> this ...)' then it could be part of a function declaration, so allow it
- }
- else
- {
- if (outEndNode != NULL)
- *outEndNode = checkIdx;
- return false;
- }
- }
- else if ((checkToken == BfToken_Delegate) || (checkToken == BfToken_Function))
- {
- int funcEndNode = -1;
- int prevReadPos = mVisitorPos.mReadPos;
- mVisitorPos.mReadPos = checkIdx;
- bool isTypeRef = IsTypeReference(checkNode, BfToken_None, -1, &funcEndNode);
- mVisitorPos.mReadPos = prevReadPos;
- if (!isTypeRef)
- {
- if (outEndNode != NULL)
- *outEndNode = checkIdx;
- return false;
- }
- checkIdx = funcEndNode;
- continue;
- }
- else if ((checkToken == BfToken_Comptype) || (checkToken == BfToken_Decltype) || (checkToken == BfToken_AllocType) || (checkToken == BfToken_RetType) || (checkToken == BfToken_Nullable))
- {
- int endNodeIdx = checkIdx + 1;
- auto nextNode = mVisitorPos.Get(checkIdx + 1);
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (tokenNode->mToken != BfToken_LParen)
- {
- isDone = true;
- }
- else
- {
- int openCount = 1;
- while (true)
- {
- endNodeIdx++;
- auto checkNextNode = mVisitorPos.Get(endNodeIdx);
- if (checkNextNode == NULL)
- break;
- if (auto checkNextToken = BfNodeDynCast<BfTokenNode>(checkNextNode))
- {
- if (checkNextToken->GetToken() == BfToken_LParen)
- openCount++;
- else if (checkNextToken->GetToken() == BfToken_RParen)
- {
- openCount--;
- if (openCount == 0)
- break;
- }
- }
- }
- }
- }
- identifierExpected = false;
- checkIdx = endNodeIdx;
- /*if (outEndNode != NULL)
- *outEndNode = endNodeIdx + 1;
- return true;*/
- }
- else if ((checkToken == BfToken_DotDotDot) && (chevronDepth > 0))
- {
- isDone = true;
- auto prevNode = mVisitorPos.Get(checkIdx + 1);
- if (prevNode = BfNodeDynCast<BfLiteralExpression>(prevNode))
- {
- // Allow expressions like '3...'
- isDone = false;
- }
- auto nextNode = mVisitorPos.Get(checkIdx + 1);
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if ((nextToken->mToken == BfToken_RChevron) || (nextToken->mToken == BfToken_RDblChevron))
- isDone = false;
- }
- }
- else if ((checkToken == BfToken_Minus) && (chevronDepth > 0))
- {
- // Allow - literal
- }
- else if (checkToken != BfToken_LBracket)
- isDone = true;
- if (isDone)
- {
- if (outEndNode != NULL)
- *outEndNode = checkIdx;
- if (isGenericType != NULL)
- *isGenericType = false;
- return false;
- }
- }
- }
- else if (bracketDepth > 0)
- {
- // Ignore
- }
- else if ((checkNode->IsA<BfIdentifierNode>()) || (checkNode->IsA<BfMemberReferenceExpression>()))
- {
- // Identifier is always allowed in tuple (parenDepth == 0), because it's potentially the field name
- // (successToken == BfToken_RParen) infers we are already checking inside parentheses, such as
- // when we see a potential cast expression
- if (!identifierExpected)
- {
- if ((parenDepth == 0) && (successToken != BfToken_RParen))
- {
- if (outEndNode != NULL)
- *outEndNode = checkIdx;
- if (successToken == BfToken_None)
- return chevronDepth == 0;
- return false;
- }
- hadUnexpectedIdentifier = true;
- }
- // if (checkNode->Equals("tag"))
- // {
- // // Keep looking for tag name
- // }
- // else
- {
- hadIdentifier = true;
- identifierExpected = false;
- }
- }
- else if (checkNode->IsA<BfBlock>())
- {
- if (successToken == BfToken_LBrace)
- {
- foundSuccessToken = true;
- }
- break;
- }
- else if ((mCompatMode) && (checkNode->IsExact<BfLiteralExpression>()) && (chevronDepth > 0) && (identifierExpected))
- {
- // Allow
- identifierExpected = false;
- }
- else
- {
- bool mayBeExprPart = false;
- if (chevronDepth > 0)
- {
- if (checkNode->IsExact<BfLiteralExpression>())
- mayBeExprPart = true;
- else if (auto tokenNode = BfNodeDynCast<BfTokenNode>(checkNode))
- {
- if (tokenNode->mToken == BfToken_Question)
- mayBeExprPart = true;
- }
- }
- if (!mayBeExprPart)
- {
- if (outEndNode != NULL)
- *outEndNode = checkIdx;
- return false;
- }
- }
- lastToken = checkTokenNode;
- checkIdx++;
- }
- if (outEndNode != NULL)
- *outEndNode = checkIdx;
- if ((!hadTupleComma) && (hadUnexpectedIdentifier)) // Looked like a tuple but wasn't
- return false;
- return (hadIdentifier) && (chevronDepth == 0) && (bracketDepth == 0) && (parenDepth == 0) && ((successToken == BfToken_None) || (foundSuccessToken));
- }
- static int sTRIdx = 0;
- bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int endNode, int* outEndNode, bool* couldBeExpr, bool* isGenericType, bool* isTuple)
- {
- int retryNode = -1;
- if (IsTypeReference(checkNode, successToken, endNode, &retryNode, outEndNode, couldBeExpr, isGenericType, isTuple))
- return true;
- if ((retryNode != -1) && (successToken == BfToken_None))
- {
- int newEndNode = -1;
- if (IsTypeReference(checkNode, successToken, retryNode, &retryNode, &newEndNode, couldBeExpr, isGenericType, isTuple))
- {
- if (outEndNode != NULL)
- *outEndNode = newEndNode;
- return true;
- }
- }
- return false;
- }
- bool BfReducer::IsLocalMethod(BfAstNode* nameNode)
- {
- if (!AssertCurrentNode(nameNode))
- return false;
- int parenDepth = 0;
- bool hadParens = false;
- int chevronDepth = 0;
- bool hadGenericParams = false;
- int checkIdx = mVisitorPos.mReadPos + 1;
- while (true)
- {
- auto checkNode = mVisitorPos.Get(checkIdx);
- if (checkNode == NULL)
- return false;
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(checkNode))
- {
- BfToken token = tokenNode->GetToken();
- if (token == BfToken_LParen)
- {
- parenDepth++;
- hadParens = true;
- }
- else if (token == BfToken_RParen)
- {
- parenDepth--;
- if (parenDepth == 0)
- return true;
- }
- else
- {
- switch (token)
- {
- case BfToken_Semicolon: // Never can be a local method
- return false;
- case BfToken_Where: // Always denotes a local method
- return true;
- default: break;
- }
- }
- }
- else if (auto tokenNode = BfNodeDynCast<BfBlock>(checkNode))
- {
- //return (hadParens) && (parenDepth == 0);
- return false;
- }
- else
- {
- }
- checkIdx++;
- }
- return false;
- }
- int BfReducer::QualifiedBacktrack(BfAstNode* endNode, int checkIdx, bool* outHadChevrons)
- {
- auto checkNode = endNode;
- BF_ASSERT(checkNode == mVisitorPos.Get(checkIdx));
- int chevronDepth = 0;
- bool identifierExpected = true;
- bool hadEndBracket = false;
- bool lastWasIdentifier = false;
- while (checkNode != NULL)
- {
- auto checkTokenNode = BfNodeDynCast<BfTokenNode>(checkNode);
- if (checkTokenNode != NULL)
- {
- BfToken checkToken = checkTokenNode->GetToken();
- if ((checkToken == BfToken_Dot) || (checkToken == BfToken_DotDot))
- {
- if (chevronDepth == 0)
- return checkIdx;
- }
- else if (checkToken == BfToken_LChevron)
- {
- if (outHadChevrons != NULL)
- *outHadChevrons = true;
- chevronDepth++;
- }
- else if (checkToken == BfToken_RChevron)
- {
- // Was this a case like "Test<T> MethodName"? Those are split.
- if (lastWasIdentifier)
- return -1;
- chevronDepth--;
- }
- else if (checkToken == BfToken_RDblChevron)
- {
- if (lastWasIdentifier)
- return -1;
- chevronDepth -= 2;
- }
- else if ((checkToken != BfToken_Comma) &&
- (checkToken != BfToken_Dot) &&
- (checkToken != BfToken_DotDot) &&
- (checkToken != BfToken_RBracket) &&
- (checkToken != BfToken_Star) &&
- (checkToken != BfToken_Question) &&
- (checkToken != BfToken_LBracket))
- {
- return -1;
- }
- if (chevronDepth == 0)
- return -1;
- lastWasIdentifier = false;
- }
- else if (checkNode->IsA<BfIdentifierNode>())
- {
- // Two identifiers in a row denotes a break
- if (lastWasIdentifier)
- return -1;
- lastWasIdentifier = true;
- }
- else
- {
- return -1;
- }
- checkIdx--;
- checkNode = mVisitorPos.Get(checkIdx);
- }
- return -1;
- }
- BfExpression* BfReducer::ApplyToFirstExpression(BfUnaryOperatorExpression* unaryOp, BfExpression* target)
- {
- auto condExpression = BfNodeDynCast<BfConditionalExpression>(target);
- if (condExpression != NULL)
- {
- auto result = ApplyToFirstExpression(unaryOp, condExpression->mConditionExpression);
- if (result == condExpression->mConditionExpression)
- {
- //TODO: Make sure this one works, check children and next's and such
- //ReplaceNode(unaryOp, binOpExpression);
- unaryOp->mExpression = condExpression->mConditionExpression;
- ReplaceNode(unaryOp, condExpression);
- unaryOp->SetSrcEnd(condExpression->mConditionExpression->GetSrcEnd());
- condExpression->mConditionExpression = unaryOp;
- }
- condExpression->SetSrcStart(unaryOp->GetSrcStart());
- return result;
- }
- auto binOpExpression = BfNodeDynCast<BfBinaryOperatorExpression>(target);
- if (binOpExpression != NULL)
- {
- auto result = ApplyToFirstExpression(unaryOp, binOpExpression->mLeft);
- if (result == binOpExpression->mLeft)
- {
- unaryOp->mExpression = binOpExpression->mLeft;
- unaryOp->SetSrcEnd(binOpExpression->mLeft->GetSrcEnd());
- binOpExpression->mLeft = unaryOp;
- }
- binOpExpression->SetSrcStart(unaryOp->GetSrcStart());
- return result;
- }
- return target;
- }
- static String DbgNodeToString(BfAstNode* astNode)
- {
- if (auto binOpExpr = BfNodeDynCast<BfBinaryOperatorExpression>(astNode))
- {
- String str;
- str += "(";
- str += DbgNodeToString(binOpExpr->mLeft);
- str += " ";
- str += DbgNodeToString(binOpExpr->mOpToken);
- str += " ";
- str += DbgNodeToString(binOpExpr->mRight);
- str += ")";
- return str;
- }
- else if (auto condExpr = BfNodeDynCast<BfConditionalExpression>(astNode))
- {
- String str;
- str += "( ";
- str += "(";
- str += DbgNodeToString(condExpr->mConditionExpression);
- str += ") ? (";
- str += DbgNodeToString(condExpr->mTrueExpression);
- str += ") : (";
- str += DbgNodeToString(condExpr->mFalseExpression);
- str += ")";
- str += " )";
- return str;
- }
- return astNode->ToString();
- }
- BfExpression* BfReducer::CheckBinaryOperatorPrecedence(BfBinaryOperatorExpression* binOpExpression)
- {
- BfExpression* resultExpr = binOpExpression;
- bool dbg = false;
- #ifdef BF_AST_HAS_PARENT_MEMBER
- BF_ASSERT(BfNodeDynCast<BfBinaryOperatorExpression>(binOpExpression->mParent) == NULL);
- #endif
- SizedArray<BfBinaryOperatorExpression*, 8> binOpParents;
- SizedArray<BfBinaryOperatorExpression*, 8> deferredChecks;
- BfBinaryOperatorExpression* checkBinOpExpression = binOpExpression;
- while (true)
- {
- if (checkBinOpExpression == NULL)
- {
- if (deferredChecks.size() == 0)
- break;
- checkBinOpExpression = deferredChecks.back();
- deferredChecks.pop_back();
- }
- if (dbg)
- OutputDebugStrF("Checking: %s\n", DbgNodeToString(checkBinOpExpression).c_str());
- #ifdef BF_AST_HAS_PARENT_MEMBER
- BfBinaryOperatorExpression* prevBinOpExpression = BfNodeDynCast<BfBinaryOperatorExpression>(checkBinOpExpression->mParent);
- if (prevBinOpExpression != NULL)
- {
- BF_ASSERT(binOpParents.back() == prevBinOpExpression);
- }
- #else
- BfBinaryOperatorExpression* prevBinOpExpression = NULL;
- #endif
- if (!binOpParents.IsEmpty())
- {
- prevBinOpExpression = binOpParents.back();
- }
- BfBinaryOperatorExpression* nextBinaryOperatorExpression = NULL;
- bool didCondSwap = false;
- while (auto rightCondExpression = BfNodeDynCast<BfConditionalExpression>(checkBinOpExpression->mRight))
- {
- if (rightCondExpression->mTrueExpression == NULL)
- break;
- // Turn (A || (B ? C : D)) into ((A || B) ? C : D)
- BfExpression* exprA = checkBinOpExpression->mLeft;
- BfExpression* exprB = rightCondExpression->mConditionExpression;
- BfExpression* exprC = rightCondExpression->mTrueExpression;
- checkBinOpExpression->SetSrcEnd(exprB->GetSrcEnd());
- MEMBER_SET(rightCondExpression, mConditionExpression, checkBinOpExpression);
- MEMBER_SET(checkBinOpExpression, mLeft, exprA);
- MEMBER_SET(checkBinOpExpression, mRight, exprB);
- didCondSwap = true;
- if (dbg)
- {
- OutputDebugStrF("NewCond: %s\n", DbgNodeToString(rightCondExpression).c_str());
- OutputDebugStrF("CheckAfterCond: %s\n", DbgNodeToString(checkBinOpExpression).c_str());
- }
- if (prevBinOpExpression != NULL)
- {
- BF_ASSERT(checkBinOpExpression == prevBinOpExpression->mRight);
- MEMBER_SET(prevBinOpExpression, mRight, rightCondExpression);
- nextBinaryOperatorExpression = prevBinOpExpression;
- binOpParents.pop_back();
- }
- else
- {
- BF_ASSERT(resultExpr == checkBinOpExpression);
- resultExpr = rightCondExpression;
- }
- }
- if (nextBinaryOperatorExpression != NULL)
- {
- checkBinOpExpression = nextBinaryOperatorExpression;
- continue;
- }
- /*auto _CheckLeftBinaryOpearator = [&](BfBinaryOperatorExpression* checkBinOpExpression)
- {
- while (auto leftBinOpExpression = BfNodeDynCast<BfBinaryOperatorExpression>(checkBinOpExpression->mLeft))
- {
- if (dbg)
- {
- OutputDebugStrF("CheckCur : %s\n", DbgNodeToString(checkBinOpExpression).c_str());
- OutputDebugStrF("Left : %s\n", DbgNodeToString(leftBinOpExpression).c_str());
- }
- if (leftBinOpExpression->mRight == NULL)
- {
- BF_ASSERT(mPassInstance->HasFailed());
- return;
- }
- int leftPrecedence = BfGetBinaryOpPrecendence(leftBinOpExpression->mOp);
- int rightPrecedence = BfGetBinaryOpPrecendence(checkBinOpExpression->mOp);
- // Turn ((A + B) * C) into (A + (B * C))
- if (leftPrecedence >= rightPrecedence)
- {
- break;
- }
- BfTokenNode* tokenNode = checkBinOpExpression->mOpToken;
- BfExpression* exprA = leftBinOpExpression->mLeft;
- BfExpression* exprB = leftBinOpExpression->mRight;
- BfExpression* exprC = checkBinOpExpression->mRight;
- auto rightBinOpExpression = leftBinOpExpression; // We reuse this memory for the right side now
- auto binOp = checkBinOpExpression->mOp;
- checkBinOpExpression->mLeft = exprA;
- checkBinOpExpression->mOp = leftBinOpExpression->mOp;
- checkBinOpExpression->mOpToken = leftBinOpExpression->mOpToken;
- checkBinOpExpression->mRight = rightBinOpExpression;
- rightBinOpExpression->mLeft = exprB;
- rightBinOpExpression->mOp = binOp;
- rightBinOpExpression->mOpToken = tokenNode;
- rightBinOpExpression->mRight = exprC;
- rightBinOpExpression->SetSrcStart(rightBinOpExpression->mLeft->GetSrcStart());
- rightBinOpExpression->SetSrcEnd(rightBinOpExpression->mRight->GetSrcEnd());
- if (dbg)
- {
- OutputDebugStrF("CheckAfter : %s\n", DbgNodeToString(checkBinOpExpression).c_str());
- }
- }
- };*/
- while (auto rightBinOpExpression = BfNodeDynCast<BfBinaryOperatorExpression>(checkBinOpExpression->mRight))
- {
- if (dbg)
- {
- OutputDebugStrF("CheckCur : %s\n", DbgNodeToString(checkBinOpExpression).c_str());
- OutputDebugStrF("Right : %s\n", DbgNodeToString(rightBinOpExpression).c_str());
- }
- if (rightBinOpExpression->mRight == NULL)
- {
- BF_ASSERT(mPassInstance->HasFailed());
- return binOpExpression;
- }
- int leftPrecedence = BfGetBinaryOpPrecendence(checkBinOpExpression->mOp);
- int rightPrecedence = BfGetBinaryOpPrecendence(rightBinOpExpression->mOp);
- // Turn (A * (B + C)) into ((A * B) + C)
- // Note: this DOES need to be '<' in order to preserve left-to-right evaluation when precedence is equal
- if (leftPrecedence < rightPrecedence)
- {
- binOpParents.Add(checkBinOpExpression);
- nextBinaryOperatorExpression = rightBinOpExpression;
- break;
- }
- BfTokenNode* tokenNode = checkBinOpExpression->mOpToken;
- BfExpression* exprA = checkBinOpExpression->mLeft;
- BfExpression* exprB = rightBinOpExpression->mLeft;
- BfExpression* exprC = rightBinOpExpression->mRight;
- auto leftBinOpExpression = rightBinOpExpression; // We reuse this memory for the left side now
- auto binOp = checkBinOpExpression->mOp;
- checkBinOpExpression->mLeft = leftBinOpExpression;
- checkBinOpExpression->mOp = rightBinOpExpression->mOp;
- checkBinOpExpression->mOpToken = rightBinOpExpression->mOpToken;
- checkBinOpExpression->mRight = exprC;
- leftBinOpExpression->mLeft = exprA;
- leftBinOpExpression->mOp = binOp;
- leftBinOpExpression->mOpToken = tokenNode;
- leftBinOpExpression->mRight = exprB;
- leftBinOpExpression->SetSrcStart(leftBinOpExpression->mLeft->GetSrcStart());
- leftBinOpExpression->SetSrcEnd(leftBinOpExpression->mRight->GetSrcEnd());
- if (dbg)
- {
- OutputDebugStrF("CheckAfter: %s\n", DbgNodeToString(checkBinOpExpression).c_str());
- }
- if ((leftPrecedence > rightPrecedence) && (prevBinOpExpression != NULL))
- {
- // Backtrack
- nextBinaryOperatorExpression = prevBinOpExpression;
- binOpParents.pop_back();
- break;
- }
- if (auto leftBinaryExpr = BfNodeDynCast<BfBinaryOperatorExpression>(checkBinOpExpression->mLeft))
- {
- deferredChecks.push_back(leftBinaryExpr);
- }
- }
- checkBinOpExpression = nextBinaryOperatorExpression;
- }
- if (dbg)
- OutputDebugStrF("NodeOut: %s\n", DbgNodeToString(resultExpr).c_str());
- return resultExpr;
- }
- BfAstNode* BfReducer::ReplaceTokenStarter(BfAstNode* astNode, int idx, bool allowIn)
- {
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(astNode))
- {
- if ((tokenNode->GetToken() == BfToken_As) ||
- ((tokenNode->GetToken() == BfToken_In) && (!allowIn)))
- {
- if (idx == -1)
- idx = mVisitorPos.mReadPos;
- BF_ASSERT(mVisitorPos.Get(idx) == astNode);
- auto identifierNode = mAlloc->Alloc<BfIdentifierNode>();
- ReplaceNode(tokenNode, identifierNode);
- mVisitorPos.Set(idx, identifierNode);
- return identifierNode;
- }
- }
- return astNode;
- }
- BfEnumCaseBindExpression* BfReducer::CreateEnumCaseBindExpression(BfTokenNode* bindToken)
- {
- auto bindExpr = mAlloc->Alloc<BfEnumCaseBindExpression>();
- MEMBER_SET(bindExpr, mBindToken, bindToken);
- mVisitorPos.MoveNext();
- auto nextNode = mVisitorPos.GetNext();
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (nextToken->GetToken() == BfToken_Dot)
- {
- auto memberReferenceExpr = mAlloc->Alloc<BfMemberReferenceExpression>();
- MEMBER_SET(memberReferenceExpr, mDotToken, nextToken);
- mVisitorPos.MoveNext();
- auto memberName = ExpectIdentifierAfter(memberReferenceExpr);
- if (memberName != NULL)
- {
- MEMBER_SET(memberReferenceExpr, mMemberName, memberName);
- }
- MEMBER_SET(bindExpr, mEnumMemberExpr, memberReferenceExpr);
- }
- }
- if (bindExpr->mEnumMemberExpr == NULL)
- {
- auto typeRef = CreateTypeRefAfter(bindExpr);
- if (typeRef != NULL)
- {
- if (auto namedTypeRef = BfNodeDynCast<BfNamedTypeReference>(typeRef))
- {
- MEMBER_SET(bindExpr, mEnumMemberExpr, namedTypeRef->mNameNode);
- }
- else
- {
- auto memberRefExpr = mAlloc->Alloc<BfMemberReferenceExpression>();
- if (auto qualifiedTypeRef = BfNodeDynCast<BfQualifiedTypeReference>(typeRef))
- {
- if (auto namedTypeRef = BfNodeDynCast<BfNamedTypeReference>(qualifiedTypeRef->mRight))
- {
- MEMBER_SET(memberRefExpr, mTarget, qualifiedTypeRef->mLeft);
- MEMBER_SET(memberRefExpr, mDotToken, qualifiedTypeRef->mDot);
- MEMBER_SET(memberRefExpr, mMemberName, namedTypeRef->mNameNode);
- }
- }
- else
- {
- MEMBER_SET(memberRefExpr, mTarget, typeRef);
- }
- MEMBER_SET(bindExpr, mEnumMemberExpr, memberRefExpr);
- }
- }
- if (bindExpr->mEnumMemberExpr == NULL)
- {
- Fail("Expected enum case name", typeRef);
- }
- }
- if (bindExpr->mEnumMemberExpr != NULL)
- {
- auto openToken = ExpectTokenAfter(bindExpr->mEnumMemberExpr, BfToken_LParen);
- if (openToken != NULL)
- {
- auto tupleExpr = CreateTupleExpression(openToken, NULL);
- MEMBER_SET(bindExpr, mBindNames, tupleExpr);
- }
- }
- return bindExpr;
- }
- BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags createExprFlags)
- {
- if (node == NULL)
- return NULL;
- BP_ZONE("CreateExpression");
- //
- {
- BP_ZONE("CreateExpression.CheckStack");
- StackHelper stackHelper;
- if (!stackHelper.CanStackExpand(64 * 1024))
- {
- BfExpression* result = NULL;
- if (!stackHelper.Execute([&]()
- {
- result = CreateExpression(node, createExprFlags);
- }))
- {
- Fail("Expression too complex to parse", node);
- }
- return result;
- }
- }
- if (!AssertCurrentNode(node))
- return NULL;
- auto rhsCreateExprFlags = (CreateExprFlags)(createExprFlags & CreateExprFlags_BreakOnRChevron);
- auto exprLeft = BfNodeDynCast<BfExpression>(node);
- AssertCurrentNode(node);
- if (auto interpolateExpr = BfNodeDynCastExact<BfStringInterpolationExpression>(node))
- {
- for (auto block : interpolateExpr->mExpressions)
- {
- HandleBlock(block, true);
- }
- return interpolateExpr;
- }
- if ((createExprFlags & (CreateExprFlags_AllowVariableDecl | CreateExprFlags_PermissiveVariableDecl)) != 0)
- {
- bool isLocalVariable = false;
- auto nextNode = mVisitorPos.GetNext();
- BfVariableDeclaration* continuingVariable = NULL;
- int outEndNode = -1;
- bool couldBeExpr = false;
- bool isTuple = false;
- if (IsTypeReference(node, BfToken_None, -1, &outEndNode, &couldBeExpr, NULL, &isTuple))
- {
- if ((createExprFlags & CreateExprFlags_PermissiveVariableDecl) != 0)
- isLocalVariable = true;
- else if (auto identifierNode = BfNodeDynCast<BfIdentifierNode>(mVisitorPos.Get(outEndNode)))
- {
- if (auto equalsToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(outEndNode + 1)))
- {
- if (equalsToken->GetToken() == BfToken_AssignEquals)
- isLocalVariable = true;
- }
- //if (!couldBeExpr)
- {
- auto endingTokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(outEndNode - 1));
- // If the type ends with a * or a ? then it could be an expression
- if (endingTokenNode == NULL)
- {
- isLocalVariable = true;
- }
- else
- {
- BfToken endingToken = endingTokenNode->GetToken();
- if (endingToken == BfToken_RParen)
- {
- if (isTuple)
- isLocalVariable = true;
- }
- else if ((endingToken != BfToken_Star) && (endingToken != BfToken_Question))
- isLocalVariable = true;
- }
- }
- }
- if (auto typeNameToken = BfNodeDynCast<BfTokenNode>(node))
- {
- if ((typeNameToken->GetToken() == BfToken_Var) || (typeNameToken->GetToken() == BfToken_Let))
- isLocalVariable = true;
- }
- }
- if (nextNode == NULL)
- {
- // Treat ending identifier as just an identifier (could be block result)
- isLocalVariable = false;
- }
- if ((isLocalVariable) || (continuingVariable != NULL))
- {
- auto variableDeclaration = mAlloc->Alloc<BfVariableDeclaration>();
- BfTypeReference* typeRef = NULL;
- if (continuingVariable != NULL)
- {
- typeRef = continuingVariable->mTypeRef;
- variableDeclaration->mModSpecifier = continuingVariable->mModSpecifier;
- ReplaceNode(node, variableDeclaration);
- variableDeclaration->mPrecedingComma = (BfTokenNode*)node;
- }
- else
- {
- typeRef = CreateTypeRef(node);
- if (typeRef == NULL)
- return NULL;
- ReplaceNode(typeRef, variableDeclaration);
- }
- variableDeclaration->mTypeRef = typeRef;
- BfAstNode* variableNameNode = NULL;
- nextNode = mVisitorPos.GetNext();
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (tokenNode->GetToken() == BfToken_LParen)
- {
- mVisitorPos.mReadPos++;
- variableNameNode = CreateTupleExpression(tokenNode);
- }
- }
- if (variableNameNode == NULL)
- variableNameNode = ExpectIdentifierAfter(variableDeclaration, "variable name");
- if (variableNameNode == NULL)
- return variableDeclaration;
- auto tokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
- variableDeclaration->mNameNode = variableNameNode;
- MoveNode(variableNameNode, variableDeclaration);
- if ((tokenNode != NULL) && (tokenNode->GetToken() == BfToken_AssignEquals))
- {
- MEMBER_SET(variableDeclaration, mEqualsNode, tokenNode);
- mVisitorPos.MoveNext();
- if (variableDeclaration->mInitializer == NULL)
- variableDeclaration->mInitializer = CreateExpressionAfter(variableDeclaration);
- if (variableDeclaration->mInitializer == NULL)
- return variableDeclaration;
- MoveNode(variableDeclaration->mInitializer, variableDeclaration);
- }
- exprLeft = variableDeclaration;
- }
- }
- if (auto block = BfNodeDynCast<BfBlock>(node))
- {
- HandleBlock(block, true);
- exprLeft = block;
- }
- if (auto identifierNode = BfNodeDynCast<BfIdentifierNode>(exprLeft))
- {
- identifierNode = CompactQualifiedName(identifierNode);
- exprLeft = identifierNode;
- if ((mCompatMode) && (exprLeft->ToString() == "defined"))
- {
- auto definedNodeExpr = mAlloc->Alloc<BfPreprocessorDefinedExpression>();
- ReplaceNode(identifierNode, definedNodeExpr);
- auto nextNode = mVisitorPos.GetNext();
- bool hadParenToken = false;
- if (auto parenToken = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (parenToken->GetToken() == BfToken_LParen)
- {
- mVisitorPos.MoveNext();
- MoveNode(parenToken, definedNodeExpr);
- hadParenToken = true;
- }
- }
- auto definedIdentifier = ExpectIdentifierAfter(definedNodeExpr);
- MEMBER_SET_CHECKED(definedNodeExpr, mIdentifier, definedIdentifier);
- if (hadParenToken)
- {
- auto parenToken = ExpectTokenAfter(definedNodeExpr, BfToken_RParen);
- if (parenToken != NULL)
- MoveNode(parenToken, definedNodeExpr);
- }
- exprLeft = definedNodeExpr;
- }
- int endNodeIdx = -1;
- if ((IsTypeReference(exprLeft, BfToken_LBracket, -1, &endNodeIdx, NULL)))
- {
- if (IsTypeReference(exprLeft, BfToken_LBrace, -1, NULL, NULL))
- {
- BfSizedArrayCreateExpression* arrayCreateExpr = mAlloc->Alloc<BfSizedArrayCreateExpression>();
- auto typeRef = CreateTypeRef(exprLeft);
- if (typeRef != NULL)
- {
- ReplaceNode(typeRef, arrayCreateExpr);
- auto arrayType = BfNodeDynCast<BfArrayTypeRef>(typeRef);
- if (arrayType != NULL)
- {
- arrayCreateExpr->mTypeRef = arrayType;
- auto nextNode = mVisitorPos.GetNext();
- auto block = BfNodeDynCast<BfBlock>(nextNode);
- if (block != NULL)
- {
- Fail("Brace initialization is not supported. Enclose initializer with parentheses.", block);
- auto initializerExpr = CreateCollectionInitializerExpression(block);
- MEMBER_SET(arrayCreateExpr, mInitializer, initializerExpr);
- mVisitorPos.MoveNext();
- }
- exprLeft = arrayCreateExpr;
- }
- else
- {
- Fail("Sized array type expected", typeRef);
- }
- }
- }
- else if (IsTypeReference(exprLeft, BfToken_LParen, -1, NULL, NULL))
- {
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(endNodeIdx - 1)))
- {
- if ((tokenNode->mToken == BfToken_Star) || (tokenNode->mToken == BfToken_Question)) // Is it something that can ONLY be a sized type reference?
- {
- BfSizedArrayCreateExpression* arrayCreateExpr = mAlloc->Alloc<BfSizedArrayCreateExpression>();
- auto typeRef = CreateTypeRef(exprLeft);
- if (typeRef != NULL)
- {
- ReplaceNode(typeRef, arrayCreateExpr);
- auto arrayType = BfNodeDynCast<BfArrayTypeRef>(typeRef);
- if (arrayType != NULL)
- {
- arrayCreateExpr->mTypeRef = arrayType;
- auto nextNode = mVisitorPos.GetNext();
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- mVisitorPos.MoveNext();
- auto initializerExpr = CreateCollectionInitializerExpression(nextToken);
- MEMBER_SET(arrayCreateExpr, mInitializer, initializerExpr);
- }
- exprLeft = arrayCreateExpr;
- }
- else
- {
- Fail("Sized array type expected", typeRef);
- AddErrorNode(typeRef);
- return NULL;
- }
- }
- }
- }
- }
- }
- else if (endNodeIdx != -1)
- {
- if (auto blockNode = BfNodeDynCast<BfBlock>(mVisitorPos.Get(endNodeIdx)))
- {
- auto typeRef = CreateTypeRef(mVisitorPos.GetCurrent());
- if (typeRef)
- {
- exprLeft = TryCreateInitializerExpression(typeRef);
- }
- }
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(endNodeIdx)))
- {
- if (tokenNode->mToken == BfToken_LParen)
- {
- int openCount = 1;
- int checkIdx = endNodeIdx + 1;
- while (true)
- {
- auto checkNode = mVisitorPos.Get(checkIdx);
- if (checkNode == NULL)
- break;
- if (auto checkTokenNode = BfNodeDynCast<BfTokenNode>(checkNode))
- {
- if (checkTokenNode->mToken == BfToken_LParen)
- openCount++;
- if (checkTokenNode->mToken == BfToken_RParen)
- {
- openCount--;
- if (openCount == 0)
- break;
- }
- }
- checkIdx++;
- }
- if (auto blockNode = BfNodeDynCast<BfBlock>(mVisitorPos.Get(checkIdx + 1)))
- {
- // If we have 'A() { ... }', that can either be an invocation with an initializer block or a
- // create expression with an inline type declaration + initializer block
- if (InitializerBlockHasInlineTypeDecl(blockNode))
- {
- exprLeft = CreateObjectCreateExpression(NULL, exprLeft);
- if (auto initExpr = TryCreateInitializerExpression(exprLeft))
- exprLeft = initExpr;
- }
- }
- }
- }
- }
- }
- if (exprLeft == NULL)
- {
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(node))
- {
- BfAstNode* notNode = NULL;
- if (tokenNode->mToken == BfToken_Not)
- {
- auto nextNode = mVisitorPos.GetNext();
- if (auto nextTokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (nextTokenNode->mToken == BfToken_Case)
- {
- mVisitorPos.MoveNext();
- notNode = tokenNode;
- node = nextNode;
- tokenNode = nextTokenNode;
- }
- }
- }
- BfToken token = tokenNode->GetToken();
- auto nextNode = mVisitorPos.GetNext();
- if ((nextNode != NULL) &&
- ((token == BfToken_Checked) ||
- (token == BfToken_Unchecked)))
- {
- mVisitorPos.MoveNext();
- auto nextExpr = CreateExpression(nextNode);
- if (nextExpr == NULL)
- return NULL;
- return nextExpr;
- }
- else if ((token == BfToken_New) ||
- (token == BfToken_Scope) ||
- (token == BfToken_Append))
- {
- auto allocNode = CreateAllocNode(tokenNode);
- bool isDelegateBind = false;
- bool isLambdaBind = false;
- bool isBoxing = false;
- auto nextNode = mVisitorPos.GetNext();
- if (auto nextTokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- int nextToken = nextTokenNode->GetToken();
- isBoxing = nextToken == BfToken_Box;
- isDelegateBind = nextToken == BfToken_FatArrow;
- isLambdaBind = (nextToken == BfToken_LBracket);
- // Either this is a lambda bind or a dynamic tuple allocation.
- // We assume it's a lambda bind unless theres a "()" afterward
- if (nextToken == BfToken_LParen)
- {
- int endNode = -1;
- mVisitorPos.mReadPos++;
- if (!IsTypeReference(nextTokenNode, BfToken_LParen, -1, &endNode))
- {
- isLambdaBind = true;
- }
- mVisitorPos.mReadPos--;
- }
- }
- if (auto interpExpr = BfNodeDynCastExact<BfStringInterpolationExpression>(nextNode))
- {
- mVisitorPos.MoveNext();
- auto nextInterpExpr = CreateExpression(nextNode);
- BF_ASSERT(nextInterpExpr == interpExpr);
- interpExpr->mAllocNode = allocNode;
- interpExpr->mTriviaStart = allocNode->mTriviaStart;
- interpExpr->mSrcStart = allocNode->mSrcStart;
- exprLeft = interpExpr;
- }
- else if (isBoxing)
- {
- auto boxExpr = mAlloc->Alloc<BfBoxExpression>();
- ReplaceNode(allocNode, boxExpr);
- boxExpr->mAllocNode = allocNode;
- tokenNode = ExpectTokenAfter(boxExpr, BfToken_Box);
- MEMBER_SET(boxExpr, mBoxToken, tokenNode);
- auto exprNode = CreateExpressionAfter(boxExpr);
- if (exprNode != NULL)
- {
- MEMBER_SET(boxExpr, mExpression, exprNode);
- }
- return boxExpr;
- }
- else if (isLambdaBind)
- exprLeft = CreateLambdaBindExpression(allocNode);
- else if (isDelegateBind)
- exprLeft = CreateDelegateBindExpression(allocNode);
- else
- {
- exprLeft = CreateObjectCreateExpression(allocNode);
- if (auto initExpr = TryCreateInitializerExpression(exprLeft))
- exprLeft = initExpr;
- }
- if (token == BfToken_Append)
- {
- #ifdef BF_AST_HAS_PARENT_MEMBER
- auto ctorDeclP = exprLeft->FindParentOfType<BfConstructorDeclaration>();
- if (ctorDeclP != NULL)
- ctorDeclP->mHasAppend = true;
- #endif
- #ifdef BF_AST_HAS_PARENT_MEMBER
- BF_ASSERT(ctorDecl == ctorDeclP);
- #endif
- }
- }
- else if (token == BfToken_This)
- {
- auto thisExpr = mAlloc->Alloc<BfThisExpression>();
- ReplaceNode(tokenNode, thisExpr);
- thisExpr->SetTriviaStart(tokenNode->GetTriviaStart());
- exprLeft = thisExpr;
- }
- else if (token == BfToken_Base)
- {
- auto baseExpr = mAlloc->Alloc<BfBaseExpression>();
- ReplaceNode(tokenNode, baseExpr);
- baseExpr->SetTriviaStart(tokenNode->GetTriviaStart());
- exprLeft = baseExpr;
- }
- else if (token == BfToken_Null)
- {
- BfVariant nullVariant;
- nullVariant.mTypeCode = BfTypeCode_NullPtr;
- auto bfLiteralExpression = mAlloc->Alloc<BfLiteralExpression>();
- bfLiteralExpression->mValue = nullVariant;
- ReplaceNode(tokenNode, bfLiteralExpression);
- bfLiteralExpression->SetTriviaStart(tokenNode->GetTriviaStart());
- exprLeft = bfLiteralExpression;
- }
- else if ((token == BfToken_TypeOf) || (token == BfToken_SizeOf) ||
- (token == BfToken_AlignOf) || (token == BfToken_StrideOf))
- {
- BfTypeAttrExpression* typeAttrExpr = NULL;
- switch (tokenNode->GetToken())
- {
- case BfToken_TypeOf:
- typeAttrExpr = mAlloc->Alloc<BfTypeOfExpression>();
- break;
- case BfToken_SizeOf:
- typeAttrExpr = mAlloc->Alloc<BfSizeOfExpression>();
- break;
- case BfToken_AlignOf:
- typeAttrExpr = mAlloc->Alloc<BfAlignOfExpression>();
- break;
- case BfToken_StrideOf:
- typeAttrExpr = mAlloc->Alloc<BfStrideOfExpression>();
- break;
- default: break;
- }
- ReplaceNode(tokenNode, typeAttrExpr);
- typeAttrExpr->mToken = tokenNode;
- tokenNode = ExpectTokenAfter(typeAttrExpr, BfToken_LParen);
- MEMBER_SET_CHECKED(typeAttrExpr, mOpenParen, tokenNode);
- auto typeRef = CreateTypeRefAfter(typeAttrExpr);
- MEMBER_SET_CHECKED(typeAttrExpr, mTypeRef, typeRef);
- tokenNode = ExpectTokenAfter(typeAttrExpr, BfToken_RParen);
- MEMBER_SET_CHECKED(typeAttrExpr, mCloseParen, tokenNode);
- exprLeft = typeAttrExpr;
- }
- else if (token == BfToken_OffsetOf)
- {
- BfOffsetOfExpression* typeAttrExpr = mAlloc->Alloc<BfOffsetOfExpression>();
- ReplaceNode(tokenNode, typeAttrExpr);
- typeAttrExpr->mToken = tokenNode;
- tokenNode = ExpectTokenAfter(typeAttrExpr, BfToken_LParen);
- MEMBER_SET_CHECKED(typeAttrExpr, mOpenParen, tokenNode);
- auto typeRef = CreateTypeRefAfter(typeAttrExpr);
- MEMBER_SET_CHECKED(typeAttrExpr, mTypeRef, typeRef);
- tokenNode = ExpectTokenAfter(typeAttrExpr, BfToken_Comma);
- MEMBER_SET_CHECKED(typeAttrExpr, mCommaToken, tokenNode);
- auto nameNode = ExpectIdentifierAfter(typeAttrExpr);
- MEMBER_SET_CHECKED(typeAttrExpr, mMemberName, nameNode);
- tokenNode = ExpectTokenAfter(typeAttrExpr, BfToken_RParen);
- MEMBER_SET_CHECKED(typeAttrExpr, mCloseParen, tokenNode);
- exprLeft = typeAttrExpr;
- }
- else if (token == BfToken_Default)
- {
- auto defaultExpr = mAlloc->Alloc<BfDefaultExpression>();
- ReplaceNode(tokenNode, defaultExpr);
- defaultExpr->mDefaultToken = tokenNode;
- if ((tokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext())) && (tokenNode->GetToken() == BfToken_LParen))
- {
- mVisitorPos.MoveNext();
- //tokenNode = ExpectTokenAfter(defaultExpr, BfToken_LParen);
- MEMBER_SET_CHECKED(defaultExpr, mOpenParen, tokenNode);
- auto sizeRef = CreateTypeRefAfter(defaultExpr);
- MEMBER_SET_CHECKED(defaultExpr, mTypeRef, sizeRef);
- tokenNode = ExpectTokenAfter(defaultExpr, BfToken_RParen);
- MEMBER_SET_CHECKED(defaultExpr, mCloseParen, tokenNode);
- }
- exprLeft = defaultExpr;
- }
- else if (token == BfToken_IsConst)
- {
- auto isConstExpr = mAlloc->Alloc<BfIsConstExpression>();
- ReplaceNode(tokenNode, isConstExpr);
- isConstExpr->mIsConstToken = tokenNode;
- tokenNode = ExpectTokenAfter(isConstExpr, BfToken_LParen);
- MEMBER_SET_CHECKED(isConstExpr, mOpenParen, tokenNode);
- auto expr = CreateExpressionAfter(isConstExpr);
- MEMBER_SET_CHECKED(isConstExpr, mExpression, expr);
- tokenNode = ExpectTokenAfter(isConstExpr, BfToken_RParen);
- MEMBER_SET_CHECKED(isConstExpr, mCloseParen, tokenNode);
- exprLeft = isConstExpr;
- }
- else if (token == BfToken_Question)
- {
- auto uninitExpr = mAlloc->Alloc<BfUninitializedExpression>();
- ReplaceNode(tokenNode, uninitExpr);
- uninitExpr->mQuestionToken = tokenNode;
- return uninitExpr;
- //MEMBER_SET(variableDeclaration, mInitializer, uninitExpr);
- }
- else if (token == BfToken_Case)
- {
- auto caseExpr = mAlloc->Alloc<BfCaseExpression>();
-
- if (notNode != NULL)
- {
- ReplaceNode(notNode, caseExpr);
- caseExpr->mNotToken = notNode;
- MEMBER_SET(caseExpr, mCaseToken, tokenNode);
- }
- else
- {
- ReplaceNode(tokenNode, caseExpr);
- caseExpr->mCaseToken = tokenNode;
- }
- if (auto bindToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if ((bindToken->GetToken() == BfToken_Var) || (bindToken->GetToken() == BfToken_Let))
- {
- auto expr = CreateEnumCaseBindExpression(bindToken);
- if (expr == NULL)
- return caseExpr;
- MEMBER_SET(caseExpr, mCaseExpression, expr);
- }
- }
- if (caseExpr->mCaseExpression == NULL)
- {
- auto expr = CreateExpressionAfter(caseExpr, (CreateExprFlags)(CreateExprFlags_NoAssignment | CreateExprFlags_PermissiveVariableDecl));
- if (expr == NULL)
- return caseExpr;
- MEMBER_SET(caseExpr, mCaseExpression, expr);
- }
- auto equalsNode = ExpectTokenAfter(caseExpr, BfToken_AssignEquals);
- if (equalsNode == NULL)
- return caseExpr;
- MEMBER_SET(caseExpr, mEqualsNode, equalsNode);
- auto expr = CreateExpressionAfter(caseExpr);
- if (expr == NULL)
- return caseExpr;
- MEMBER_SET(caseExpr, mValueExpression, expr);
- return caseExpr;
- }
- else if (token == BfToken_Dot) // Abbreviated dot syntax ".EnumVal"
- {
- bool handled = false;
- if (auto nextTokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if (nextTokenNode->mToken == BfToken_This)
- {
- auto invocationExpr = CreateObjectCreateExpression(NULL, tokenNode);
- if (invocationExpr == NULL)
- return exprLeft;
- exprLeft = invocationExpr;
- handled = true;
- }
- }
- if (auto blockNode = BfNodeDynCast<BfBlock>(mVisitorPos.GetNext()))
- {
- // Initializer ".{ x = 1, y = 2 }"
- auto typeRef = CreateTypeRef(mVisitorPos.GetCurrent());
- if (typeRef)
- {
- exprLeft = TryCreateInitializerExpression(typeRef);
- }
- }
- else if (!handled)
- {
- auto memberReferenceExpr = mAlloc->Alloc<BfMemberReferenceExpression>();
- ReplaceNode(tokenNode, memberReferenceExpr);
- MEMBER_SET(memberReferenceExpr, mDotToken, tokenNode);
- bool handled = false;
- if (auto nextToken = BfNodeDynCastExact<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if (nextToken->GetToken() == BfToken_LParen)
- {
- // It's an unnamed dot ctor
- handled = true;
- }
- }
- if (!handled)
- {
- auto memberName = ExpectIdentifierAfter(memberReferenceExpr);
- if (memberName != NULL)
- {
- MEMBER_SET(memberReferenceExpr, mMemberName, memberName);
- }
- }
- // We don't set exprLeft here because it's illegal to do ".EnumVal.SomethingElse". That wouldn't make
- // sense because the abbreviated syntax relies on type inference and the ".SomethingElse" wouldn't be
- // the right type (whatever it is), AND mostly importantly, it breaks autocomplete when we are typing
- // "KEnum val = ." above a line that starts with a something like a method call "OtherThing.MethodCall()"
- // The exception is if we're creating an enum val with a payload
- //auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
- //if ((nextToken != NULL) && (nextToken->GetToken() == BfToken_LParen))
- {
- exprLeft = memberReferenceExpr;
- }
- /*else
- {
- return memberReferenceExpr;
- }*/
- }
- }
- else if (token == BfToken_LBracket)
- {
- if ((createExprFlags & CreateExprFlags_AllowAnonymousIndexer) != 0)
- {
- exprLeft = CreateIndexerExpression(NULL, tokenNode);
- }
- else
- exprLeft = CreateAttributedExpression(tokenNode, false);
- }
- else if (token == BfToken_FatArrow)
- {
- auto delegateBindExpr = mAlloc->Alloc<BfDelegateBindExpression>();
- ReplaceNode(tokenNode, delegateBindExpr);
- MEMBER_SET_CHECKED(delegateBindExpr, mFatArrowToken, tokenNode);
- auto expr = CreateExpressionAfter(delegateBindExpr);
- MEMBER_SET_CHECKED(delegateBindExpr, mTarget, expr);
- auto nextNode = mVisitorPos.GetNext();
- if ((tokenNode = BfNodeDynCast<BfTokenNode>(nextNode)))
- {
- if (tokenNode->GetToken() == BfToken_LChevron)
- {
- mVisitorPos.MoveNext();
- auto genericParamsDecl = CreateGenericArguments(tokenNode);
- MEMBER_SET_CHECKED(delegateBindExpr, mGenericArgs, genericParamsDecl);
- }
- }
- return delegateBindExpr;
- }
- }
- }
- if (exprLeft == NULL)
- {
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(node))
- {
- BfUnaryOperatorExpression* unaryOpExpr = NULL;
- auto nextNode = mVisitorPos.GetNext();
- if ((tokenNode->GetToken() == BfToken_LParen) && (nextNode != NULL))
- {
- bool couldBeExpr = true;
- // Peek ahead
- int endNodeIdx = -1;
- BfAstNode* endNode = NULL;
- bool isTuple = false;
- bool outerIsTypeRef = IsTypeReference(tokenNode, BfToken_FatArrow, -1, &endNodeIdx, &couldBeExpr, NULL, &isTuple);
- if (outerIsTypeRef)
- {
- if (endNodeIdx != -1)
- {
- endNode = mVisitorPos.Get(endNodeIdx);
- if (auto endToken = BfNodeDynCast<BfTokenNode>(endNode))
- {
- bool isLambda = false;
- if (endToken->GetToken() == BfToken_FatArrow)
- {
- isLambda = true;
- if (auto innerToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if (innerToken->mToken != BfToken_RParen)
- {
- // Specifically we're looking for a (function ...) cast, but any token besides a close here means it's not a lambda
- isLambda = false;
- }
- }
- }
- if (isLambda)
- return CreateLambdaBindExpression(NULL, tokenNode);
- }
- }
- }
- bool isCastExpr = false;
- couldBeExpr = false;
- isTuple = false;
- if ((createExprFlags & CreateExprFlags_NoCast) == 0)
- isCastExpr = IsTypeReference(node, BfToken_RParen, -1, &endNodeIdx, &couldBeExpr, NULL, &isTuple);
- if (endNodeIdx != -1)
- endNode = mVisitorPos.Get(endNodeIdx);
- if (isCastExpr)
- {
- bool isValidTupleCast = false;
- auto tokenNextNode = mVisitorPos.Get(mVisitorPos.mReadPos + 1);
- if (auto startToken = BfNodeDynCast<BfTokenNode>(tokenNextNode))
- {
- if (startToken->GetToken() == BfToken_LParen)
- {
- if (endNode != NULL)
- {
- auto afterEndNode = mVisitorPos.Get(endNodeIdx + 1);
- if (auto afterEndToken = BfNodeDynCast<BfTokenNode>(afterEndNode))
- {
- if (afterEndToken->GetToken() == BfToken_RParen)
- {
- isValidTupleCast = true;
- endNode = afterEndToken; // Check this one now, instead...
- }
- }
- }
- if (!isValidTupleCast)
- isCastExpr = false;
- }
- }
- BfAstNode* beforeEndNode = mVisitorPos.Get(endNodeIdx - 1);
- if (auto prevTokenNode = BfNodeDynCast<BfTokenNode>(beforeEndNode))
- {
- int prevToken = prevTokenNode->GetToken();
- // Ending in a "*" or a ">" means it's definitely a type reference
- if ((prevToken == BfToken_Star) || (prevToken == BfToken_RChevron) || (prevToken == BfToken_RDblChevron))
- couldBeExpr = false;
- }
- // It's not a cast expression if a binary operator (like +) immediately follows
- if (couldBeExpr)
- {
- auto endNextNode = mVisitorPos.Get(endNodeIdx + 1);
- if (endNextNode == NULL)
- {
- isCastExpr = false;
- }
- else if (auto nextTokenNode = BfNodeDynCast<BfTokenNode>(endNextNode))
- {
- BfToken nextToken = nextTokenNode->GetToken();
- //TODO: Hm. What other tokens make it into a cast expr?
- auto binaryOp = BfTokenToBinaryOp(nextToken);
- // When we have a binary operator token following, it COULD either be a "(double)-val" or it COULD be a "(val2)-val"
- // But we can't tell until we determine whether the thing inside the paren is a type name or a value name, so we
- // have special code in BfExprEvaluator that can fix those cases at evaluation time
- if (((binaryOp != BfBinaryOp_None) /*&& (nextToken != BfToken_Star) && (nextToken != BfToken_Ampersand)*/) || // Star could be dereference, not multiply
- (nextToken == BfToken_RParen) ||
- (nextToken == BfToken_LBracket) ||
- (nextToken == BfToken_Dot) ||
- (nextToken == BfToken_DotDot) ||
- (nextToken == BfToken_Comma) ||
- (nextToken == BfToken_Colon) ||
- (nextToken == BfToken_Question) ||
- (nextToken == BfToken_Semicolon) ||
- (nextToken == BfToken_AssignEquals) ||
- (nextToken == BfToken_Case))
- isCastExpr = false;
- }
- }
- }
- if (isCastExpr)
- {
- BfCastExpression* bfCastExpr = NULL;
- if (isTuple)
- {
- // Create typeRef including the parens (tuple type)
- auto castTypeRef = CreateTypeRef(tokenNode);
- if (castTypeRef != NULL)
- {
- bfCastExpr = mAlloc->Alloc<BfCastExpression>();
- ReplaceNode(castTypeRef, bfCastExpr);
- bfCastExpr->mTypeRef = castTypeRef;
- }
- }
- else
- {
- auto castTypeRef = CreateTypeRefAfter(tokenNode);
- if (castTypeRef != NULL)
- {
- bfCastExpr = mAlloc->Alloc<BfCastExpression>();
- ReplaceNode(tokenNode, bfCastExpr);
- bfCastExpr->mOpenParen = tokenNode;
- MEMBER_SET_CHECKED(bfCastExpr, mTypeRef, castTypeRef);
- tokenNode = ExpectTokenAfter(bfCastExpr, BfToken_RParen);
- MEMBER_SET_CHECKED(bfCastExpr, mCloseParen, tokenNode);
- }
- }
- if (bfCastExpr == NULL)
- isCastExpr = false;
- else
- {
- auto expression = CreateExpressionAfter(bfCastExpr);
- if (expression == NULL)
- return bfCastExpr;
- MEMBER_SET(bfCastExpr, mExpression, expression);
- unaryOpExpr = bfCastExpr;
- }
- }
- if (!isCastExpr)
- {
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- // Empty tuple?
- if (nextToken->GetToken() == BfToken_RParen)
- {
- auto tupleExpr = mAlloc->Alloc<BfTupleExpression>();
- ReplaceNode(tokenNode, tupleExpr);
- tupleExpr->mOpenParen = tokenNode;
- MEMBER_SET(tupleExpr, mCloseParen, nextToken);
- mVisitorPos.MoveNext();
- return tupleExpr;
- }
- }
- // static int sItrIdx = 0;
- // sItrIdx++;
- // int itrIdx = sItrIdx;
- // if (itrIdx == 197)
- // {
- // NOP;
- // }
- // BfParenthesizedExpression or BfTupleExpression
- SetAndRestoreValue<bool> prevInParenExpr(mInParenExpr, true);
- auto innerExpr = CreateExpressionAfter(tokenNode, CreateExprFlags_AllowVariableDecl);
- if (innerExpr == NULL)
- return NULL;
- BfTokenNode* closeParenToken;
- if (innerExpr->IsA<BfIdentifierNode>())
- closeParenToken = ExpectTokenAfter(innerExpr, BfToken_RParen, BfToken_Comma, BfToken_Colon);
- else
- closeParenToken = ExpectTokenAfter(innerExpr, BfToken_RParen, BfToken_Comma);
- if ((closeParenToken == NULL) || (closeParenToken->GetToken() == BfToken_RParen))
- {
- auto parenExpr = mAlloc->Alloc<BfParenthesizedExpression>();
- parenExpr->mExpression = innerExpr;
- ReplaceNode(node, parenExpr);
- parenExpr->mOpenParen = tokenNode;
- MoveNode(innerExpr, parenExpr);
- if (closeParenToken == NULL)
- return parenExpr;
- MEMBER_SET(parenExpr, mCloseParen, closeParenToken);
- exprLeft = parenExpr;
- if ((createExprFlags & CreateExprFlags_ExitOnParenExpr) != 0)
- return exprLeft;
- }
- else
- {
- mVisitorPos.mReadPos--; // Backtrack to before token
- exprLeft = CreateTupleExpression(tokenNode, innerExpr);
- }
- }
- }
- else if ((tokenNode->GetToken() == BfToken_Comptype) || (tokenNode->GetToken() == BfToken_Decltype))
- {
- auto typeRef = CreateTypeRef(tokenNode, CreateTypeRefFlags_EarlyExit);
- if (typeRef != NULL)
- {
- exprLeft = CreateMemberReferenceExpression(typeRef);
- }
- }
- else if (tokenNode->GetToken() == BfToken_NameOf)
- {
- BfNameOfExpression* nameOfExpr = mAlloc->Alloc<BfNameOfExpression>();
- ReplaceNode(tokenNode, nameOfExpr);
- nameOfExpr->mToken = tokenNode;
- tokenNode = ExpectTokenAfter(nameOfExpr, BfToken_LParen);
- MEMBER_SET_CHECKED(nameOfExpr, mOpenParen, tokenNode);
- mVisitorPos.MoveNext();
- int outEndNode = -1;
- bool isTypeRef = IsTypeReference(mVisitorPos.GetCurrent(), BfToken_RParen, -1, &outEndNode);
- mVisitorPos.mReadPos--;
- if ((isTypeRef) && (outEndNode > 0))
- {
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(outEndNode - 1)))
- {
- if ((tokenNode->mToken == BfToken_RChevron) || (tokenNode->mToken == BfToken_RDblChevron))
- {
- // Can ONLY be a type reference
- auto typeRef = CreateTypeRefAfter(nameOfExpr);
- MEMBER_SET_CHECKED(nameOfExpr, mTarget, typeRef);
- }
- }
- }
- if (nameOfExpr->mTarget == NULL)
- {
- auto expr = CreateExpressionAfter(nameOfExpr);
- MEMBER_SET_CHECKED(nameOfExpr, mTarget, expr);
- }
- tokenNode = ExpectTokenAfter(nameOfExpr, BfToken_RParen);
- MEMBER_SET_CHECKED(nameOfExpr, mCloseParen, tokenNode);
- exprLeft = nameOfExpr;
- }
- if (exprLeft == NULL)
- {
- BfUnaryOp unaryOp = BfTokenToUnaryOp(tokenNode->GetToken());
- if (unaryOp != BfUnaryOp_None)
- {
- unaryOpExpr = mAlloc->Alloc<BfUnaryOperatorExpression>();
- unaryOpExpr->mOp = unaryOp;
- unaryOpExpr->mOpToken = tokenNode;
- ReplaceNode(tokenNode, unaryOpExpr);
- CreateExprFlags innerFlags = (CreateExprFlags)(rhsCreateExprFlags | CreateExprFlags_EarlyExit);
- if (unaryOp == BfUnaryOp_Cascade)
- innerFlags = (CreateExprFlags)(innerFlags | (createExprFlags & CreateExprFlags_AllowVariableDecl));
- if (unaryOp == BfUnaryOp_PartialRangeThrough) // This allows for just a naked '...'
- innerFlags = (CreateExprFlags)(innerFlags | CreateExprFlags_AllowEmpty);
- // Don't attempt binary or unary operations- they will always be lower precedence
- unaryOpExpr->mExpression = CreateExpressionAfter(unaryOpExpr, innerFlags);
- if (unaryOpExpr->mExpression == NULL)
- return unaryOpExpr;
- MoveNode(unaryOpExpr->mExpression, unaryOpExpr);
- }
- if (unaryOpExpr != NULL)
- {
- exprLeft = unaryOpExpr;
- if (auto binaryOpExpr = BfNodeDynCast<BfBinaryOperatorExpression>(unaryOpExpr->mExpression))
- {
- exprLeft = binaryOpExpr;
- ApplyToFirstExpression(unaryOpExpr, binaryOpExpr);
- }
- if (auto condExpr = BfNodeDynCast<BfConditionalExpression>(unaryOpExpr->mExpression))
- {
- if (exprLeft == unaryOpExpr)
- exprLeft = condExpr;
- ApplyToFirstExpression(unaryOpExpr, condExpr);
- }
- if (auto assignmentExpr = BfNodeDynCast<BfAssignmentExpression>(unaryOpExpr->mExpression))
- {
- // Apply unary operator (likely a dereference) to LHS
- assignmentExpr->RemoveSelf();
- ReplaceNode(unaryOpExpr, assignmentExpr);
- if (assignmentExpr->mLeft != NULL)
- {
- MEMBER_SET(unaryOpExpr, mExpression, assignmentExpr->mLeft);
- unaryOpExpr->SetSrcEnd(assignmentExpr->mLeft->GetSrcEnd());
- MEMBER_SET(assignmentExpr, mLeft, unaryOpExpr);
- if (exprLeft == unaryOpExpr)
- exprLeft = assignmentExpr;
- }
- }
- if (auto dynCastExpr = BfNodeDynCast<BfDynamicCastExpression>(unaryOpExpr->mExpression))
- {
- // Apply unary operator (likely a dereference) to Expr
- dynCastExpr->RemoveSelf();
- ReplaceNode(unaryOpExpr, dynCastExpr);
- if (dynCastExpr->mTarget != NULL)
- {
- MEMBER_SET(unaryOpExpr, mExpression, dynCastExpr->mTarget);
- unaryOpExpr->SetSrcEnd(dynCastExpr->mTarget->GetSrcEnd());
- MEMBER_SET(dynCastExpr, mTarget, unaryOpExpr);
- if (exprLeft == unaryOpExpr)
- exprLeft = dynCastExpr;
- }
- }
- if (auto caseExpr = BfNodeDynCast<BfCaseExpression>(unaryOpExpr->mExpression))
- {
- // Apply unary operator (likely a dereference) to Expr
- caseExpr->RemoveSelf();
- ReplaceNode(unaryOpExpr, caseExpr);
- if (caseExpr->mValueExpression != NULL)
- {
- MEMBER_SET(unaryOpExpr, mExpression, caseExpr->mValueExpression);
- unaryOpExpr->SetSrcEnd(caseExpr->mValueExpression->GetSrcEnd());
- MEMBER_SET(caseExpr, mValueExpression, unaryOpExpr);
- if (exprLeft == unaryOpExpr)
- exprLeft = caseExpr;
- }
- }
- }
- }
- }
- }
- if (exprLeft == NULL)
- {
- if ((createExprFlags & CreateExprFlags_AllowEmpty) == 0)
- Fail("Expected expression", node);
- return NULL;
- }
- while (true)
- {
- auto nextNode = mVisitorPos.GetNext();
- if (nextNode == NULL)
- break;
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- BfToken token = tokenNode->GetToken();
- if (((createExprFlags & CreateExprFlags_BreakOnRChevron) != 0) &&
- ((token == BfToken_RChevron) || (token == BfToken_RDblChevron)))
- return exprLeft;
- BfUnaryOp postUnaryOp = BfUnaryOp_None;
- if (token == BfToken_DblPlus)
- postUnaryOp = BfUnaryOp_PostIncrement;
- if (token == BfToken_DblMinus)
- postUnaryOp = BfUnaryOp_PostDecrement;
- if (token == BfToken_DotDotDot)
- {
- //TODO: Detect if this is a BfUnaryOp_PartialRangeFrom
- }
- if (postUnaryOp != BfUnaryOp_None)
- {
- auto unaryOpExpr = mAlloc->Alloc<BfUnaryOperatorExpression>();
- ReplaceNode(exprLeft, unaryOpExpr);
- unaryOpExpr->mOp = postUnaryOp;
- MEMBER_SET(unaryOpExpr, mOpToken, tokenNode);
- MEMBER_SET(unaryOpExpr, mExpression, exprLeft);
- exprLeft = unaryOpExpr;
- mVisitorPos.MoveNext();
- continue;
- }
- if (token == BfToken_As)
- {
- auto dynCastExpr = mAlloc->Alloc<BfDynamicCastExpression>();
- ReplaceNode(exprLeft, dynCastExpr);
- dynCastExpr->mTarget = exprLeft;
- MEMBER_SET(dynCastExpr, mAsToken, tokenNode);
- mVisitorPos.MoveNext();
- auto typeRef = CreateTypeRefAfter(dynCastExpr);
- if (typeRef == NULL)
- return dynCastExpr;
- MEMBER_SET(dynCastExpr, mTypeRef, typeRef);
- return dynCastExpr;
- }
- if (token == BfToken_Is)
- {
- auto checkTypeExpr = mAlloc->Alloc<BfCheckTypeExpression>();
- ReplaceNode(exprLeft, checkTypeExpr);
- checkTypeExpr->mTarget = exprLeft;
- MEMBER_SET(checkTypeExpr, mIsToken, tokenNode);
- mVisitorPos.MoveNext();
- auto typeRef = CreateTypeRefAfter(checkTypeExpr);
- if (typeRef == NULL)
- return checkTypeExpr;
- MEMBER_SET(checkTypeExpr, mTypeRef, typeRef);
- exprLeft = checkTypeExpr;
- continue;
- }
- if (token == BfToken_Question)
- {
- if ((createExprFlags & CreateExprFlags_EarlyExit) != 0)
- return exprLeft;
- auto conditionExpr = mAlloc->Alloc<BfConditionalExpression>();
- ReplaceNode(exprLeft, conditionExpr);
- conditionExpr->mConditionExpression = exprLeft;
- MEMBER_SET(conditionExpr, mQuestionToken, tokenNode);
- mVisitorPos.MoveNext();
- auto expr = CreateExpressionAfter(conditionExpr);
- if (expr != NULL)
- {
- MEMBER_SET(conditionExpr, mTrueExpression, expr);
- tokenNode = ExpectTokenAfter(conditionExpr, BfToken_Colon);
- if (tokenNode != NULL)
- {
- MEMBER_SET(conditionExpr, mColonToken, tokenNode);
- expr = CreateExpressionAfter(conditionExpr);
- if (expr != NULL)
- {
- MEMBER_SET(conditionExpr, mFalseExpression, expr);
- }
- }
- }
- exprLeft = conditionExpr;
- continue;
- }
- if (((token == BfToken_Case) || (token == BfToken_Not))
- && ((createExprFlags & CreateStmtFlags_NoCaseExpr) == 0))
- {
- if ((createExprFlags & CreateExprFlags_EarlyExit) != 0)
- return exprLeft;
- // If we have a ".Member case <XXX>" expression, that is an invalid construct. We bail out here
- // because it allows the ".Member" to autocomplete because we will treat it as a full expression instead
- // of making it the target of an illegal expression
- if (auto memberRefLeft = BfNodeDynCast<BfMemberReferenceExpression>(exprLeft))
- {
- if (memberRefLeft->mTarget == NULL)
- return exprLeft;
- }
- auto caseExpr = mAlloc->Alloc<BfCaseExpression>();
- ReplaceNode(exprLeft, caseExpr);
- caseExpr->mValueExpression = exprLeft;
- if (token == BfToken_Not)
- {
- MEMBER_SET(caseExpr, mNotToken, tokenNode);
- mVisitorPos.MoveNext();
- tokenNode = ExpectTokenAfter(caseExpr, BfToken_Case);
- MEMBER_SET(caseExpr, mCaseToken, tokenNode);
- }
- else
- {
- MEMBER_SET(caseExpr, mCaseToken, tokenNode);
- mVisitorPos.MoveNext();
- }
-
- exprLeft = caseExpr;
- if (auto bindTokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- BfToken bindToken = bindTokenNode->GetToken();
- if ((bindToken == BfToken_Var) || (bindToken == BfToken_Let))
- {
- auto expr = CreateEnumCaseBindExpression(bindTokenNode);
- if (expr == NULL)
- continue;
- MEMBER_SET(caseExpr, mCaseExpression, expr);
- }
- }
- if (caseExpr->mCaseExpression == NULL)
- {
- auto expr = CreateExpressionAfter(caseExpr, (CreateExprFlags)(CreateExprFlags_NoAssignment | CreateExprFlags_PermissiveVariableDecl | CreateExprFlags_EarlyExit));
- if (expr == NULL)
- continue;
- MEMBER_SET(caseExpr, mCaseExpression, expr);
- }
- continue;
- }
- if (token == BfToken_LChevron)
- {
- bool hadEndingToken = false;
- // If this is a complex member reference (IE: GType<int>.sVal) then condense in into a BfMemberReference.
- // We need to be conservative about typeRef names, so GType<int>.A<T>.B.C.D, we can only assume "GType<int>.A<T>" is a typeref
- // and the ".B.C.D" part is exposed as a MemberReference that may or may not include inner types
- int outNodeIdx = -1;
- bool isGenericType = false;
- bool isTypeRef = ((IsTypeReference(exprLeft, BfToken_None, -1, &outNodeIdx, NULL, &isGenericType)) &&
- (outNodeIdx != -1));
- BfAstNode* outNode = mVisitorPos.Get(outNodeIdx);
- if ((!isTypeRef) && (outNodeIdx != -1))
- {
- if ((isGenericType) && (outNode == NULL))
- {
- for (int checkOutNodeIdx = outNodeIdx + 1; true; checkOutNodeIdx++)
- {
- BfAstNode* checkNode = mVisitorPos.Get(checkOutNodeIdx);
- if (checkNode == NULL)
- break;
- outNode = checkNode;
- }
- isTypeRef = true;
- }
- else if (auto outTokenNode = BfNodeDynCast<BfTokenNode>(outNode))
- {
- BfToken outToken = outTokenNode->GetToken();
- if ((outToken == BfToken_Semicolon) || (outToken == BfToken_RParen) || (outToken == BfToken_Comma) ||
- (outToken == BfToken_Let) || (outToken == BfToken_Var) || (outToken == BfToken_Const))
- {
- auto prevNode = mVisitorPos.Get(outNodeIdx - 1);
- if (auto prevToken = BfNodeDynCast<BfTokenNode>(prevNode))
- {
- // This handles such as "dlg = stack => obj.method<int>;"
- if ((prevToken->GetToken() == BfToken_RChevron) || (prevToken->GetToken() == BfToken_RDblChevron))
- hadEndingToken = true;
- }
- }
- //TODO: We had BfToken_Semicolon here, but it broke legitimate cases of "a.b.c < d.e.f;" expressions
- //if ((outToken == BfToken_Semicolon) || (isGenericType) || (outToken == BfToken_LParen) || (outToken == BfToken_Var) || (outToken == BfToken_Const))
- {
- // Was just 'true'
- int newOutNodeIdx = -1;
- //bool newIsTypeRef = IsTypeReference(exprLeft, outToken, -1, &newOutNodeIdx, NULL, &isGenericType);
- bool newIsTypeRef = IsTypeReference(exprLeft, BfToken_None, outNodeIdx, &newOutNodeIdx, NULL, &isGenericType);
- BfAstNode* newOutNode = mVisitorPos.Get(newOutNodeIdx);
- if ((newIsTypeRef) && (newOutNode == outNode) && (isGenericType))
- isTypeRef = true;
- }
- }
- }
- if (isTypeRef)
- {
- auto startIdentifier = exprLeft;
- int curNodeEndIdx = outNodeIdx - 1;
- BfAstNode* curNodeEnd = mVisitorPos.Get(curNodeEndIdx);
- bool isDotName = false;
- if (auto qualifiedIdentifierNode = BfNodeDynCast<BfMemberReferenceExpression>(startIdentifier))
- {
- // Don't try to convert dot-name to a qualified type
- isDotName = qualifiedIdentifierNode->mTarget == NULL;
- }
- int chevronDepth = 0;
- bool didSplit = false;
- for (int checkIdx = curNodeEndIdx; checkIdx >= mVisitorPos.mReadPos; checkIdx--)
- {
- if (isDotName)
- break;
- auto checkNode = mVisitorPos.Get(checkIdx);
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(checkNode))
- {
- BfToken token = tokenNode->GetToken();
- if (((token == BfToken_RChevron) || (token == BfToken_RDblChevron)) && (chevronDepth == 0))
- {
- auto nextCheckNode = mVisitorPos.Get(checkIdx + 1);
- if (auto nextTokenNode = BfNodeDynCast<BfTokenNode>(nextCheckNode))
- {
- if (nextTokenNode->GetToken() == BfToken_Dot)
- {
- TryIdentifierConvert(checkIdx + 2);
- auto nextNextCheckNode = mVisitorPos.Get(checkIdx + 2);
- if (auto identifierNode = BfNodeDynCast<BfIdentifierNode>(nextNextCheckNode))
- {
- // Remove dot temporarily so we create a typedef up to that dot
- nextTokenNode->SetToken(BfToken_None);
- auto typeRef = CreateTypeRef(startIdentifier);
- if (typeRef == NULL)
- return NULL;
- nextTokenNode->SetToken(BfToken_Dot);
- auto memberRefExpr = mAlloc->Alloc<BfMemberReferenceExpression>();
- ReplaceNode(identifierNode, memberRefExpr);
- MEMBER_SET(memberRefExpr, mDotToken, nextTokenNode);
- MEMBER_SET(memberRefExpr, mTarget, typeRef);
- MEMBER_SET(memberRefExpr, mMemberName, identifierNode);
- memberRefExpr->mTriviaStart = typeRef->mTriviaStart;
- exprLeft = memberRefExpr;
- mVisitorPos.mReadPos = checkIdx + 2;
- didSplit = true;
- break;
- }
- else if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNextCheckNode))
- {
- if (tokenNode->GetToken() == BfToken_LBracket)
- {
- // Remove dot temporarily so we create a typedef up to that dot
- nextTokenNode->SetToken(BfToken_None);
- auto typeRef = CreateTypeRef(startIdentifier);
- if (typeRef == NULL)
- return NULL;
- nextTokenNode->SetToken(BfToken_Dot);
- mVisitorPos.mReadPos = checkIdx + 0;
- exprLeft = CreateMemberReferenceExpression(typeRef);
- didSplit = true;
- }
- }
- }
- else if (nextTokenNode->GetToken() == BfToken_LBracket)
- {
- int endNodeIdx = -1;
- if (IsTypeReference(startIdentifier, BfToken_LParen, -1, &endNodeIdx))
- {
- if (endNodeIdx > checkIdx + 1)
- {
- auto typeRef = CreateTypeRef(startIdentifier);
- auto arrayType = BfNodeDynCast<BfArrayTypeRef>(typeRef);
- if (arrayType == NULL)
- return NULL;
- mVisitorPos.mReadPos = checkIdx + 0;
- auto arrayCreateExpr = mAlloc->Alloc<BfSizedArrayCreateExpression>();
- ReplaceNode(typeRef, arrayCreateExpr);
- arrayCreateExpr->mTypeRef = arrayType;
- mVisitorPos.mReadPos = endNodeIdx;
- auto initializerExpr = CreateCollectionInitializerExpression(BfNodeDynCast<BfTokenNode>(mVisitorPos.GetCurrent()));
- MEMBER_SET(arrayCreateExpr, mInitializer, initializerExpr);
- exprLeft = arrayCreateExpr;
- return arrayCreateExpr;
- }
- }
- }
- }
- }
- if (token == BfToken_RChevron)
- chevronDepth++;
- else if (token == BfToken_RDblChevron)
- chevronDepth += 2;
- else if (token == BfToken_LChevron)
- chevronDepth--;
- else if (token == BfToken_LDblChevron)
- chevronDepth -= 2;
- }
- }
- if (didSplit)
- continue;
- }
- // Could be a struct generic initializer, or a generic method invocation
- if (auto outToken = BfNodeDynCast<BfTokenNode>(outNode))
- {
- int endNodeIdx = -1;
- if (((outToken->mToken == BfToken_LParen) && (IsTypeReference(exprLeft, BfToken_LParen, -1, &endNodeIdx))) ||
- (outToken->mToken == BfToken_DotDotDot))
- {
- exprLeft = CreateInvocationExpression(exprLeft);
- if (exprLeft == NULL)
- return NULL;
- continue;
- }
- }
- if (hadEndingToken)
- return exprLeft;
- }
- if (token == BfToken_Star)
- {
- auto nextNode = mVisitorPos.GetNext();
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if ((nextToken->mToken == BfToken_Star) || (nextToken->mToken == BfToken_LBracket))
- {
- //if (IsTypeReference(tokenNode, BfToken_LBracket))
- {
- /*auto typeRef = CreateTypeRef(tokenNode, true);
- exprLeft = CreateObjectCreateExpression(typeRef);
- return exprLeft;*/
- }
- }
- }
- }
- BfBinaryOp binOp = BfTokenToBinaryOp(tokenNode->GetToken());
- if (binOp != BfBinaryOp_None)
- {
- if ((createExprFlags & CreateExprFlags_EarlyExit) != 0)
- return exprLeft;
- mVisitorPos.MoveNext();
- // We only need to check binary operator precedence at the "top level" binary operator
- rhsCreateExprFlags = (CreateExprFlags)(rhsCreateExprFlags | CreateExprFlags_NoCheckBinOpPrecedence);
- if (tokenNode->mToken == BfToken_DotDotDot)
- rhsCreateExprFlags = (CreateExprFlags)(rhsCreateExprFlags | CreateExprFlags_AllowEmpty);
- BfExpression* exprRight = CreateExpressionAfter(tokenNode, rhsCreateExprFlags);
- if (exprRight == NULL)
- {
- if (tokenNode->mToken == BfToken_DotDotDot)
- {
- auto unaryOpExpression = mAlloc->Alloc<BfUnaryOperatorExpression>();
- ReplaceNode(exprLeft, unaryOpExpression);
- unaryOpExpression->mExpression = exprLeft;
- unaryOpExpression->mOp = BfUnaryOp_PartialRangeFrom;
- MEMBER_SET(unaryOpExpression, mOpToken, tokenNode);
- return unaryOpExpression;
- }
- }
- auto binOpExpression = mAlloc->Alloc<BfBinaryOperatorExpression>();
- ReplaceNode(exprLeft, binOpExpression);
- binOpExpression->mLeft = exprLeft;
- binOpExpression->mOp = binOp;
- MEMBER_SET(binOpExpression, mOpToken, tokenNode);
- if (exprRight == NULL)
- return binOpExpression;
- MEMBER_SET(binOpExpression, mRight, exprRight);
- if ((createExprFlags & CreateExprFlags_NoCheckBinOpPrecedence) != 0)
- return binOpExpression;
- return CheckBinaryOperatorPrecedence(binOpExpression);
- }
- auto assignmentOp = BfTokenToAssignmentOp(tokenNode->GetToken());
- if (assignmentOp != BfAssignmentOp_None)
- {
- if ((createExprFlags & CreateExprFlags_EarlyExit) != 0)
- return exprLeft;
- if ((createExprFlags & CreateExprFlags_NoAssignment) != 0)
- return exprLeft;
- auto assignmentExpression = mAlloc->Alloc<BfAssignmentExpression>();
- ReplaceNode(exprLeft, assignmentExpression);
- mVisitorPos.MoveNext();
- assignmentExpression->mOp = assignmentOp;
- assignmentExpression->mLeft = exprLeft;
- assignmentExpression->mOpToken = tokenNode;
- MoveNode(assignmentExpression->mOpToken, assignmentExpression);
- bool continueCascade = false;
- if (auto memberExpr = BfNodeDynCast<BfMemberReferenceExpression>(exprLeft))
- {
- if ((memberExpr->mDotToken != NULL) && (memberExpr->mDotToken->GetToken() == BfToken_DotDot))
- continueCascade = true;
- }
- CreateExprFlags flags = rhsCreateExprFlags;
- if (continueCascade)
- flags = (CreateExprFlags)(rhsCreateExprFlags | CreateExprFlags_BreakOnCascade);
- auto exprRight = CreateExpressionAfter(assignmentExpression, flags);
- if (exprRight == NULL)
- {
- FailAfter("Invalid expression", assignmentExpression);
- return assignmentExpression;
- }
- assignmentExpression->mRight = exprRight;
- MoveNode(assignmentExpression->mRight, assignmentExpression);
- if (continueCascade)
- {
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if (nextToken->GetToken() == BfToken_DotDot)
- {
- exprLeft = assignmentExpression;
- continue;
- }
- }
- }
- return assignmentExpression;
- }
- BF_ASSERT(tokenNode->GetToken() == token);
- if (token == BfToken_Dot)
- {
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(mVisitorPos.mReadPos + 2)))
- {
- if (nextToken->mToken == BfToken_This)
- {
- int outNodeIdx = -1;
- bool isGenericType;
- bool isTypeRef = ((IsTypeReference(exprLeft, BfToken_This, -1, &outNodeIdx, NULL, &isGenericType)) &&
- (outNodeIdx != -1));
- if (isTypeRef)
- {
- auto invocationExpr = CreateObjectCreateExpression(NULL, exprLeft);
- if (invocationExpr == NULL)
- return exprLeft;
- exprLeft = invocationExpr;
- continue;
- }
- }
- }
- }
- // Not a binary op, it's a 'close'
- if (token == BfToken_Bang)
- {
- if ((createExprFlags & CreateExprFlags_ExitOnBang) != 0)
- return exprLeft;
- exprLeft = CreateInvocationExpression(exprLeft);
- }
- else if (token == BfToken_LParen)
- {
- exprLeft = CreateInvocationExpression(exprLeft, (CreateExprFlags)(createExprFlags & ~(CreateExprFlags_NoCast)));
- if (auto initExpr = TryCreateInitializerExpression(exprLeft))
- exprLeft = initExpr;
- }
- else if ((token == BfToken_LBracket) || (token == BfToken_QuestionLBracket))
- {
- exprLeft = CreateIndexerExpression(exprLeft);
- }
- else if ((token == BfToken_Dot) || (token == BfToken_DotDot) || (token == BfToken_QuestionDot) || (token == BfToken_Arrow))
- {
- if ((token == BfToken_DotDot) && ((createExprFlags & CreateExprFlags_BreakOnCascade) != 0))
- return exprLeft;
- if (auto memberExpr = BfNodeDynCastExact<BfMemberReferenceExpression>(exprLeft))
- {
- if (memberExpr->mTarget == NULL)
- {
- // A dot syntax like ".A.B" is never valid - to help with autocomplete we stop the expr parsing here
- Fail("Unexpected '.' token", tokenNode);
- return exprLeft;
- }
- }
- exprLeft = CreateMemberReferenceExpression(exprLeft);
- }
- else
- {
- return exprLeft;
- }
- if (exprLeft == NULL)
- return NULL;
- }
- else
- break;
- }
- return exprLeft;
- }
- BfExpression* BfReducer::CreateExpressionAfter(BfAstNode* node, CreateExprFlags createExprFlags)
- {
- if (!AssertCurrentNode(node))
- return NULL;
- auto nextNode = mVisitorPos.GetNext();
- bool isEmpty = false;
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (tokenNode->GetToken() == BfToken_RParen)
- isEmpty = true;
- }
- if ((nextNode == NULL) || (isEmpty))
- {
- FailAfter("Expression expected", node);
- return NULL;
- }
- int startReadPos = mVisitorPos.mReadPos;
- mVisitorPos.MoveNext();
- auto result = CreateExpression(nextNode, createExprFlags);
- if (result == NULL)
- {
- // Nope, didn't handle it
- mVisitorPos.mReadPos = startReadPos;
- }
- return result;
- }
- BfForEachStatement* BfReducer::CreateForEachStatement(BfAstNode* node, bool hasTypeDecl)
- {
- auto forToken = BfNodeDynCast<BfTokenNode>(node);
- auto parenToken = ExpectTokenAfter(forToken, BfToken_LParen);
- if (parenToken == NULL)
- return NULL;
- auto forEachStatement = mAlloc->Alloc<BfForEachStatement>();
- ReplaceNode(forToken, forEachStatement);
- MEMBER_SET(forEachStatement, mForToken, forToken);
- MEMBER_SET(forEachStatement, mOpenParen, parenToken);
- if (hasTypeDecl)
- {
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if (tokenNode->mToken == BfToken_ReadOnly)
- {
- MEMBER_SET_CHECKED(forEachStatement, mReadOnlyToken, tokenNode);
- mVisitorPos.MoveNext();
- }
- }
- auto typeRef = CreateTypeRefAfter(forEachStatement);
- if (typeRef == NULL)
- return forEachStatement;
- MEMBER_SET_CHECKED(forEachStatement, mVariableTypeRef, typeRef);
- }
- if (auto nextNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if ((nextNode->mToken == BfToken_LParen) || (nextNode->mToken == BfToken_LessEquals))
- {
- mVisitorPos.MoveNext();
- auto tupleNode = CreateTupleExpression(nextNode);
- MEMBER_SET_CHECKED(forEachStatement, mVariableName, tupleNode);
- }
- }
- if (forEachStatement->mVariableName == NULL)
- {
- auto name = ExpectIdentifierAfter(forEachStatement, "variable name");
- MEMBER_SET_CHECKED(forEachStatement, mVariableName, name);
- }
- auto inToken = ExpectTokenAfter(forEachStatement, BfToken_In, BfToken_LChevron, BfToken_LessEquals);
- MEMBER_SET_CHECKED(forEachStatement, mInToken, inToken);
- auto expr = CreateExpressionAfter(forEachStatement);
- MEMBER_SET_CHECKED(forEachStatement, mCollectionExpression, expr);
- parenToken = ExpectTokenAfter(forEachStatement, BfToken_RParen);
- MEMBER_SET_CHECKED(forEachStatement, mCloseParen, parenToken);
- auto stmt = CreateStatementAfter(forEachStatement, CreateStmtFlags_FindTrailingSemicolon);
- if (stmt == NULL)
- return forEachStatement;
- MEMBER_SET(forEachStatement, mEmbeddedStatement, stmt);
- return forEachStatement;
- }
- BfStatement* BfReducer::CreateForStatement(BfAstNode* node)
- {
- int startReadIdx = mVisitorPos.mReadPos;
- auto forToken = BfNodeDynCast<BfTokenNode>(node);
- auto parenToken = ExpectTokenAfter(forToken, BfToken_LParen);
- if (parenToken == NULL)
- return NULL;
- int outNodeIdx = -1;
- auto nextNode = mVisitorPos.GetNext();
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- // Handle 'for (let (key, value) in dict)'
- if ((tokenNode->mToken == BfToken_Let) || (tokenNode->mToken == BfToken_Var))
- {
- if (auto afterLet = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(mVisitorPos.mReadPos + 2)))
- {
- if (afterLet->mToken == BfToken_LParen)
- {
- bool isTupleIn = true;
- int parenDepth = 1;
- for (int readPos = mVisitorPos.mReadPos + 3; true; readPos++)
- {
- auto checkNode = mVisitorPos.Get(readPos);
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(checkNode))
- {
- if (tokenNode->mToken == BfToken_RParen)
- {
- if (parenDepth != 1)
- {
- isTupleIn = false;
- break;
- }
- parenDepth--;
- }
- else if (tokenNode->mToken == BfToken_In)
- {
- if (parenDepth != 0)
- isTupleIn = false;
- break;
- }
- else if (tokenNode->mToken == BfToken_Comma)
- {
- //
- }
- else
- {
- isTupleIn = false;
- break;
- }
- }
- else if (auto identifierNode = BfNodeDynCast<BfIdentifierNode>(checkNode))
- {
- //
- }
- else
- {
- isTupleIn = false;
- break;
- }
- }
- if (isTupleIn)
- {
- mVisitorPos.mReadPos = startReadIdx;
- return CreateForEachStatement(node, true);
- }
- }
- }
- }
- }
- bool isTypeRef = false;
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (nextNode->mToken == BfToken_ReadOnly)
- {
- mVisitorPos.mReadPos += 2;
- isTypeRef = IsTypeReference(mVisitorPos.Get(mVisitorPos.mReadPos), BfToken_None, -1, &outNodeIdx);
- mVisitorPos.mReadPos -= 2;
- }
- }
- if (!isTypeRef)
- {
- mVisitorPos.mReadPos++;
- isTypeRef = IsTypeReference(nextNode, BfToken_None, -1, &outNodeIdx);
- mVisitorPos.mReadPos--;
- }
- BfAstNode* outNode = mVisitorPos.Get(outNodeIdx);
- if (isTypeRef)
- {
- auto nextNode = mVisitorPos.Get(outNodeIdx + 1);
- if ((outNode != NULL) && (nextNode != NULL))
- {
- auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if (tokenNode != NULL)
- {
- int token = tokenNode->GetToken();
- if ((token == BfToken_In) || (token == BfToken_LChevron) || (token == BfToken_LessEquals))
- {
- mVisitorPos.mReadPos = startReadIdx;
- return CreateForEachStatement(node, true);
- }
- }
- }
- }
- else
- {
- int checkNodeIdx = (outNodeIdx != -1) ? outNodeIdx : mVisitorPos.mReadPos + 1;
- auto checkNode = mVisitorPos.Get(checkNodeIdx);
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(checkNode))
- {
- BfToken token = tokenNode->GetToken();
- // Is this an 'anonymous' foreach?
- if ((token != BfToken_Semicolon) && (token != BfToken_LChevron) &&
- (token != BfToken_In) && (token != BfToken_AssignEquals))
- {
- mVisitorPos.mReadPos = startReadIdx;
- auto forToken = BfNodeDynCast<BfTokenNode>(node);
- auto parenToken = ExpectTokenAfter(forToken, BfToken_LParen);
- if (parenToken == NULL)
- return NULL;
- auto forEachStatement = mAlloc->Alloc<BfForEachStatement>();
- ReplaceNode(forToken, forEachStatement);
- MEMBER_SET(forEachStatement, mForToken, forToken);
- MEMBER_SET(forEachStatement, mOpenParen, parenToken);
- auto expr = CreateExpressionAfter(forEachStatement);
- MEMBER_SET_CHECKED(forEachStatement, mCollectionExpression, expr);
- parenToken = ExpectTokenAfter(forEachStatement, BfToken_RParen);
- MEMBER_SET_CHECKED(forEachStatement, mCloseParen, parenToken);
- auto stmt = CreateStatementAfter(forEachStatement, CreateStmtFlags_FindTrailingSemicolon);
- if (stmt == NULL)
- return forEachStatement;
- MEMBER_SET(forEachStatement, mEmbeddedStatement, stmt);
- return forEachStatement;
- }
- }
- }
- auto nextNextNode = mVisitorPos.Get(mVisitorPos.mReadPos + 2);
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNextNode))
- {
- if ((tokenNode != NULL) && ((tokenNode->GetToken() == BfToken_LChevron) || (tokenNode->GetToken() == BfToken_In)))
- {
- Fail("Ranged for statement must declare new value variable, consider adding a type name, 'var', or 'let'", tokenNode);
- mVisitorPos.mReadPos = startReadIdx;
- return CreateForEachStatement(node, false);
- }
- }
- BfAstNode* stmt;
- auto forStatement = mAlloc->Alloc<BfForStatement>();
- BfDeferredAstSizedArray<BfAstNode*> initializers(forStatement->mInitializers, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> initializerCommas(forStatement->mInitializerCommas, mAlloc);
- BfDeferredAstSizedArray<BfAstNode*> iterators(forStatement->mIterators, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> iteratorCommas(forStatement->mIteratorCommas, mAlloc);
- ReplaceNode(forToken, forStatement);
- MEMBER_SET(forStatement, mForToken, forToken);
- MEMBER_SET(forStatement, mOpenParen, parenToken);
- // Initializers
- for (int listIdx = 0; true; listIdx++)
- {
- auto nextNode = mVisitorPos.GetNext();
- if ((listIdx > 0) || (!IsSemicolon(nextNode)))
- {
- auto stmt = CreateStatementAfter(forStatement);
- if (stmt == NULL)
- return forStatement;
- if (!initializers.IsEmpty())
- {
- // Try to convert 'int i = 0, j = 0` into two variable declarations instead of a var decl and an assignment
- if (auto prevExprStmt = BfNodeDynCast<BfExpressionStatement>(initializers.back()))
- {
- if (auto prevVarDecl = BfNodeDynCast<BfVariableDeclaration>(prevExprStmt->mExpression))
- {
- if (auto exprStmt = BfNodeDynCast<BfExpressionStatement>(stmt))
- {
- if (auto assignExpr = BfNodeDynCast<BfAssignmentExpression>(exprStmt->mExpression))
- {
- if (assignExpr->mOp != BfAssignmentOp_Assign)
- continue;
- if (auto identifierNode = BfNodeDynCast<BfIdentifierNode>(assignExpr->mLeft))
- {
- auto varDecl = mAlloc->Alloc<BfVariableDeclaration>();
- ReplaceNode(assignExpr, varDecl);
- varDecl->mTypeRef = prevVarDecl->mTypeRef;
- varDecl->mNameNode = identifierNode;
- varDecl->mEqualsNode = assignExpr->mOpToken;
- varDecl->mInitializer = assignExpr->mRight;
- varDecl->mModSpecifier = prevVarDecl->mModSpecifier;
- exprStmt->mExpression = varDecl;
- }
- }
- }
- }
- }
- }
- initializers.push_back(stmt);
- MoveNode(stmt, forStatement);
- }
- nextNode = mVisitorPos.GetNext();
- auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if (tokenNode == NULL)
- return forStatement;
- if (tokenNode->GetToken() == BfToken_Semicolon)
- {
- MEMBER_SET(forStatement, mInitializerSemicolon, tokenNode);
- mVisitorPos.MoveNext();
- break;
- }
- else if (tokenNode->GetToken() == BfToken_Comma)
- {
- MoveNode(tokenNode, forStatement);
- initializerCommas.push_back(tokenNode);
- mVisitorPos.MoveNext();
- }
- else
- {
- Fail("Expected ',' or ';'", tokenNode);
- return forStatement;
- }
- }
- // Condition
- nextNode = mVisitorPos.GetNext();
- if (!IsSemicolon(nextNode))
- {
- bool doExpr = true;
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (tokenNode->GetToken() == BfToken_RParen)
- {
- Fail("Expected expression or ';'", tokenNode);
- doExpr = false;
- }
- }
- if (doExpr)
- {
- auto expr = CreateExpressionAfter(forStatement);
- if (expr == NULL)
- return forStatement;
- MEMBER_SET(forStatement, mCondition, expr);
- }
- }
- auto tokenNode = ExpectTokenAfter(forStatement, BfToken_Semicolon);
- if (tokenNode == NULL)
- return forStatement;
- MEMBER_SET(forStatement, mConditionSemicolon, tokenNode);
- // Iterators
- for (int listIdx = 0; true; listIdx++)
- {
- if (listIdx == 0)
- {
- auto nextNode = mVisitorPos.GetNext();
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (tokenNode->GetToken() == BfToken_RParen)
- {
- MEMBER_SET(forStatement, mCloseParen, tokenNode);
- mVisitorPos.MoveNext();
- break;
- }
- }
- }
- auto stmt = CreateStatementAfter(forStatement);
- if (stmt == NULL)
- return forStatement;
- iterators.push_back(stmt);
- MoveNode(stmt, forStatement);
- auto nextNode = mVisitorPos.GetNext();
- tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if (tokenNode == NULL)
- return forStatement;
- if (tokenNode->GetToken() == BfToken_RParen)
- {
- MEMBER_SET(forStatement, mCloseParen, tokenNode);
- mVisitorPos.MoveNext();
- break;
- }
- else if (tokenNode->GetToken() == BfToken_Comma)
- {
- MoveNode(tokenNode, forStatement);
- iteratorCommas.push_back(tokenNode);
- mVisitorPos.MoveNext();
- }
- else
- {
- Fail("Expected ',' or ')'", tokenNode);
- return forStatement;
- }
- }
- stmt = CreateStatementAfter(forStatement, CreateStmtFlags_FindTrailingSemicolon);
- if (stmt == NULL)
- return forStatement;
- MEMBER_SET(forStatement, mEmbeddedStatement, stmt);
- return forStatement;
- }
- BfUsingStatement* BfReducer::CreateUsingStatement(BfAstNode* node)
- {
- auto tokenNode = BfNodeDynCast<BfTokenNode>(node);
- auto usingStatement = mAlloc->Alloc<BfUsingStatement>();
- ReplaceNode(tokenNode, usingStatement);
- MEMBER_SET(usingStatement, mUsingToken, tokenNode);
- tokenNode = ExpectTokenAfter(usingStatement, BfToken_LParen);
- if (tokenNode == NULL)
- return NULL;
- MEMBER_SET(usingStatement, mOpenParen, tokenNode);
- auto nextNode = mVisitorPos.GetNext();
- if (nextNode != NULL)
- {
- BfVariableDeclaration* varDecl = mAlloc->Alloc<BfVariableDeclaration>();
- int outNodeIdx = -1;
- auto nextNode = mVisitorPos.GetNext();
- mVisitorPos.mReadPos++;
- bool isTypeReference = IsTypeReference(nextNode, BfToken_None, -1, &outNodeIdx);
- mVisitorPos.mReadPos--;
- if (isTypeReference)
- {
- BfAstNode* outNode = mVisitorPos.Get(outNodeIdx);
- BfAstNode* outNodeNext = mVisitorPos.Get(outNodeIdx + 1);
- BfTokenNode* equalsNode = NULL;
- if ((outNode != NULL) && (BfNodeIsA<BfIdentifierNode>(outNode)) && (BfNodeIsA<BfTokenNode>(outNodeNext)))
- {
- auto typeRef = CreateTypeRefAfter(usingStatement);
- if (typeRef == NULL)
- return usingStatement;
- MEMBER_SET(varDecl, mTypeRef, typeRef);
- usingStatement->SetSrcEnd(typeRef->GetSrcEnd());
- auto nameNode = ExpectIdentifierAfter(usingStatement, "variable name");
- if (nameNode == NULL)
- return usingStatement;
- MEMBER_SET(varDecl, mNameNode, nameNode);
- usingStatement->SetSrcEnd(varDecl->GetSrcEnd());
- auto equalsNode = ExpectTokenAfter(usingStatement, BfToken_AssignEquals);
- if (equalsNode == NULL)
- return usingStatement;
- MEMBER_SET(varDecl, mEqualsNode, equalsNode);
- usingStatement->SetSrcEnd(equalsNode->GetSrcEnd());
- }
- }
- auto expr = CreateExpressionAfter(usingStatement);
- if (expr == NULL)
- return usingStatement;
- MEMBER_SET(varDecl, mInitializer, expr);
- MEMBER_SET(usingStatement, mVariableDeclaration, varDecl);
- }
- tokenNode = ExpectTokenAfter(usingStatement, BfToken_RParen);
- if (tokenNode == NULL)
- return usingStatement;
- MEMBER_SET(usingStatement, mCloseParen, tokenNode);
- auto stmt = CreateStatementAfter(usingStatement, CreateStmtFlags_FindTrailingSemicolon);
- if (stmt == NULL)
- return usingStatement;
- MEMBER_SET(usingStatement, mEmbeddedStatement, stmt);
- return usingStatement;
- }
- BfWhileStatement* BfReducer::CreateWhileStatement(BfAstNode* node)
- {
- auto tokenNode = BfNodeDynCast<BfTokenNode>(node);
- auto whileStatement = mAlloc->Alloc<BfWhileStatement>();
- ReplaceNode(tokenNode, whileStatement);
- MEMBER_SET(whileStatement, mWhileToken, tokenNode);
- tokenNode = ExpectTokenAfter(whileStatement, BfToken_LParen);
- if (tokenNode == NULL)
- return NULL;
- MEMBER_SET(whileStatement, mOpenParen, tokenNode);
- // Condition
- auto nextNode = mVisitorPos.GetNext();
- if (!IsSemicolon(nextNode))
- {
- auto expr = CreateExpressionAfter(whileStatement);
- if (expr == NULL)
- return whileStatement;
- MEMBER_SET(whileStatement, mCondition, expr);
- }
- tokenNode = ExpectTokenAfter(whileStatement, BfToken_RParen);
- if (tokenNode == NULL)
- return whileStatement;
- MEMBER_SET(whileStatement, mCloseParen, tokenNode);
- auto stmt = CreateStatementAfter(whileStatement, CreateStmtFlags_FindTrailingSemicolon);
- if (stmt == NULL)
- return whileStatement;
- MEMBER_SET(whileStatement, mEmbeddedStatement, stmt);
- return whileStatement;
- }
- BfDoStatement* BfReducer::CreateDoStatement(BfAstNode* node)
- {
- auto tokenNode = BfNodeDynCast<BfTokenNode>(node);
- auto doStatement = mAlloc->Alloc<BfDoStatement>();
- ReplaceNode(tokenNode, doStatement);
- MEMBER_SET(doStatement, mDoToken, tokenNode);
- auto stmt = CreateStatementAfter(doStatement, CreateStmtFlags_FindTrailingSemicolon);
- if (stmt != NULL)
- {
- MEMBER_SET(doStatement, mEmbeddedStatement, stmt);
- }
- return doStatement;
- }
- BfRepeatStatement* BfReducer::CreateRepeatStatement(BfAstNode* node)
- {
- auto tokenNode = BfNodeDynCast<BfTokenNode>(node);
- auto repeatStatement = mAlloc->Alloc<BfRepeatStatement>();
- ReplaceNode(tokenNode, repeatStatement);
- MEMBER_SET(repeatStatement, mRepeatToken, tokenNode);
- auto stmt = CreateStatementAfter(repeatStatement, CreateStmtFlags_FindTrailingSemicolon);
- if (stmt != NULL)
- {
- MEMBER_SET(repeatStatement, mEmbeddedStatement, stmt);
- }
- tokenNode = ExpectTokenAfter(repeatStatement, BfToken_While);
- if (tokenNode != NULL)
- {
- MEMBER_SET(repeatStatement, mWhileToken, tokenNode);
- }
- tokenNode = ExpectTokenAfter(repeatStatement, BfToken_LParen);
- if (tokenNode != NULL)
- {
- MEMBER_SET(repeatStatement, mOpenParen, tokenNode);
- }
- // Condition
- auto nextNode = mVisitorPos.GetNext();
- if (!IsSemicolon(nextNode))
- {
- auto expr = CreateExpressionAfter(repeatStatement);
- if (expr == NULL)
- return repeatStatement;
- MEMBER_SET(repeatStatement, mCondition, expr);
- }
- tokenNode = ExpectTokenAfter(repeatStatement, BfToken_RParen);
- if (tokenNode != NULL)
- {
- MEMBER_SET(repeatStatement, mCloseParen, tokenNode);
- }
- return repeatStatement;
- }
- BfSwitchStatement* BfReducer::CreateSwitchStatement(BfTokenNode* tokenNode)
- {
- auto switchStatement = mAlloc->Alloc<BfSwitchStatement>();
- BfDeferredAstSizedArray<BfSwitchCase*> switchCases(switchStatement->mSwitchCases, mAlloc);
- ReplaceNode(tokenNode, switchStatement);
- switchStatement->mSwitchToken = tokenNode;
- tokenNode = ExpectTokenAfter(switchStatement, BfToken_LParen);
- if (tokenNode != NULL)
- {
- MEMBER_SET(switchStatement, mOpenParen, tokenNode);
- }
- auto switchValue = CreateExpressionAfter(switchStatement);
- if (switchValue != NULL)
- {
- MEMBER_SET(switchStatement, mSwitchValue, switchValue);
- }
- tokenNode = ExpectTokenAfter(switchStatement, BfToken_RParen);
- if (tokenNode != NULL)
- {
- MEMBER_SET(switchStatement, mCloseParen, tokenNode);
- }
- auto block = ExpectBlockAfter(switchStatement);
- if (block == NULL)
- return switchStatement;
- MoveNode(block, switchStatement);
- switchStatement->mOpenBrace = block->mOpenBrace;
- switchStatement->mCloseBrace = block->mCloseBrace;
- bool hadEmptyCaseStatement = false;
- BfSwitchCase* switchCase = NULL;
- SetAndRestoreValue<BfVisitorPos> prevVisitorPos(mVisitorPos, BfVisitorPos(block));
- bool isDone = !mVisitorPos.MoveNext();
- while (!isDone)
- {
- auto child = mVisitorPos.GetCurrent();
- tokenNode = BfNodeDynCast<BfTokenNode>(child);
- BfToken token = BfToken_None;
- if (tokenNode != NULL)
- token = tokenNode->GetToken();
- if ((tokenNode == NULL) ||
- ((token != BfToken_Case) && (token != BfToken_When) && (token != BfToken_Default)))
- {
- Fail("Expected 'case'", child);
- AddErrorNode(child);
- isDone = !mVisitorPos.MoveNext();
- continue;
- }
- //TODO: This error was getting annoying... Put back?
- // This check is here at the top, being processed for the previous switchCase because
- // we don't throw an error on the last case in the switch
- /*if (hadEmptyCaseStatement)
- FailAfter("Expected case statement, 'fallthrough', or 'break'", switchCase);*/
- bool isDefault = token == BfToken_Default;
- switchCase = mAlloc->Alloc<BfSwitchCase>();
- BfDeferredAstSizedArray<BfExpression*> caseExpressions(switchCase->mCaseExpressions, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> caseCommas(switchCase->mCaseCommas, mAlloc);
- ReplaceNode(tokenNode, switchCase);
- BfTokenNode* whenToken = NULL;
- if (token == BfToken_When)
- whenToken = tokenNode;
- else
- switchCase->mCaseToken = tokenNode;
- for (int caseIdx = 0; true; caseIdx++)
- {
- if (!isDefault)
- {
- BfExpression* expr = NULL;
- bool wasWhenSet = whenToken != NULL;
- if (!wasWhenSet)
- {
- auto nextNode = mVisitorPos.GetNext();
- whenToken = BfNodeDynCast<BfTokenNode>(nextNode);
- if ((whenToken != NULL) && (whenToken->GetToken() == BfToken_When))
- {
- mVisitorPos.MoveNext();
- }
- else
- whenToken = NULL;
- }
- if (whenToken != NULL)
- {
- auto whenExpr = mAlloc->Alloc<BfWhenExpression>();
- whenExpr->mWhenToken = whenToken;
- ReplaceNode(whenToken, whenExpr);
- //mVisitorPos.MoveNext();
- //auto exprAfter = wasWhenSet ? (BfAstNode*)switchCase : (BfAstNode*)whenExpr;
- if (expr == NULL)
- {
- auto innerExpr = CreateExpressionAfter(whenToken);
- if (innerExpr != NULL)
- {
- MEMBER_SET(whenExpr, mExpression, innerExpr);
- }
- expr = whenExpr;
- }
- }
- if (expr == NULL)
- {
- if (auto bindToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if ((bindToken->GetToken() == BfToken_Var) || (bindToken->GetToken() == BfToken_Let))
- {
- expr = CreateEnumCaseBindExpression(bindToken);
- }
- }
- }
- if (expr == NULL)
- expr = CreateExpressionAfter(switchCase);
- if (expr == NULL)
- {
- ///
- }
- else
- {
- caseExpressions.push_back(expr);
- MoveNode(expr, switchCase);
- }
- }
- if ((whenToken == NULL) && (!isDefault))
- tokenNode = ExpectTokenAfter(switchCase, BfToken_When, BfToken_Colon, BfToken_Comma);
- else
- tokenNode = ExpectTokenAfter(switchCase, BfToken_Colon);
- if (tokenNode == NULL)
- break;
- if (tokenNode->GetToken() == BfToken_When)
- {
- whenToken = tokenNode;
- continue;
- }
- if (tokenNode->GetToken() == BfToken_Colon)
- {
- MEMBER_SET(switchCase, mColonToken, tokenNode);
- break;
- }
- if (isDefault)
- {
- Fail("Expected ':'", tokenNode);
- break;
- }
- MoveNode(tokenNode, switchCase);
- caseCommas.push_back(tokenNode);
- BF_ASSERT(whenToken == NULL);
- }
- if (isDefault)
- {
- if (switchStatement->mDefaultCase != NULL)
- {
- Fail("Only one default case is allowed", switchCase);
- // Add to normal switch cases just so we process it
- switchCases.push_back(switchCase);
- }
- else
- switchStatement->mDefaultCase = switchCase;
- }
- else
- {
- if (switchStatement->mDefaultCase != NULL)
- {
- Fail("Default case must be last case", switchStatement->mDefaultCase);
- }
- switchCases.push_back(switchCase);
- }
- hadEmptyCaseStatement = true;
- auto codeBlock = mAlloc->Alloc<BfBlock>();
- //codeBlock->mSource = switchCase->mSource;
- MEMBER_SET(switchCase, mCodeBlock, codeBlock);
- //switchCase->Add(codeBlock);
- BfDeferredAstSizedArray<BfAstNode*> codeBlockChildArr(codeBlock->mChildArr, mAlloc);
- SetAndRestoreValue<BfAstNode*> prevLastBlockNode(mLastBlockNode, NULL);
- while (true)
- {
- auto nextNode = mVisitorPos.GetNext();
- auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if (tokenNode != NULL)
- {
- int token = tokenNode->GetToken();
- if ((token == BfToken_Case) || (token == BfToken_Default) || (token == BfToken_When))
- break; // Done! No fallthrough
- }
- nextNode = mVisitorPos.GetNext();
- if (nextNode == NULL)
- break;
- hadEmptyCaseStatement = false;
- mVisitorPos.MoveNext();
- // We need to use CreateStmtFlags_NoCaseExpr because otherwise during typing a new statement at the end of one case, it
- // could interpret the 'case' token for the next case as being part of a case expression in the first case
- auto stmt = CreateStatement(nextNode, (CreateStmtFlags)(CreateStmtFlags_FindTrailingSemicolon | CreateStmtFlags_NoCaseExpr | CreateStmtFlags_AllowLocalFunction));
- if (stmt == NULL)
- {
- AddErrorNode(nextNode);
- }
- else
- {
- MoveNode(stmt, codeBlock);
- codeBlockChildArr.push_back(stmt);
- }
- mLastBlockNode = stmt;
- }
- MoveNode(switchCase, switchStatement);
- if (!codeBlock->IsInitialized())
- {
- int srcPos = switchCase->GetSrcEnd();
- codeBlock->Init(srcPos, srcPos, srcPos);
- }
- isDone = !mVisitorPos.MoveNext();
- }
- return switchStatement;
- }
- // Does everything but pull the trailing semicolon
- BfAstNode* BfReducer::DoCreateStatement(BfAstNode* node, CreateStmtFlags createStmtFlags)
- {
- auto subCreateStmtFlags = (CreateStmtFlags)(createStmtFlags & (CreateStmtFlags_NoCaseExpr | CreateStmtFlags_FindTrailingSemicolon | CreateStmtFlags_AllowUnterminatedExpression));
- if (node->IsA<BfBlock>())
- {
- auto block = (BfBlock*)node;
- HandleBlock(block, (createStmtFlags & CreateStmtFlags_AllowUnterminatedExpression) != 0);
- return block;
- }
- BfVariableDeclaration* continuingVariable = NULL;
- BfTokenNode* refToken = NULL;
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(node))
- {
- int token = tokenNode->GetToken();
- if ((token == BfToken_Ref) || (token == BfToken_Mut))
- {
- refToken = tokenNode;
- }
- else if (token == BfToken_Semicolon)
- {
- Fail("Empty statement not allowed", tokenNode);
- auto emptyStatement = mAlloc->Alloc<BfEmptyStatement>();
- ReplaceNode(tokenNode, emptyStatement);
- emptyStatement->mTrailingSemicolon = tokenNode;
- return emptyStatement;
- }
- else if (token == BfToken_Break)
- {
- auto breakStmt = mAlloc->Alloc<BfBreakStatement>();
- ReplaceNode(tokenNode, breakStmt);
- breakStmt->mBreakNode = tokenNode;
- if (auto label = BfNodeDynCast<BfIdentifierNode>(mVisitorPos.GetNext()))
- {
- MEMBER_SET(breakStmt, mLabel, label);
- mVisitorPos.MoveNext();
- }
- else if (auto tokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if (tokenNode->GetToken() == BfToken_Mixin)
- {
- MEMBER_SET(breakStmt, mLabel, tokenNode);
- mVisitorPos.MoveNext();
- }
- }
- return breakStmt;
- }
- else if (token == BfToken_Continue)
- {
- auto continueStmt = mAlloc->Alloc<BfContinueStatement>();
- ReplaceNode(tokenNode, continueStmt);
- continueStmt->mContinueNode = tokenNode;
- if (auto label = BfNodeDynCast<BfIdentifierNode>(mVisitorPos.GetNext()))
- {
- MEMBER_SET(continueStmt, mLabel, label);
- mVisitorPos.MoveNext();
- }
- else if (auto tokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if (tokenNode->GetToken() == BfToken_Mixin)
- {
- MEMBER_SET(continueStmt, mLabel, tokenNode);
- mVisitorPos.MoveNext();
- }
- }
- return continueStmt;
- }
- else if (token == BfToken_Fallthrough)
- {
- auto fallthroughStmt = mAlloc->Alloc<BfFallthroughStatement>();
- ReplaceNode(tokenNode, fallthroughStmt);
- fallthroughStmt->mFallthroughToken = tokenNode;
- if (auto label = BfNodeDynCast<BfIdentifierNode>(mVisitorPos.GetNext()))
- {
- MEMBER_SET(fallthroughStmt, mLabel, label);
- mVisitorPos.MoveNext();
- }
- else if (auto tokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if (tokenNode->GetToken() == BfToken_Mixin)
- {
- MEMBER_SET(fallthroughStmt, mLabel, tokenNode);
- mVisitorPos.MoveNext();
- }
- }
- return fallthroughStmt;
- }
- else if (token == BfToken_For)
- {
- return CreateForStatement(node);
- }
- else if (token == BfToken_Using)
- {
- return CreateUsingStatement(node);
- }
- else if (token == BfToken_While)
- {
- return CreateWhileStatement(node);
- }
- else if (token == BfToken_Do)
- {
- bool isRepeat = false;
- auto checkNode = mVisitorPos.Get(mVisitorPos.mReadPos + 2);
- auto checkToken = BfNodeDynCast<BfTokenNode>(checkNode);
- if ((checkToken != NULL) && (checkToken->mToken == BfToken_While))
- {
- // Check to see if it's a 'do {} while (...);' or an indepent 'while' statement
- int checkIdx = mVisitorPos.mReadPos + 3;
- int openCount = 0;
- while (true)
- {
- auto checkNode = mVisitorPos.Get(checkIdx);
- if (checkNode == NULL)
- break;
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(checkNode))
- {
- if (tokenNode->mToken == BfToken_LParen)
- {
- if ((openCount == 0) && (checkIdx != mVisitorPos.mReadPos + 3))
- break;
- openCount++;
- }
- else if (tokenNode->mToken == BfToken_RParen)
- {
- openCount--;
- if (openCount < 0)
- break;
- }
- else if (tokenNode->mToken == BfToken_Semicolon)
- {
- isRepeat = true;
- break;
- }
- else if (openCount == 0)
- break;
- }
- else
- {
- if (openCount == 0)
- break;
- }
- checkIdx++;
- }
- }
- if (isRepeat)
- return CreateRepeatStatement(node);
- else
- return CreateDoStatement(node);
- }
- else if (token == BfToken_Repeat)
- {
- return CreateRepeatStatement(node);
- }
- else if (token == BfToken_Return)
- {
- auto returnStmt = mAlloc->Alloc<BfReturnStatement>();
- ReplaceNode(node, returnStmt);
- MEMBER_SET(returnStmt, mReturnToken, tokenNode);
- auto nextNode = mVisitorPos.GetNext();
- if (!IsSemicolon(nextNode))
- {
- auto expr = CreateExpressionAfter(returnStmt);
- MEMBER_SET_CHECKED(returnStmt, mExpression, expr);
- }
- return returnStmt;
- }
- else if (token == BfToken_Delete)
- {
- auto deleteStmt = mAlloc->Alloc<BfDeleteStatement>();
- ReplaceNode(node, deleteStmt);
- MEMBER_SET(deleteStmt, mDeleteToken, tokenNode);
- auto nextNode = mVisitorPos.GetNext();
- if ((tokenNode = BfNodeDynCast<BfTokenNode>(nextNode)))
- {
- if (tokenNode->GetToken() == BfToken_Colon)
- {
- MEMBER_SET(deleteStmt, mTargetTypeToken, tokenNode);
- mVisitorPos.MoveNext();
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if (tokenNode->mToken == BfToken_Append)
- {
- MEMBER_SET(deleteStmt, mAllocExpr, tokenNode);
- mVisitorPos.MoveNext();
- }
- }
- if (deleteStmt->mAllocExpr == NULL)
- {
- auto allocExpr = CreateExpressionAfter(deleteStmt, (CreateExprFlags)(CreateExprFlags_NoCast | CreateExprFlags_ExitOnParenExpr));
- if (allocExpr != NULL)
- {
- MEMBER_SET(deleteStmt, mAllocExpr, allocExpr);
- }
- }
- }
- }
- nextNode = mVisitorPos.GetNext();
- if ((tokenNode = BfNodeDynCast<BfTokenNode>(nextNode)))
- {
- if (tokenNode->mToken == BfToken_LBracket)
- {
- mVisitorPos.MoveNext();
- auto attrib = CreateAttributeDirective(tokenNode);
- if (attrib == NULL)
- return deleteStmt;
- MEMBER_SET(deleteStmt, mAttributes, attrib);
- }
- }
- auto expr = CreateExpressionAfter(deleteStmt);
- MEMBER_SET_CHECKED(deleteStmt, mExpression, expr);
- return deleteStmt;
- }
- else if (token == BfToken_Throw)
- {
- auto throwStmt = mAlloc->Alloc<BfThrowStatement>();
- ReplaceNode(node, throwStmt);
- MEMBER_SET(throwStmt, mThrowToken, tokenNode);
- auto expr = CreateExpressionAfter(throwStmt);
- MEMBER_SET_CHECKED(throwStmt, mExpression, expr);
- return throwStmt;
- }
- else if (token == BfToken_If)
- {
- subCreateStmtFlags = (CreateStmtFlags)(createStmtFlags & (CreateStmtFlags_FindTrailingSemicolon));
- auto ifStmt = mAlloc->Alloc<BfIfStatement>();
- ReplaceNode(node, ifStmt);
- MEMBER_SET(ifStmt, mIfToken, tokenNode);
- tokenNode = ExpectTokenAfter(ifStmt, BfToken_LParen);
- MEMBER_SET_CHECKED(ifStmt, mOpenParen, tokenNode);
- auto condExpr = CreateExpressionAfter(ifStmt, CreateExprFlags_AllowVariableDecl);
- MEMBER_SET_CHECKED(ifStmt, mCondition, condExpr);
- tokenNode = ExpectTokenAfter(ifStmt, BfToken_RParen);
- MEMBER_SET_CHECKED(ifStmt, mCloseParen, tokenNode);
- auto trueStmt = CreateStatementAfter(ifStmt, subCreateStmtFlags);
- MEMBER_SET_CHECKED(ifStmt, mTrueStatement, trueStmt);
- auto nextNode = mVisitorPos.GetNext();
- tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if ((tokenNode != NULL) && (tokenNode->GetToken() == BfToken_Else))
- {
- MEMBER_SET(ifStmt, mElseToken, tokenNode);
- mVisitorPos.MoveNext();
- auto falseStmt = CreateStatementAfter(ifStmt, (CreateStmtFlags)(subCreateStmtFlags | CreateStmtFlags_CheckStack));
- MEMBER_SET_CHECKED(ifStmt, mFalseStatement, falseStmt);
- }
- return ifStmt;
- }
- else if (token == BfToken_Switch)
- {
- return CreateSwitchStatement(tokenNode);
- }
- else if (token == BfToken_Defer)
- {
- auto deferStmt = mAlloc->Alloc<BfDeferStatement>();
- ReplaceNode(tokenNode, deferStmt);
- deferStmt->mDeferToken = tokenNode;
- auto nextNode = mVisitorPos.GetNext();
- if (auto nextTokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (nextTokenNode->GetToken() == BfToken_Colon)
- {
- MEMBER_SET(deferStmt, mColonToken, nextTokenNode);
- mVisitorPos.MoveNext();
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if ((nextToken->GetToken() == BfToken_Colon) || (nextToken->GetToken() == BfToken_Mixin))
- {
- MEMBER_SET(deferStmt, mScopeName, nextToken);
- mVisitorPos.MoveNext();
- }
- }
- else if (auto identifier = BfNodeDynCast<BfIdentifierNode>(mVisitorPos.GetNext()))
- {
- MEMBER_SET(deferStmt, mScopeName, identifier);
- mVisitorPos.MoveNext();
- }
- if (deferStmt->mScopeName == NULL)
- {
- FailAfter("Expected scope name", deferStmt);
- }
- }
- else if (nextTokenNode->GetToken() == BfToken_ColonColon)
- {
- MEMBER_SET(deferStmt, mColonToken, nextTokenNode);
- mVisitorPos.MoveNext();
- }
- else if (nextTokenNode->GetToken() == BfToken_LParen)
- {
- mPassInstance->Warn(0, "Syntax deprecated", nextTokenNode);
- MEMBER_SET(deferStmt, mOpenParen, nextTokenNode);
- mVisitorPos.MoveNext();
- nextTokenNode = ExpectTokenAfter(deferStmt, BfToken_Scope);
- MEMBER_SET_CHECKED(deferStmt, mScopeToken, nextTokenNode);
- nextTokenNode = ExpectTokenAfter(deferStmt, BfToken_RParen);
- MEMBER_SET_CHECKED(deferStmt, mCloseParen, nextTokenNode);
- }
- }
- if (auto nextTokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if (nextTokenNode->GetToken() == BfToken_LBracket)
- {
- auto bindNode = mAlloc->Alloc<BfDeferBindNode>();
- ReplaceNode(nextTokenNode, bindNode);
- MEMBER_SET(bindNode, mOpenBracket, nextTokenNode);
- mVisitorPos.MoveNext();
- BfDeferredAstSizedArray<BfIdentifierNode*> params(bindNode->mParams, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(bindNode->mCommas, mAlloc);
- for (int paramIdx = 0; true; paramIdx++)
- {
- bool isRBracket = false;
- auto nextNode = mVisitorPos.GetNext();
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- isRBracket = tokenNode->GetToken() == BfToken_RBracket;
- if (!isRBracket)
- {
- auto nameIdentifier = ExpectIdentifierAfter(bindNode, "parameter name");
- if (nameIdentifier == NULL)
- break;
- MoveNode(nameIdentifier, bindNode);
- params.push_back(nameIdentifier);
- }
- tokenNode = ExpectTokenAfter(bindNode, BfToken_Comma, BfToken_RBracket);
- if (tokenNode == NULL)
- return deferStmt;
- if (tokenNode->GetToken() == BfToken_RBracket)
- {
- MEMBER_SET(bindNode, mCloseBracket, tokenNode);
- break;
- }
- MoveNode(tokenNode, bindNode);
- commas.push_back(tokenNode);
- }
- MEMBER_SET(deferStmt, mBind, bindNode);
- }
- }
- BfAstNode* targetNode = CreateStatementAfter(deferStmt);
- if (targetNode != NULL)
- {
- BfAstNode* innerTarget = targetNode;
- if (auto exprStmt = BfNodeDynCast<BfExpressionStatement>(innerTarget))
- innerTarget = exprStmt->mExpression;
- if (deferStmt->mBind != NULL)
- {
- if (!innerTarget->IsA<BfBlock>())
- {
- Fail("Only blocks are allowed when defer binding is used", targetNode);
- }
- }
- else
- {
- if ((!innerTarget->IsA<BfInvocationExpression>()) &&
- (!innerTarget->IsA<BfBlock>()) &&
- (!innerTarget->IsA<BfDeleteStatement>()))
- {
- Fail("Only invocation expressions, statement blocks, or deletes are allowed", targetNode);
- }
- }
- MEMBER_SET(deferStmt, mTargetNode, targetNode);
- }
- return deferStmt;
- }
- else if (token == BfToken_Comma)
- {
- BfAstNode* prevVarDecl = mVisitorPos.Get(mVisitorPos.mWritePos - 1);
- if (mLastBlockNode != NULL)
- prevVarDecl = mLastBlockNode;
- if (auto exprStmt = BfNodeDynCast<BfExpressionStatement>(prevVarDecl))
- {
- continuingVariable = BfNodeDynCast<BfVariableDeclaration>(exprStmt->mExpression);
- }
- }
- else if ((token == BfToken_Const) || (token == BfToken_ReadOnly) || (token == BfToken_Static))
- {
- auto flags = (CreateStmtFlags)(CreateStmtFlags_FindTrailingSemicolon | CreateStmtFlags_ForceVariableDecl);
- if (token == BfToken_Static)
- flags = (CreateStmtFlags)(flags | CreateStmtFlags_AllowLocalFunction);
- auto stmt = CreateStatementAfter(tokenNode, flags);
- if (auto exprStmt = BfNodeDynCast<BfExpressionStatement>(stmt))
- {
- if (auto variableDecl = BfNodeDynCast<BfVariableDeclaration>(exprStmt->mExpression))
- {
- if (variableDecl->mModSpecifier != NULL)
- {
- Fail(StrFormat("'%s' already specified", BfTokenToString(variableDecl->mModSpecifier->GetToken())), variableDecl->mModSpecifier);
- }
- MEMBER_SET(variableDecl, mModSpecifier, tokenNode);
- exprStmt->SetSrcStart(tokenNode->mSrcStart);
- return stmt;
- }
- }
- if (auto localMethod = BfNodeDynCast<BfLocalMethodDeclaration>(stmt))
- {
- if (localMethod->mMethodDeclaration->mStaticSpecifier != NULL)
- {
- Fail(StrFormat("'%s' already specified", BfTokenToString(localMethod->mMethodDeclaration->mStaticSpecifier->GetToken())), localMethod->mMethodDeclaration->mStaticSpecifier);
- }
- MEMBER_SET(localMethod->mMethodDeclaration, mStaticSpecifier, tokenNode);
- localMethod->SetSrcStart(tokenNode->mSrcStart);
- return localMethod;
- }
- Fail(StrFormat("Unexpected '%s' specifier", BfTokenToString(tokenNode->GetToken())), tokenNode);
- return stmt;
- }
- else if (token == BfToken_Volatile)
- {
- Fail("Cannot create volatile local variables", tokenNode);
- return NULL;
- }
- else if (token == BfToken_Asm)
- {
- return CreateInlineAsmStatement(node);
- }
- else if (token == BfToken_Mixin)
- {
- auto methodDecl = mAlloc->Alloc<BfMethodDeclaration>();
- BfDeferredAstSizedArray<BfParameterDeclaration*> params(methodDecl->mParams, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(methodDecl->mCommas, mAlloc);
- ReplaceNode(tokenNode, methodDecl);
- methodDecl->mDocumentation = FindDocumentation(methodDecl);
- methodDecl->mMixinSpecifier = tokenNode;
- auto nameNode = ExpectIdentifierAfter(methodDecl);
- if (nameNode != NULL)
- {
- MEMBER_SET(methodDecl, mNameNode, nameNode);
- ParseMethod(methodDecl, ¶ms, &commas, true);
- }
- auto localMethodDecl = mAlloc->Alloc<BfLocalMethodDeclaration>();
- ReplaceNode(methodDecl, localMethodDecl);
- localMethodDecl->mMethodDeclaration = methodDecl;
- return localMethodDecl;
- }
- else if (token == BfToken_LBracket)
- {
- return CreateAttributedStatement(tokenNode, createStmtFlags);
- }
- }
- if (auto identifier = BfNodeDynCast<BfIdentifierNode>(node))
- {
- node = CompactQualifiedName(identifier);
- }
- bool isLocalVariable = false;
- auto nextNode = mVisitorPos.GetNext();
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (nextToken->GetToken() == BfToken_Colon)
- {
- auto nameIdentifier = BfNodeDynCast<BfIdentifierNode>(node);
- if (nameIdentifier != NULL)
- {
- BfLabelNode* labelNode = mAlloc->Alloc<BfLabelNode>();
- ReplaceNode(nameIdentifier, labelNode);
- labelNode->mLabel = nameIdentifier;
- mVisitorPos.MoveNext();
- MEMBER_SET(labelNode, mColonToken, nextToken);
- BfAstNode* stmt = NULL;
- auto nextNode = mVisitorPos.GetNext();
- if (nextNode != NULL)
- {
- mVisitorPos.MoveNext();
- stmt = DoCreateStatement(nextNode);
- if (auto labelableStmt = BfNodeDynCast<BfLabelableStatement>(stmt))
- {
- MEMBER_SET(labelableStmt, mLabelNode, labelNode);
- return labelableStmt;
- }
- if (auto block = BfNodeDynCast<BfBlock>(stmt))
- {
- auto labeledBlock = mAlloc->Alloc<BfLabeledBlock>();
- ReplaceNode(block, labeledBlock);
- labeledBlock->mBlock = block;
- MEMBER_SET(labeledBlock, mLabelNode, labelNode);
- return labeledBlock;
- }
- }
- Fail("Label must appear before a labelable statement (if, for, do, while, switch, block)", labelNode);
- AddErrorNode(labelNode);
- return stmt;
- }
- }
- }
- int typeRefEndNode = -1;
- bool isTuple = false;
- if (IsTypeReference(node, BfToken_None, -1, &typeRefEndNode, NULL, NULL, &isTuple))
- isLocalVariable = true;
- if ((isLocalVariable) && (isTuple))
- {
- if (typeRefEndNode != -1)
- {
- // When we're typing something like "(a, )" ... don't make that a type ref yet because it could be "(a, b) = " where
- // we're typing a tuple value rather than a tuple tpye ref
- auto checkNode = mVisitorPos.Get(typeRefEndNode);
- if (checkNode == NULL)
- isLocalVariable = false;
- }
- }
- if (nextNode == NULL)
- {
- // Treat ending identifier as just an identifier (could be block result)
- isLocalVariable = false;
- }
- if ((isLocalVariable) && (typeRefEndNode != -1) && (continuingVariable == NULL) && ((createStmtFlags & CreateStmtFlags_AllowLocalFunction) != 0))
- {
- BfTokenNode* nextToken = BfNodeDynCast<BfTokenNode>(node);
- if ((nextToken == NULL) ||
- ((nextToken->GetToken() != BfToken_Delegate) && (nextToken->GetToken() != BfToken_Function)))
- {
- auto afterTypeRefNode = mVisitorPos.Get(typeRefEndNode);
- if (auto nameIdentifier = BfNodeDynCast<BfIdentifierNode>(afterTypeRefNode))
- {
- auto nextNextNode = mVisitorPos.Get(typeRefEndNode + 1);
- if (auto afterNameToken = BfNodeDynCast<BfTokenNode>(nextNextNode))
- {
- bool isLocalMethod = (afterNameToken->GetToken() == BfToken_LParen) || (afterNameToken->GetToken() == BfToken_LChevron);
- if (isLocalMethod)
- {
- int prevReadPos = mVisitorPos.mReadPos;
- mVisitorPos.mReadPos = typeRefEndNode;
- isLocalMethod = IsLocalMethod(nameIdentifier);
- mVisitorPos.mReadPos = prevReadPos;
- }
- if (isLocalMethod)
- {
- auto typeRef = CreateTypeRef(node);
- if (mVisitorPos.GetNext() != nameIdentifier)
- isLocalMethod = false;
- else
- {
- int prevReadPos = mVisitorPos.mReadPos;
- mVisitorPos.MoveNext();
- isLocalMethod = IsLocalMethod(nameIdentifier);
- if (!isLocalMethod)
- mVisitorPos.mReadPos = prevReadPos;
- }
- if (!isLocalMethod)
- {
- // TypeRef didn't match what we expected, just set it up as a variable declaration
- auto variableDeclaration = mAlloc->Alloc<BfVariableDeclaration>();
- ReplaceNode(typeRef, variableDeclaration);
- variableDeclaration->mTypeRef = typeRef;
- return variableDeclaration;
- }
- auto methodDecl = mAlloc->Alloc<BfMethodDeclaration>();
- ReplaceNode(typeRef, methodDecl);
- methodDecl->mDocumentation = FindDocumentation(methodDecl);
- methodDecl->mReturnType = typeRef;
- CheckMultiuseAttributeTypeRef(methodDecl->mReturnType);
- BfDeferredAstSizedArray<BfParameterDeclaration*> params(methodDecl->mParams, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(methodDecl->mCommas, mAlloc);
- MEMBER_SET(methodDecl, mNameNode, nameIdentifier);
- if (afterNameToken->GetToken() == BfToken_LChevron)
- {
- auto genericParams = CreateGenericParamsDeclaration(afterNameToken);
- if (genericParams != NULL)
- {
- MEMBER_SET(methodDecl, mGenericParams, genericParams);
- }
- }
- ParseMethod(methodDecl, ¶ms, &commas, true);
- auto localMethodDecl = mAlloc->Alloc<BfLocalMethodDeclaration>();
- ReplaceNode(methodDecl, localMethodDecl);
- localMethodDecl->mMethodDeclaration = methodDecl;
- return localMethodDecl;
- }
- }
- }
- else if (afterTypeRefNode == NULL)
- isLocalVariable = false;
- else if (auto tokenNode = BfNodeDynCast<BfTokenNode>(afterTypeRefNode))
- {
- if (tokenNode->mToken != BfToken_LParen)
- isLocalVariable = false; // May be tuple
- }
- }
- }
- if ((isLocalVariable) || (continuingVariable != NULL))
- {
- auto variableDeclaration = mAlloc->Alloc<BfVariableDeclaration>();
- BfTypeReference* typeRef = NULL;
- if (continuingVariable != NULL)
- {
- typeRef = continuingVariable->mTypeRef;
- variableDeclaration->mModSpecifier = continuingVariable->mModSpecifier;
- ReplaceNode(node, variableDeclaration);
- variableDeclaration->mPrecedingComma = (BfTokenNode*)node;
- }
- else
- {
- typeRef = CreateTypeRef(node);
- if (typeRef == NULL)
- return NULL;
- ReplaceNode(typeRef, variableDeclaration);
- }
- variableDeclaration->mTypeRef = typeRef;
- BfAstNode* variableNameNode = NULL;
- nextNode = mVisitorPos.GetNext();
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (tokenNode->GetToken() == BfToken_LParen)
- {
- mVisitorPos.mReadPos++;
- variableNameNode = CreateTupleExpression(tokenNode);
- }
- }
- if (variableNameNode == NULL)
- {
- auto checkToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(mVisitorPos.mReadPos + 2));
- if ((checkToken != NULL) && (checkToken->mToken == BfToken_Dot))
- {
- FailAfter("Expected variable name", variableDeclaration);
- }
- else
- variableNameNode = ExpectIdentifierAfter(variableDeclaration, "variable name");
- }
- if (variableNameNode == NULL)
- return variableDeclaration;
- bool isValidFinish = false;
- BfTokenNode* tokenNode;
- if ((tokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext())))
- {
- int token = tokenNode->GetToken();
- if ((token == BfToken_AssignEquals) || (token == BfToken_Semicolon) || (token == BfToken_Comma))
- isValidFinish = true;
- }
- /*if (!isValidFinish)
- {
- if (auto nextIdentifier = BfNodeDynCast<BfIdentifierNode>(mVisitorPos.GetNext()))
- {
- if (auto nextNextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(mVisitorPos.mReadPos + 2)))
- {
- if ((nextNextToken->GetToken() == BfToken_LParen) || (nextNextToken->GetToken() == BfToken_LChevron))
- {
- // It's less destructive to not consume the identifier we see as the name, because it may not be. This handles the case
- // where we're typing some stuff before a local method declaration. Kindof a corner case...
- Fail("Unexpected type", typeRef);
- mVisitorPos.mReadPos--;
- return variableDeclaration;
- }
- }
- }
- }*/
- // Is a local variable?
- tokenNode = ExpectTokenAfter(variableNameNode, BfToken_AssignEquals, BfToken_Semicolon, BfToken_Comma);
- variableDeclaration->mNameNode = variableNameNode;
- MoveNode(variableNameNode, variableDeclaration);
- if (tokenNode == NULL)
- return variableDeclaration;
- if (tokenNode->GetToken() == BfToken_AssignEquals)
- {
- MEMBER_SET(variableDeclaration, mEqualsNode, tokenNode);
- if (variableDeclaration->mInitializer == NULL)
- variableDeclaration->mInitializer = CreateExpressionAfter(variableDeclaration, (CreateExprFlags)(createStmtFlags & CreateStmtFlags_To_CreateExprFlags_Mask));
- if (variableDeclaration->mInitializer == NULL)
- return variableDeclaration;
- MoveNode(variableDeclaration->mInitializer, variableDeclaration);
- }
- else
- mVisitorPos.mReadPos--; // Backtrack to the semicolon or comma
- return variableDeclaration;
- }
- if ((createStmtFlags & CreateStmtFlags_ForceVariableDecl) != 0)
- {
- Fail("Expected local variable declaration", node);
- return NULL;
- }
- // Must be an expression. Always set CreateExprFlags_NoCaseExpr, to keep ending statements in a switch case to look like case expressions
- CreateExprFlags exprFlags = (CreateExprFlags)(createStmtFlags & CreateStmtFlags_To_CreateExprFlags_Mask);
- if ((createStmtFlags & CreateStmtFlags_AllowUnterminatedExpression) == 0)
- exprFlags = (CreateExprFlags)(exprFlags | CreateExprFlags_NoCaseExpr);
- auto expr = CreateExpression(node, exprFlags);
- if (expr == NULL)
- return NULL;
- bool isOkUnary = false;
- if (auto unaryOperatorExpr = BfNodeDynCast<BfUnaryOperatorExpression>(expr))
- {
- isOkUnary =
- (unaryOperatorExpr->mOp == BfUnaryOp_Increment) ||
- (unaryOperatorExpr->mOp == BfUnaryOp_PostIncrement) ||
- (unaryOperatorExpr->mOp == BfUnaryOp_Decrement) ||
- (unaryOperatorExpr->mOp == BfUnaryOp_PostDecrement);
- if (unaryOperatorExpr->mOp == BfUnaryOp_Out)
- {
- unaryOperatorExpr->mOp = BfUnaryOp_Ref;
- Fail("Cannot use 'out' in this context", unaryOperatorExpr);
- }
- }
- if ((!mPrevStmtHadError) && (!mStmtHasError))
- {
- nextNode = mVisitorPos.GetNext();
- if (nextNode != NULL)
- {
- if (!isOkUnary)
- expr->VerifyIsStatement(mPassInstance);
- }
- }
- return expr;
- }
- // This is conservative - it doesn't HAVE to return true, but in some cases may cause a parsing error if the nodes
- // can be consumed as a statement rather than an expression. We must be more careful about not returning 'true'
- // for something that can only be interpreted as a statement, however.
- bool BfReducer::IsTerminatingExpression(BfAstNode* node)
- {
- int parenDepth = 0;
- int chevronDepth = 0;
- int readIdx = mVisitorPos.mReadPos;
- bool prevWasValue = false;
- BfTokenNode* prevTokenNode = NULL;
- while (true)
- {
- auto node = mVisitorPos.Get(readIdx);
- if (node == NULL)
- break;
- auto tokenNode = BfNodeDynCast<BfTokenNode>(node);
- if (tokenNode != NULL)
- {
- switch (tokenNode->GetToken())
- {
- case BfToken_AssignEquals:
- if (parenDepth == 0)
- return false;
- break;
- case BfToken_LParen:
- chevronDepth = 0;
- parenDepth++;
- break;
- case BfToken_RParen:
- chevronDepth = 0;
- parenDepth--;
- break;
- case BfToken_LChevron:
- chevronDepth++;
- break;
- case BfToken_RChevron:
- // If we find a < and > that are not separated by parens, that's a generic, which must be a
- // variable decl if it's not in parens
- if ((parenDepth == 0) && (chevronDepth > 0))
- return false;
- chevronDepth--;
- break;
- case BfToken_RDblChevron:
- chevronDepth--;
- break;
- case BfToken_Comma:
- if (parenDepth == 0)
- return false;
- break;
- case BfToken_As:
- case BfToken_AllocType:
- case BfToken_Append:
- case BfToken_Default:
- case BfToken_Is:
- case BfToken_Scope:
- case BfToken_New:
- case BfToken_RetType:
- case BfToken_Nullable:
- case BfToken_SizeOf:
- case BfToken_This:
- case BfToken_TypeOf:
- case BfToken_LessEquals:
- case BfToken_GreaterEquals:
- case BfToken_LBracket:
- case BfToken_RBracket:
- case BfToken_Colon:
- case BfToken_Dot:
- case BfToken_DotDot:
- case BfToken_QuestionDot:
- case BfToken_QuestionLBracket:
- case BfToken_Plus:
- case BfToken_Minus:
- case BfToken_DblPlus:
- case BfToken_DblMinus:
- case BfToken_Star:
- case BfToken_ForwardSlash:
- case BfToken_Modulus:
- case BfToken_Ampersand:
- case BfToken_At:
- case BfToken_DblAmpersand:
- case BfToken_Bar:
- case BfToken_DblBar:
- case BfToken_Bang:
- case BfToken_Carat:
- case BfToken_Tilde:
- case BfToken_Question:
- case BfToken_DblQuestion:
- case BfToken_Arrow:
- case BfToken_FatArrow:
- // Allow these
- break;
- case BfToken_Semicolon:
- return false;
- default:
- // Disallow everything else
- return false;
- }
- }
- if ((node->IsExact<BfIdentifierNode>()) ||
- (node->IsExact<BfQualifiedNameNode>()) ||
- (node->IsExact<BfMemberReferenceExpression>()) ||
- (node->IsExact<BfLiteralExpression>()))
- {
- if (prevWasValue)
- {
- // Two values in a row cannot be a valid expression
- return false;
- }
- prevWasValue = true;
- }
- else
- {
- prevWasValue = false;
- }
- if (auto block = BfNodeDynCastExact<BfBlock>(node))
- {
- // Local method decl
- if ((parenDepth == 0) && (prevTokenNode != NULL) && (prevTokenNode->GetToken() == BfToken_RParen))
- return false;
- }
- prevTokenNode = tokenNode;
- readIdx++;
- }
- int outEndNode = 0;
- bool couldBeExpr = false;
- if (IsTypeReference(node, BfToken_None, -1, &outEndNode, &couldBeExpr))
- {
- if (outEndNode == mVisitorPos.mTotalSize - 1)
- {
- if (auto name = BfNodeDynCast<BfIdentifierNode>(mVisitorPos.Get(outEndNode)))
- {
- auto beforeNameToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(outEndNode - 1));
- // We treat "a*b" as a multiply rather than a variable declaration
- if ((beforeNameToken == NULL) || (beforeNameToken->GetToken() != BfToken_Star))
- {
- return false;
- }
- }
- }
- }
- return true;
- }
- BfAstNode* BfReducer::CreateStatement(BfAstNode* node, CreateStmtFlags createStmtFlags)
- {
- if (!AssertCurrentNode(node))
- return NULL;
- if ((createStmtFlags & CreateStmtFlags_CheckStack) != 0)
- {
- BP_ZONE("CreateStatement.CheckStack");
- StackHelper stackHelper;
- if (!stackHelper.CanStackExpand(64 * 1024))
- {
- BfAstNode* result = NULL;
- if (!stackHelper.Execute([&]()
- {
- result = CreateStatement(node, createStmtFlags);
- }))
- {
- Fail("Statement too complex to parse", node);
- }
- return result;
- }
- }
- if ((createStmtFlags & CreateStmtFlags_AllowUnterminatedExpression) != 0)
- {
- if (IsTerminatingExpression(node))
- {
- mPrevStmtHadError = false;
- // Must be an expression. Always set CreateExprFlags_NoCaseExpr, to keep ending statements in a switch case to look like case expressions
- auto expr = CreateExpression(node, (CreateExprFlags)((createStmtFlags & CreateStmtFlags_To_CreateExprFlags_Mask) | CreateExprFlags_NoCaseExpr));
- if (expr != NULL)
- {
- auto nextNode = mVisitorPos.GetNext();
- if (nextNode != NULL)
- FailAfter("Semicolon expected", expr);
- }
- return expr;
- }
- }
- mStmtHasError = false;
- auto stmtNode = DoCreateStatement(node, createStmtFlags);
- mPrevStmtHadError = mStmtHasError;
- if (stmtNode == NULL)
- return NULL;
- auto origStmtNode = stmtNode;
- if (stmtNode->IsA<BfBlock>())
- return stmtNode;
- auto nextNode = mVisitorPos.GetNext();
- if (auto expr = BfNodeDynCast<BfExpression>(stmtNode))
- {
- if (((createStmtFlags & CreateStmtFlags_AllowUnterminatedExpression) != 0) && (nextNode == NULL))
- return expr;
- auto stmt = mAlloc->Alloc<BfExpressionStatement>();
- ReplaceNode(expr, stmt);
- stmt->mExpression = expr;
- stmtNode = stmt;
- }
- if (auto stmt = BfNodeDynCast<BfStatement>(stmtNode))
- {
- if ((stmt->IsMissingSemicolon()) && ((createStmtFlags & CreateStmtFlags_FindTrailingSemicolon) != 0) && (!stmt->IsA<BfEmptyStatement>()))
- {
- if (!IsSemicolon(nextNode))
- {
- bool doWarn = false;
- // Why did we have this BfIdentifierNode check? It failed to throw an error on just things like "{ a }"
- if (origStmtNode->IsA<BfRepeatStatement>())
- {
- // These do require a semicolon
- doWarn = true;
- }
- else if (/*(origStmtNode->IsA<BfIdentifierNode>()) || */(origStmtNode->IsA<BfCompoundStatement>()) || (origStmtNode->IsA<BfBlock>()))
- return stmt;
- if (origStmtNode->IsA<BfVariableDeclaration>())
- {
- // For compound variables
- auto commaToken = BfNodeDynCast<BfTokenNode>(nextNode);
- if ((commaToken != NULL) && (commaToken->GetToken() == BfToken_Comma))
- return stmt;
- }
- if (((createStmtFlags & CreateStmtFlags_AllowUnterminatedExpression) != 0) && (origStmtNode->IsA<BfExpression>()) && (nextNode == NULL))
- return stmt;
- BfError* error;
- if (doWarn)
- error = mPassInstance->WarnAfterAt(0, "Semicolon expected", node->GetSourceData(), stmt->GetSrcEnd() - 1);
- else
- error = mPassInstance->FailAfterAt("Semicolon expected", node->GetSourceData(), stmt->GetSrcEnd() - 1);
- if ((error != NULL) && (mSource != NULL))
- error->mProject = mSource->mProject;
- mPrevStmtHadError = true;
- return stmt;
- }
- if ((!stmt->IsA<BfBlock>()) && (!stmt->IsA<BfIdentifierNode>()))
- {
- mVisitorPos.MoveNext();
- MEMBER_SET(stmt, mTrailingSemicolon, (BfTokenNode*)nextNode);
- }
- }
- }
- return stmtNode;
- }
- BfAstNode* BfReducer::CreateStatementAfter(BfAstNode* node, CreateStmtFlags createStmtFlags)
- {
- if (!AssertCurrentNode(node))
- return NULL;
- auto nextNode = mVisitorPos.GetNext();
- if (nextNode == NULL)
- {
- FailAfter("Expected statement", node);
- return NULL;
- }
- mVisitorPos.MoveNext();
- BfAstNode* stmt = CreateStatement(nextNode, createStmtFlags);
- if (stmt == NULL)
- {
- // Nope, didn't handle it
- mVisitorPos.mReadPos--;
- }
- return stmt;
- }
- bool BfReducer::IsExtendedTypeName(BfIdentifierNode* identifierNode)
- {
- auto nextNode = mVisitorPos.GetNext();
- if (nextNode == NULL)
- return false;
- auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if (tokenNode == NULL)
- return false;
- int token = tokenNode->GetToken();
- return ((token == BfToken_Star) ||
- (token == BfToken_Question) ||
- (token == BfToken_Dot) ||
- (token == BfToken_LChevron) ||
- (token == BfToken_LBracket));
- }
- static String TypeToString(BfTypeReference* typeRef)
- {
- if (typeRef == NULL)
- return "null";
- if (auto qualifiedTypeRef = BfNodeDynCast<BfQualifiedTypeReference>(typeRef))
- return "(" + TypeToString(qualifiedTypeRef->mLeft) + " . " + TypeToString(qualifiedTypeRef->mRight) + ")";
- if (auto genericTypeInstanceRef = BfNodeDynCast<BfGenericInstanceTypeRef>(typeRef))
- return TypeToString(genericTypeInstanceRef->mElementType) + "<...>";
- return typeRef->ToString();
- }
- BfTypeReference* BfReducer::DoCreateNamedTypeRef(BfIdentifierNode* identifierNode)
- {
- if (auto qualifiedNameNode = BfNodeDynCast<BfQualifiedNameNode>(identifierNode))
- {
- auto qualifiedTypeRef = mAlloc->Alloc<BfQualifiedTypeReference>();
- ReplaceNode(identifierNode, qualifiedTypeRef);
- MoveNode(qualifiedNameNode->mLeft, qualifiedTypeRef);
- auto leftTypeRef = DoCreateNamedTypeRef(qualifiedNameNode->mLeft);
- MEMBER_SET(qualifiedTypeRef, mLeft, leftTypeRef);
- MEMBER_SET(qualifiedTypeRef, mDot, qualifiedNameNode->mDot);
- MoveNode(qualifiedNameNode->mRight, qualifiedNameNode);
- auto rightTypeRef = DoCreateNamedTypeRef(qualifiedNameNode->mRight);
- MEMBER_SET(qualifiedTypeRef, mRight, rightTypeRef);
- return qualifiedTypeRef;
- }
- else
- {
- auto namedTypeRef = mAlloc->Alloc<BfNamedTypeReference>();
- namedTypeRef->mNameNode = identifierNode;
- ReplaceNode(identifierNode, namedTypeRef);
- namedTypeRef->SetTriviaStart(identifierNode->GetTriviaStart());
- return namedTypeRef;
- }
- }
- BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefFlags createTypeRefFlags, int endNode)
- {
- if (!AssertCurrentNode(firstNode))
- return NULL;
- bool parseArrayBracket = (createTypeRefFlags & CreateTypeRefFlags_NoParseArrayBrackets) == 0;
- auto identifierNode = BfNodeDynCast<BfIdentifierNode>(firstNode);
- if (identifierNode == NULL)
- {
- if (auto memberReferenceExpression = BfNodeDynCast<BfMemberReferenceExpression>(firstNode))
- {
- SetAndRestoreValue<bool> prevSkipCurrentNodeAssert(mSkipCurrentNodeAssert, true);
- auto qualifiedTypeRef = mAlloc->Alloc<BfQualifiedTypeReference>();
- ReplaceNode(firstNode, qualifiedTypeRef);
- BF_ASSERT(memberReferenceExpression->mTarget != NULL);
- if (memberReferenceExpression->mTarget != NULL)
- {
- MoveNode(memberReferenceExpression->mTarget, qualifiedTypeRef);
- auto leftTypeRef = DoCreateTypeRef(memberReferenceExpression->mTarget);
- if (leftTypeRef == NULL)
- return NULL;
- MEMBER_SET(qualifiedTypeRef, mLeft, leftTypeRef);
- }
- MEMBER_SET(qualifiedTypeRef, mDot, memberReferenceExpression->mDotToken);
- if (memberReferenceExpression->mDotToken->mToken == BfToken_DotDot)
- Fail("Invalid use of '..' in type reference", memberReferenceExpression->mDotToken);
- if (memberReferenceExpression->mMemberName != NULL)
- {
- MoveNode(memberReferenceExpression->mMemberName, memberReferenceExpression);
- auto rightTypeRef = DoCreateTypeRef(memberReferenceExpression->mMemberName);
- if (rightTypeRef == NULL)
- return NULL;
- MEMBER_SET(qualifiedTypeRef, mRight, rightTypeRef);
- }
- firstNode = qualifiedTypeRef;
- }
- else if (auto typeRef = BfNodeDynCast<BfTypeReference>(firstNode))
- {
- // Already a typeRef
- return typeRef;
- }
- else
- {
- bool isHandled = false;
- auto tokenNode = BfNodeDynCast<BfTokenNode>(firstNode);
- if (tokenNode != NULL)
- {
- BfToken token = tokenNode->GetToken();
- if (token == BfToken_Dot)
- {
- auto dotTypeRef = mAlloc->Alloc<BfDotTypeReference>();
- ReplaceNode(firstNode, dotTypeRef);
- dotTypeRef->mDotToken = tokenNode;
- firstNode = dotTypeRef;
- isHandled = true;
- }
- else if (token == BfToken_DotDotDot)
- {
- auto dotTypeRef = mAlloc->Alloc<BfDotTypeReference>();
- ReplaceNode(firstNode, dotTypeRef);
- dotTypeRef->mDotToken = tokenNode;
- firstNode = dotTypeRef;
- isHandled = true;
- return dotTypeRef;
- }
- else if ((token == BfToken_Star) && (mAllowTypeWildcard))
- {
- auto wildcardTypeRef = mAlloc->Alloc<BfWildcardTypeReference>();
- ReplaceNode(firstNode, wildcardTypeRef);
- wildcardTypeRef->mWildcardToken = tokenNode;
- return wildcardTypeRef;
- }
- else if ((token == BfToken_Var) || (token == BfToken_Let))
- {
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if ((nextToken->GetToken() == BfToken_Ref) || (nextToken->GetToken() == BfToken_Mut))
- {
- auto varTypeRef = mAlloc->Alloc<BfVarRefTypeReference>();
- ReplaceNode(firstNode, varTypeRef);
- varTypeRef->mVarToken = tokenNode;
- MEMBER_SET(varTypeRef, mRefToken, nextToken);
- mVisitorPos.MoveNext();
- return varTypeRef;
- }
- }
- if (token == BfToken_Var)
- {
- auto varTypeRef = mAlloc->Alloc<BfVarTypeReference>();
- ReplaceNode(firstNode, varTypeRef);
- varTypeRef->mVarToken = tokenNode;
- return varTypeRef;
- }
- else
- {
- auto letTypeRef = mAlloc->Alloc<BfLetTypeReference>();
- ReplaceNode(firstNode, letTypeRef);
- letTypeRef->mLetToken = tokenNode;
- return letTypeRef;
- }
- }
- else if ((mCompatMode) && (token == BfToken_Minus))
- {
- auto constExpr = CreateExpression(tokenNode, CreateExprFlags_BreakOnRChevron);
- auto constTypeRef = mAlloc->Alloc<BfConstExprTypeRef>();
- ReplaceNode(firstNode, constTypeRef);
- MEMBER_SET_CHECKED(constTypeRef, mConstExpr, constExpr);
- return constTypeRef;
- }
- else if (token == BfToken_Const)
- {
- if (!mCompatMode)
- {
- //Fail("Invalid use of 'const', only fields and local variables can be declared as const", tokenNode);
- //AddErrorNode(tokenNode);
- auto constExpr = CreateExpressionAfter(tokenNode, CreateExprFlags_BreakOnRChevron);
- auto constTypeRef = mAlloc->Alloc<BfConstExprTypeRef>();
- ReplaceNode(firstNode, constTypeRef);
- MEMBER_SET(constTypeRef, mConstToken, tokenNode);
- MEMBER_SET_CHECKED(constTypeRef, mConstExpr, constExpr);
- return constTypeRef;
- }
- else
- {
- auto elementType = CreateTypeRefAfter(tokenNode, createTypeRefFlags);
- auto constTypeRef = mAlloc->Alloc<BfConstTypeRef>();
- ReplaceNode(firstNode, constTypeRef);
- MEMBER_SET(constTypeRef, mConstToken, tokenNode);
- MEMBER_SET_CHECKED(constTypeRef, mElementType, elementType);
- return constTypeRef;
- }
- }
- else if (token == BfToken_Unsigned)
- {
- BF_ASSERT(mCompatMode);
- auto elementType = CreateTypeRefAfter(tokenNode, createTypeRefFlags);
- BfTypeReference* rootElementParent = NULL;
- auto rootElement = elementType;
- while (auto elementedType = BfNodeDynCast<BfElementedTypeRef>(rootElement))
- {
- rootElementParent = rootElement;
- rootElement = elementedType->mElementType;
- }
- auto unsignedTypeRef = mAlloc->Alloc<BfUnsignedTypeRef>();
- ReplaceNode(firstNode, unsignedTypeRef);
- MEMBER_SET(unsignedTypeRef, mUnsignedToken, tokenNode);
- if (rootElement == elementType)
- {
- MEMBER_SET_CHECKED(unsignedTypeRef, mElementType, elementType);
- return unsignedTypeRef;
- }
- else
- {
- #ifdef BF_AST_HAS_PARENT_MEMBER
- BF_ASSERT(rootElementParent == rootElement->mParent);
- #endif
- auto elementedType = BfNodeDynCast<BfElementedTypeRef>(rootElementParent);
- MEMBER_SET_CHECKED(unsignedTypeRef, mElementType, rootElement);
- MEMBER_SET_CHECKED(elementedType, mElementType, unsignedTypeRef);
- elementType->SetSrcStart(unsignedTypeRef->GetSrcStart());
- return elementType;
- }
- }
- else if ((token == BfToken_AllocType) || (token == BfToken_Nullable) || (token == BfToken_RetType))
- {
- auto retTypeTypeRef = mAlloc->Alloc<BfModifiedTypeRef>();
- ReplaceNode(firstNode, retTypeTypeRef);
- MEMBER_SET(retTypeTypeRef, mRetTypeToken, tokenNode);
- tokenNode = ExpectTokenAfter(retTypeTypeRef, BfToken_LParen);
- MEMBER_SET_CHECKED(retTypeTypeRef, mOpenParen, tokenNode);
- auto elementType = CreateTypeRefAfter(retTypeTypeRef, createTypeRefFlags);
- MEMBER_SET_CHECKED(retTypeTypeRef, mElementType, elementType);
- tokenNode = ExpectTokenAfter(retTypeTypeRef, BfToken_RParen);
- MEMBER_SET_CHECKED(retTypeTypeRef, mCloseParen, tokenNode);
- return retTypeTypeRef;
- }
- else if ((token == BfToken_Delegate) || (token == BfToken_Function))
- {
- auto delegateTypeRef = mAlloc->Alloc<BfDelegateTypeRef>();
- ReplaceNode(firstNode, delegateTypeRef);
- MEMBER_SET(delegateTypeRef, mTypeToken, tokenNode);
- auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
- if ((nextToken != NULL) && (nextToken->mToken == BfToken_LBracket))
- {
- mVisitorPos.MoveNext();
- auto attribs = CreateAttributeDirective(nextToken);
- MEMBER_SET_CHECKED(delegateTypeRef, mAttributes, attribs);
- }
- auto returnType = CreateTypeRefAfter(delegateTypeRef);
- MEMBER_SET_CHECKED(delegateTypeRef, mReturnType, returnType);
- tokenNode = ExpectTokenAfter(delegateTypeRef, BfToken_LParen);
- MEMBER_SET_CHECKED(delegateTypeRef, mOpenParen, tokenNode);
- BfDeferredAstSizedArray<BfParameterDeclaration*> params(delegateTypeRef->mParams, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(delegateTypeRef->mCommas, mAlloc);
- auto closeNode = ParseMethodParams(delegateTypeRef, ¶ms, &commas, BfToken_RParen, false);
- if (closeNode == NULL)
- {
- if (!params.empty())
- delegateTypeRef->AdjustSrcEnd(params.back());
- if (!commas.empty())
- delegateTypeRef->AdjustSrcEnd(commas.back());
- }
- MEMBER_SET_CHECKED(delegateTypeRef, mCloseParen, closeNode);
- mVisitorPos.MoveNext();
- for (auto paramDecl : params)
- {
- if ((paramDecl != NULL) && (paramDecl->mEqualsNode != NULL))
- Fail(StrFormat("Initializers cannot be used in anonymous %s type references. Consider creating a named %s type.", BfTokenToString(token), BfTokenToString(token)), paramDecl->mEqualsNode);
- }
- isHandled = true;
- firstNode = delegateTypeRef;
- if ((createTypeRefFlags & CreateTypeRefFlags_EarlyExit) != 0)
- return delegateTypeRef;
- }
- else if ((BfTokenIsTypeDecl(token)) || (token == BfToken_LBracket))
- {
- BfAttributeDirective* attributes = NULL;
- if (token == BfToken_LBracket)
- {
- attributes = CreateAttributeDirective(tokenNode);
- if (attributes == NULL)
- return NULL;
- mVisitorPos.MoveNext();
- bool isValid = false;
- auto nextNode = mVisitorPos.GetCurrent();
- tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if (tokenNode != NULL)
- {
- token = tokenNode->mToken;
- if (BfTokenIsTypeDecl(token))
- isValid = true;
- }
- if (!isValid)
- {
- AddErrorNode(attributes);
- return NULL;
- }
- }
- bool attribsApply = false;
- if ((mTypeMemberNodeStart != NULL) && (mTypeMemberNodeStart->mSrcEnd == tokenNode->mTriviaStart))
- attribsApply = true;
- auto typeDeclNode = CreateTopLevelObject(tokenNode, attributes, attribsApply ? mTypeMemberNodeStart : NULL, true);
- if (typeDeclNode == NULL)
- {
- if (attributes != NULL)
- AddErrorNode(attributes);
- return NULL;
- }
- auto typeDecl = BfNodeDynCast<BfTypeDeclaration>(typeDeclNode);
- if (typeDecl == NULL)
- {
- if (attributes != NULL)
- AddErrorNode(attributes);
- AddErrorNode(typeDeclNode);
- return NULL;
- }
- InitAnonymousType(typeDecl);
- auto typeRef = mAlloc->Alloc<BfInlineTypeReference>();
- ReplaceNode(typeDecl, typeRef);
- typeRef->mTypeDeclaration = typeDecl;
- return typeRef;
- }
- else if ((token == BfToken_Comptype) || (token == BfToken_Decltype))
- {
- auto declTypeRef = mAlloc->Alloc<BfExprModTypeRef>();
- ReplaceNode(tokenNode, declTypeRef);
- declTypeRef->mToken = tokenNode;
- tokenNode = ExpectTokenAfter(declTypeRef, BfToken_LParen);
- MEMBER_SET_CHECKED(declTypeRef, mOpenParen, tokenNode);
- auto targetExpr = CreateExpressionAfter(declTypeRef);
- MEMBER_SET_CHECKED(declTypeRef, mTarget, targetExpr);
- tokenNode = ExpectTokenAfter(declTypeRef, BfToken_RParen);
- MEMBER_SET_CHECKED(declTypeRef, mCloseParen, tokenNode);
- isHandled = true;
- firstNode = declTypeRef;
- if ((createTypeRefFlags & CreateTypeRefFlags_EarlyExit) != 0)
- return declTypeRef;
- }
- else if (token == BfToken_LParen)
- {
- auto tupleTypeRef = mAlloc->Alloc<BfTupleTypeRef>();
- BfDeferredAstSizedArray<BfTypeReference*> fieldTypes(tupleTypeRef->mFieldTypes, mAlloc);
- BfDeferredAstSizedArray<BfIdentifierNode*> fieldNames(tupleTypeRef->mFieldNames, mAlloc);
- BfDeferredAstSizedArray<BfAstNode*> commas(tupleTypeRef->mCommas, mAlloc);
- ReplaceNode(firstNode, tupleTypeRef);
- tupleTypeRef->mOpenParen = tokenNode;
- while (true)
- {
- auto tupleFieldType = CreateTypeRefAfter(tupleTypeRef);
- if (tupleFieldType == NULL)
- return tupleTypeRef;
- fieldTypes.push_back(tupleFieldType);
- MoveNode(tupleFieldType, tupleTypeRef);
- auto nextNode = mVisitorPos.GetNext();
- if (auto identifierNode = BfNodeDynCast<BfIdentifierNode>(nextNode))
- {
- while (fieldNames.size() < fieldTypes.size() - 1)
- fieldNames.push_back(NULL);
- MoveNode(identifierNode, tupleTypeRef);
- fieldNames.push_back(identifierNode);
- mVisitorPos.MoveNext();
- }
- auto tokenNode = ExpectTokenAfter(tupleTypeRef, BfToken_Comma, BfToken_RParen);
- if (tokenNode == NULL)
- return tupleTypeRef;
- if (tokenNode->GetToken() == BfToken_RParen)
- {
- if ((fieldTypes.size() == 1) && ((createTypeRefFlags & CreateTypeRefFlags_AllowSingleMemberTuple) == 0))
- {
- Fail("Tuple types must contain more than one member", tokenNode);
- }
- MEMBER_SET(tupleTypeRef, mCloseParen, tokenNode);
- //return tupleTypeRef;
- firstNode = tupleTypeRef;
- isHandled = true;
- break;
- }
- MoveNode(tokenNode, tupleTypeRef);
- commas.push_back(tokenNode);
- }
- }
- }
- else if (mCompatMode)
- {
- if (auto literalExpr = BfNodeDynCast<BfLiteralExpression>(firstNode))
- {
- auto constExpr = CreateExpression(literalExpr, CreateExprFlags_BreakOnRChevron);
- auto constTypeRef = mAlloc->Alloc<BfConstExprTypeRef>();
- ReplaceNode(firstNode, constTypeRef);
- MEMBER_SET_CHECKED(constTypeRef, mConstExpr, constExpr);
- return constTypeRef;
- }
- }
- if (!isHandled)
- {
- Fail("Expected type", firstNode);
- return NULL;
- }
- }
- }
- BfTypeReference* typeRef = BfNodeDynCast<BfTypeReference>(firstNode);
- if (typeRef == NULL)
- {
- // if (identifierNode->Equals("tag"))
- // {
- // auto rightIdentifer = ExpectIdentifierAfter(identifierNode);
- // if (rightIdentifer != NULL)
- // {
- // auto tagTypeRef = mAlloc->Alloc<BfTagTypeRef>();
- // ReplaceNode(identifierNode, tagTypeRef);
- // tagTypeRef->mTagNode = identifierNode;
- // MEMBER_SET(tagTypeRef, mNameNode, rightIdentifer);
- // return tagTypeRef;
- // }
- // }
- typeRef = DoCreateNamedTypeRef(identifierNode);
- }
- while (true)
- {
- if ((endNode != -1) && (mVisitorPos.mReadPos + 1 >= endNode))
- break;
- auto nextNode = mVisitorPos.GetNext();
- auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if (tokenNode != NULL)
- {
- BfToken token = tokenNode->GetToken();
- if (token == BfToken_Dot)
- {
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(mVisitorPos.mReadPos + 2)))
- {
- if (nextToken->mToken == BfToken_This)
- {
- // Don't encode '.this' in type ref
- break;
- }
- }
- BfQualifiedTypeReference* qualifiedTypeRef = mAlloc->Alloc<BfQualifiedTypeReference>();
- ReplaceNode(typeRef, qualifiedTypeRef);
- qualifiedTypeRef->mLeft = typeRef;
- MEMBER_SET(qualifiedTypeRef, mDot, tokenNode);
- mVisitorPos.MoveNext();
- while (true)
- {
- bool handled = false;
- if (mAllowTypeWildcard)
- {
- auto nextNode = mVisitorPos.GetNext();
- if (auto nextTokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (nextTokenNode->mToken == BfToken_Star)
- {
- auto wildcardTypeRef = mAlloc->Alloc<BfWildcardTypeReference>();
- ReplaceNode(nextTokenNode, wildcardTypeRef);
- wildcardTypeRef->mWildcardToken = nextTokenNode;
- typeRef = wildcardTypeRef;
- handled = true;
- mVisitorPos.MoveNext();
- }
- }
- }
- if (!handled)
- {
- auto rightIdentifer = ExpectIdentifierAfter(qualifiedTypeRef);
- if (rightIdentifer == NULL)
- return qualifiedTypeRef;
- auto namedTypeRef = mAlloc->Alloc<BfNamedTypeReference>();
- namedTypeRef->mNameNode = rightIdentifer;
- ReplaceNode(rightIdentifer, namedTypeRef);
- namedTypeRef->SetTriviaStart(rightIdentifer->GetTriviaStart());
- typeRef = namedTypeRef;
- }
- MEMBER_SET(qualifiedTypeRef, mRight, typeRef);
- nextNode = mVisitorPos.GetNext();
- if ((tokenNode = BfNodeDynCast<BfTokenNode>(nextNode)))
- {
- if (tokenNode->GetToken() == BfToken_Dot)
- {
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(mVisitorPos.mReadPos + 2)))
- {
- if (nextToken->mToken == BfToken_This)
- {
- // Don't encode '.this' in type ref
- break;
- }
- }
- BfQualifiedTypeReference* outerQualifiedTypeRef = mAlloc->Alloc<BfQualifiedTypeReference>();
- ReplaceNode(qualifiedTypeRef, outerQualifiedTypeRef);
- outerQualifiedTypeRef->mLeft = qualifiedTypeRef;
- MEMBER_SET(outerQualifiedTypeRef, mDot, tokenNode);
- qualifiedTypeRef = outerQualifiedTypeRef;
- mVisitorPos.MoveNext();
- }
- else
- break;
- }
- else
- {
- break;
- }
- }
- typeRef = qualifiedTypeRef;
- }
- else if (token == BfToken_Star)
- {
- auto ptrType = mAlloc->Alloc<BfPointerTypeRef>();
- ReplaceNode(typeRef, ptrType);
- ptrType->mElementType = typeRef;
- MEMBER_SET(ptrType, mStarNode, tokenNode);
- typeRef = ptrType;
- mVisitorPos.MoveNext();
- }
- else if ((token == BfToken_Question) || (token == BfToken_QuestionLBracket))
- {
- if (token == BfToken_QuestionLBracket)
- tokenNode = BreakQuestionLBracket(tokenNode);
- else
- mVisitorPos.MoveNext();
- auto nullableType = mAlloc->Alloc<BfNullableTypeRef>();
- ReplaceNode(typeRef, nullableType);
- nullableType->mElementType = typeRef;
- MEMBER_SET(nullableType, mQuestionToken, tokenNode);
- typeRef = nullableType;
- }
- else if (token == BfToken_LBracket)
- {
- if (!parseArrayBracket)
- return typeRef;
- auto arrayType = mAlloc->Alloc<BfArrayTypeRef>();
- auto newArrayType = arrayType;
- ReplaceNode(typeRef, arrayType);
- arrayType->mOpenBracket = tokenNode;
- MoveNode(tokenNode, arrayType);
- arrayType->mDimensions = 1;
- arrayType->mElementType = typeRef;
- mVisitorPos.MoveNext();
- while (true)
- {
- auto prevArrayType = BfNodeDynCast<BfArrayTypeRef>(arrayType->mElementType);
- if (prevArrayType == NULL)
- break;
- std::swap(prevArrayType->mOpenBracket, arrayType->mOpenBracket);
- std::swap(prevArrayType->mParams, arrayType->mParams);
- std::swap(prevArrayType->mCloseBracket, arrayType->mCloseBracket);
- std::swap(prevArrayType->mDimensions, arrayType->mDimensions);
- prevArrayType->SetSrcEnd(arrayType->GetSrcEnd());
- arrayType = prevArrayType;
- }
- BF_ASSERT(arrayType->mParams.mVals == NULL);
- arrayType->mParams.mSize = 0;
- BfDeferredAstSizedArray<BfAstNode*> params(arrayType->mParams, mAlloc);
- bool hasFailed = false;
- bool isSized = false;
- while (true)
- {
- nextNode = mVisitorPos.GetNext();
- tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if (tokenNode != NULL)
- {
- if (tokenNode->GetToken() == BfToken_Comma)
- {
- MoveNode(tokenNode, arrayType);
- mVisitorPos.MoveNext();
- arrayType->mDimensions++;
- params.push_back(tokenNode);
- }
- else if (tokenNode->GetToken() == BfToken_RBracket)
- {
- MoveNode(tokenNode, arrayType);
- mVisitorPos.MoveNext();
- arrayType->mCloseBracket = tokenNode;
- break;
- }
- else
- tokenNode = NULL;
- }
- if (tokenNode == NULL)
- {
- if ((!params.IsEmpty()) && (!BfNodeIsExact<BfTokenNode>(params.back())))
- {
- FailAfter("Expected ','", params.back());
- hasFailed = true;
- break;
- }
- BfExpression* sizeExpr = CreateExpressionAfter(arrayType);
- if (sizeExpr == NULL)
- {
- hasFailed = true;
- break;
- }
- MoveNode(sizeExpr, arrayType);
- params.push_back(sizeExpr);
- }
- }
- newArrayType->SetSrcEnd(arrayType->GetSrcEnd());
- if (hasFailed)
- return newArrayType;
- typeRef = newArrayType;
- }
- else if (token == BfToken_LChevron)
- {
- if (auto elementGeneric = BfNodeDynCastExact<BfGenericInstanceTypeRef>(typeRef))
- {
- // Already a generic
- return typeRef;
- }
- auto genericInstance = mAlloc->Alloc<BfGenericInstanceTypeRef>();
- BfDeferredSizedArray<BfAstNode*> genericArguments(genericInstance->mGenericArguments, mAlloc);
- BfDeferredAstSizedArray<BfAstNode*> commas(genericInstance->mCommas, mAlloc);
- ReplaceNode(typeRef, genericInstance);
- genericInstance->mOpenChevron = tokenNode;
- MoveNode(tokenNode, genericInstance);
- genericInstance->mElementType = typeRef;
- mVisitorPos.MoveNext();
- bool isBoundName = false;
- bool isUnboundName = false;
- while (true)
- {
- auto nextNode = mVisitorPos.GetNext();
- auto genericIdentifier = BfNodeDynCast<BfIdentifierNode>(nextNode);
- bool doAddType = genericIdentifier != NULL;
- bool addAsExpr = false;
- if (BfNodeDynCast<BfLiteralExpression>(nextNode) != NULL)
- {
- doAddType = true;
- addAsExpr = true;
- }
- else if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (tokenNode->mToken == BfToken_Minus)
- {
- doAddType = true;
- addAsExpr = true;
- }
- }
- if (genericIdentifier == NULL)
- {
- auto nextNode = mVisitorPos.GetNext();
- tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- BfToken token = BfToken_None;
- if (tokenNode != NULL)
- token = tokenNode->GetToken();
- if ((tokenNode != NULL) &&
- ((token == BfToken_Const) ||
- (token == BfToken_Ref) ||
- (token == BfToken_Mut) ||
- (token == BfToken_LParen) ||
- (token == BfToken_Delegate) ||
- (token == BfToken_Function) ||
- (token == BfToken_Comptype) ||
- (token == BfToken_Decltype) ||
- ((token == BfToken_Star) && (mAllowTypeWildcard))))
- doAddType = true;
- }
- if ((!doAddType) && (isBoundName))
- {
- FailAfter("Expected type", genericInstance);
- }
- if ((doAddType) && (!isUnboundName))
- {
- BfAstNode* genericArgumentTypeRef = NULL;
- if (addAsExpr)
- {
- genericArgumentTypeRef = CreateExpressionAfter(genericInstance, CreateExprFlags_BreakOnRChevron);
- }
- else
- genericArgumentTypeRef = CreateTypeRefAfter(genericInstance);
- if (genericArgumentTypeRef == NULL)
- return NULL;
- MoveNode(genericArgumentTypeRef, genericInstance);
- genericArguments.push_back(genericArgumentTypeRef);
- isBoundName = true;
- }
- else
- isUnboundName = true;
- nextNode = mVisitorPos.GetNext();
- tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if (tokenNode == NULL)
- {
- FailAfter("Expected ',' or '>'", genericInstance);
- return genericInstance;
- }
- token = tokenNode->GetToken();
- if (token == BfToken_RDblChevron)
- {
- tokenNode = BreakDoubleChevron(tokenNode);
- token = tokenNode->GetToken();
- }
- else
- {
- mVisitorPos.MoveNext();
- }
- if (token == BfToken_RChevron)
- {
- MoveNode(tokenNode, genericInstance);
- genericInstance->mCloseChevron = tokenNode;
- break;
- }
- if (token != BfToken_Comma)
- {
- Fail("Either ',' or '>' expected", tokenNode);
- mVisitorPos.mReadPos--;
- //AddErrorNode(tokenNode);
- return genericInstance;
- }
- MoveNode(tokenNode, genericInstance);
- commas.push_back(tokenNode);
- }
- typeRef = genericInstance;
- }
- else
- break;
- }
- else
- break;
- }
- return typeRef;
- }
- BfTypeReference* BfReducer::CreateTypeRef(BfAstNode* firstNode, CreateTypeRefFlags createTypeRefFlags)
- {
- int endNode = -1;
- if ((createTypeRefFlags & CreateTypeRefFlags_SafeGenericParse) != 0)
- {
- createTypeRefFlags = (CreateTypeRefFlags)(createTypeRefFlags & ~CreateTypeRefFlags_SafeGenericParse);
- int outEndNode = -1;
- int retryNode = -1;
- bool isTypeRef = IsTypeReference(firstNode, BfToken_None, -1, &retryNode, &outEndNode, NULL, NULL, NULL);
- if ((!isTypeRef) && (retryNode != -1))
- endNode = retryNode;
- }
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(firstNode))
- {
- BfToken token = tokenNode->GetToken();
- if ((token == BfToken_Ref) || (token == BfToken_Mut))
- {
- auto nextNode = mVisitorPos.GetNext();
- mVisitorPos.MoveNext();
- auto typeRef = DoCreateTypeRef(nextNode, createTypeRefFlags);
- if (typeRef == NULL)
- {
- mVisitorPos.mReadPos--;
- AddErrorNode(tokenNode);
- return NULL;
- }
- return CreateRefTypeRef(typeRef, tokenNode);
- }
- }
- return DoCreateTypeRef(firstNode, createTypeRefFlags, endNode);
- }
- BfTypeReference* BfReducer::CreateTypeRefAfter(BfAstNode* astNode, CreateTypeRefFlags createTypeRefFlags)
- {
- if (!AssertCurrentNode(astNode))
- return NULL;
- auto nextNode = mVisitorPos.GetNext();
- if (nextNode == NULL)
- {
- FailAfter("Expected type", astNode);
- return NULL;
- }
- mVisitorPos.MoveNext();
- int startPos = mVisitorPos.mReadPos;
- BfTypeReference* typeRef = CreateTypeRef(nextNode, createTypeRefFlags);
- if (typeRef == NULL)
- {
- if (mLastErrorSrcEnd > startPos)
- {
- // We added an error node and made progress
- for (int checkIdx = mVisitorPos.mReadPos - 1; checkIdx >= startPos - 1; checkIdx--)
- {
- auto checkNode = mVisitorPos.Get(checkIdx);
- if (checkNode->mSrcEnd <= mLastErrorSrcEnd)
- break;
- mVisitorPos.mReadPos = checkIdx;
- }
- }
- else
- {
- BF_ASSERT(mVisitorPos.mReadPos == startPos);
- mVisitorPos.mReadPos = startPos - 1;
- }
- }
- return typeRef;
- }
- BfTypeReference* BfReducer::CreateRefTypeRef(BfTypeReference* elementType, BfTokenNode* refTokenNode)
- {
- BfToken refToken = refTokenNode->GetToken();
- BF_ASSERT((refToken == BfToken_Ref) || (refToken == BfToken_Mut) || (refToken == BfToken_In) || (refToken == BfToken_Out));
- if (elementType->IsA<BfRefTypeRef>())
- {
- Fail("Multiple ref levels are not allowed", refTokenNode);
- AddErrorNode(refTokenNode);
- return elementType;
- }
- if (elementType->IsA<BfConstTypeRef>())
- {
- Fail("Refs to const values are not allowed", refTokenNode);
- AddErrorNode(refTokenNode);
- return elementType;
- }
- auto refTypeRef = mAlloc->Alloc<BfRefTypeRef>();
- MEMBER_SET(refTypeRef, mRefToken, refTokenNode);
- ReplaceNode(elementType, refTypeRef);
- refTypeRef->mElementType = elementType;
- return refTypeRef;
- }
- BfIdentifierNode* BfReducer::CompactQualifiedName(BfAstNode* leftNode, bool allowGlobalLookup)
- {
- if (!AssertCurrentNode(leftNode))
- return NULL;
- if ((leftNode == NULL) || (!leftNode->IsA<BfIdentifierNode>()))
- return NULL;
- auto prevNode = mVisitorPos.Get(mVisitorPos.mWritePos - 1);
- auto leftIdentifier = (BfIdentifierNode*)leftNode;
- while (true)
- {
- bool isGlobalLookup = false;
- auto nextToken = mVisitorPos.Get(mVisitorPos.mReadPos + 1);
- auto tokenNode = BfNodeDynCast<BfTokenNode>(nextToken);
- if ((tokenNode != NULL) && (tokenNode->mToken == BfToken_ColonColon) && (leftNode->IsExact<BfIdentifierNode>()) && (leftNode->Equals("global")) && (allowGlobalLookup))
- {
- isGlobalLookup = true;
- }
- else if ((tokenNode == NULL) || ((tokenNode->GetToken() != BfToken_Dot) /*&& (tokenNode->GetToken() != BfToken_QuestionDot)*/))
- return leftIdentifier;
- auto nextNextToken = mVisitorPos.Get(mVisitorPos.mReadPos + 2);
- auto rightIdentifier = BfNodeDynCast<BfIdentifierNode>(nextNextToken);
- if (rightIdentifier == NULL)
- {
- if (auto rightToken = BfNodeDynCast<BfTokenNode>(nextNextToken))
- {
- if (rightToken->mToken == BfToken_This)
- {
- return leftIdentifier;
- }
- if (BfTokenIsKeyword(rightToken->mToken))
- {
- rightIdentifier = mAlloc->Alloc<BfIdentifierNode>();
- ReplaceNode(rightToken, rightIdentifier);
- }
- }
- if (rightIdentifier == NULL)
- return leftIdentifier;
- }
- if (isGlobalLookup)
- {
- // For 'global::', we put 'global' on the left and the rest on the right which is different from normal
- mVisitorPos.MoveNext(); // past .
- mVisitorPos.MoveNext(); // past right
- auto rightSide = CompactQualifiedName(rightIdentifier, false);
-
- auto qualifiedNameNode = mAlloc->Alloc<BfQualifiedNameNode>();
- ReplaceNode(leftIdentifier, qualifiedNameNode);
- qualifiedNameNode->mLeft = leftIdentifier;
- MEMBER_SET(qualifiedNameNode, mDot, tokenNode);
- MEMBER_SET(qualifiedNameNode, mRight, rightSide);
- return qualifiedNameNode;
- }
- // If the previous dotted span failed (IE: had chevrons) then don't insert qualified names in the middle of it
- auto prevNodeToken = BfNodeDynCast<BfTokenNode>(prevNode);
- if ((prevNodeToken != NULL) &&
- ((prevNodeToken->GetToken() == BfToken_Dot) ||
- (prevNodeToken->GetToken() == BfToken_QuestionDot) ||
- (prevNodeToken->GetToken() == BfToken_Arrow)))
- return leftIdentifier;
- mVisitorPos.MoveNext(); // past .
- mVisitorPos.MoveNext(); // past right
- auto qualifiedNameNode = mAlloc->Alloc<BfQualifiedNameNode>();
- ReplaceNode(leftIdentifier, qualifiedNameNode);
- qualifiedNameNode->mLeft = leftIdentifier;
- MEMBER_SET(qualifiedNameNode, mDot, tokenNode);
- MEMBER_SET(qualifiedNameNode, mRight, rightIdentifier);
- leftIdentifier = qualifiedNameNode;
- prevNode = NULL;
- }
- return leftIdentifier;
- }
- void BfReducer::TryIdentifierConvert(int readPos)
- {
- auto node = mVisitorPos.Get(readPos);
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(node))
- {
- if (BfTokenIsKeyword(tokenNode->mToken))
- {
- auto identifierNode = mAlloc->Alloc<BfIdentifierNode>();
- ReplaceNode(tokenNode, identifierNode);
- mVisitorPos.Set(readPos, identifierNode);
- }
- }
- }
- void BfReducer::CreateQualifiedNames(BfAstNode* node)
- {
- auto block = BfNodeDynCast<BfBlock>(node);
- if (block == NULL)
- return;
- SetAndRestoreValue<BfVisitorPos> prevVisitorPos(mVisitorPos, BfVisitorPos(block));
- bool isDone = !mVisitorPos.MoveNext();
- while (!isDone)
- {
- auto child = mVisitorPos.GetCurrent();
- BfAstNode* newNode = CompactQualifiedName(child);
- if (newNode == NULL)
- newNode = child;
- CreateQualifiedNames(child);
- isDone = !mVisitorPos.MoveNext();
- if (newNode != NULL)
- mVisitorPos.Write(newNode);
- }
- mVisitorPos.Trim();
- }
- BfAttributeDirective* BfReducer::CreateAttributeDirective(BfTokenNode* startToken)
- {
- BfAttributeDirective* attributeDirective = mAlloc->Alloc<BfAttributeDirective>();
- BfDeferredAstSizedArray<BfExpression*> arguments(attributeDirective->mArguments, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(attributeDirective->mCommas, mAlloc);
- ReplaceNode(startToken, attributeDirective);
- attributeDirective->mAttrOpenToken = startToken;
- bool isHandled = false;
- auto nextNode = mVisitorPos.GetNext();
- auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if (tokenNode != NULL)
- {
- if (tokenNode->GetToken() == BfToken_Return)
- {
- auto attributeTargetSpecifier = mAlloc->Alloc<BfAttributeTargetSpecifier>();
- ReplaceNode(tokenNode, attributeTargetSpecifier);
- MEMBER_SET(attributeDirective, mAttributeTargetSpecifier, attributeTargetSpecifier);
- attributeTargetSpecifier->mTargetToken = tokenNode;
- mVisitorPos.MoveNext();
- tokenNode = ExpectTokenAfter(attributeDirective, BfToken_Colon);
- if (tokenNode != NULL)
- MEMBER_SET(attributeTargetSpecifier, mColonToken, tokenNode);
- attributeDirective->SetSrcEnd(attributeDirective->mAttributeTargetSpecifier->GetSrcEnd());
- }
- else if ((tokenNode->mToken == BfToken_Ampersand) || (tokenNode->mToken == BfToken_AssignEquals) || (tokenNode->mToken == BfToken_Question))
- {
- MEMBER_SET(attributeDirective, mAttributeTargetSpecifier, tokenNode);
- mVisitorPos.MoveNext();
- isHandled = true;
- nextNode = mVisitorPos.GetNext();
- BfExpression* nameNode = NULL;
- if (auto identiferNode = BfNodeDynCast<BfIdentifierNode>(nextNode))
- nameNode = identiferNode;
- else if (auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (nextToken->mToken == BfToken_This)
- {
- auto thisExpr = mAlloc->Alloc<BfThisExpression>();
- ReplaceNode(nextToken, thisExpr);
- nameNode = thisExpr;
- }
- }
- if (nameNode != NULL)
- {
- attributeDirective->SetSrcEnd(nameNode->GetSrcEnd());
- arguments.push_back(nameNode);
- mVisitorPos.MoveNext();
- nextNode = mVisitorPos.GetNext();
- }
- }
- }
- if (!isHandled)
- {
- int prevReadPos = mVisitorPos.mReadPos;
- auto typeRef = CreateTypeRefAfter(attributeDirective);
- if (typeRef == NULL)
- {
- if (mVisitorPos.mReadPos != prevReadPos)
- {
- AddErrorNode(attributeDirective);
- auto curNode = mVisitorPos.GetCurrent();
- if ((mSource != NULL) && (!mSource->HasPendingError(curNode)))
- mSource->AddErrorNode(curNode);
- return NULL;
- }
-
- auto nextNode = mVisitorPos.GetNext();
- if (BfTokenNode* endToken = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (endToken->GetToken() == BfToken_RBracket)
- {
- mVisitorPos.MoveNext();
- MEMBER_SET(attributeDirective, mCtorCloseParen, endToken);
- return attributeDirective;
- }
- }
- return attributeDirective;
- }
- MEMBER_SET(attributeDirective, mAttributeTypeRef, typeRef);
- }
- tokenNode = ExpectTokenAfter(attributeDirective, BfToken_LParen, BfToken_RBracket, BfToken_Comma);
- if (tokenNode == NULL)
- return attributeDirective;
- if (tokenNode->GetToken() == BfToken_LParen)
- {
- MEMBER_SET(attributeDirective, mCtorOpenParen, tokenNode);
- tokenNode = ReadArguments(attributeDirective, attributeDirective, &arguments, &commas, BfToken_RParen, false);
- if (tokenNode == NULL)
- {
- auto nextNode = mVisitorPos.GetNext();
- tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if ((tokenNode != NULL) && (tokenNode->GetToken() == BfToken_RBracket))
- {
- mVisitorPos.MoveNext();
- goto Do_RBracket;
- }
- return attributeDirective;
- }
- MEMBER_SET(attributeDirective, mCtorCloseParen, tokenNode);
- tokenNode = ExpectTokenAfter(attributeDirective, BfToken_RBracket, BfToken_Comma);
- if (tokenNode == NULL)
- return attributeDirective;
- }
- Do_RBracket:
- if (tokenNode->GetToken() == BfToken_RBracket)
- {
- MEMBER_SET(attributeDirective, mAttrCloseToken, tokenNode);
- auto nextNode = mVisitorPos.GetNext();
- tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if ((tokenNode == NULL) || (tokenNode->GetToken() != BfToken_LBracket))
- return attributeDirective;
- mVisitorPos.MoveNext();
- }
- // Has another one- chain it
- auto nextAttribute = CreateAttributeDirective(tokenNode);
- if (nextAttribute != NULL)
- {
- MEMBER_SET(attributeDirective, mNextAttribute, nextAttribute);
- }
- return attributeDirective;
- }
- BfStatement* BfReducer::CreateAttributedStatement(BfTokenNode* tokenNode, CreateStmtFlags createStmtFlags)
- {
- auto attrib = CreateAttributeDirective(tokenNode);
- if (attrib == NULL)
- return NULL;
- BfAstNode* stmt = CreateStatementAfter(attrib, createStmtFlags);
- if (stmt != NULL)
- {
- if (auto localMethodDecl = BfNodeDynCastExact<BfLocalMethodDeclaration>(stmt))
- {
- BF_ASSERT(localMethodDecl->mMethodDeclaration->mAttributes == NULL);
- localMethodDecl->mSrcStart = attrib->mSrcStart;
- MEMBER_SET(localMethodDecl->mMethodDeclaration, mAttributes, attrib);
- return localMethodDecl;
- }
- bool isValid = true;
- auto checkNode = stmt;
- if (auto exprStatement = BfNodeDynCast<BfExpressionStatement>(checkNode))
- checkNode = exprStatement->mExpression;
- if ((checkNode->IsA<BfObjectCreateExpression>()) ||
- (checkNode->IsA<BfInvocationExpression>()) ||
- (checkNode->IsA<BfVariableDeclaration>()) ||
- (checkNode->IsA<BfStringInterpolationExpression>()) ||
- (checkNode->IsA<BfBlock>()))
- {
- if (auto varDecl = BfNodeDynCast<BfVariableDeclaration>(checkNode))
- {
- if (CheckInlineTypeRefAttribute(varDecl->mTypeRef, attrib))
- return BfNodeDynCast<BfStatement>(stmt);
- }
- BfAttributedStatement* attribStmt = mAlloc->Alloc<BfAttributedStatement>();
- ReplaceNode(attrib, attribStmt);
- attribStmt->mAttributes = attrib;
- MEMBER_SET(attribStmt, mStatement, stmt);
- return attribStmt;
- }
- }
- Fail("Prefixed attributes can only be used on allocations, invocations, blocks, or variable declarations", attrib);
- BfAttributedStatement* attribStmt = mAlloc->Alloc<BfAttributedStatement>();
- ReplaceNode(attrib, attribStmt);
- attribStmt->mAttributes = attrib;
- if (stmt != NULL)
- MEMBER_SET(attribStmt, mStatement, stmt);
- return attribStmt;
- }
- BfExpression* BfReducer::CreateAttributedExpression(BfTokenNode* tokenNode, bool onlyAllowIdentifier)
- {
- auto attrib = CreateAttributeDirective(tokenNode);
- if (attrib == NULL)
- return NULL;
- if (!onlyAllowIdentifier)
- {
- BfExpression* expr = CreateExpressionAfter(attrib, CreateExprFlags_EarlyExit);
- if (expr != NULL)
- {
- if (auto identifier = BfNodeDynCast<BfIdentifierNode>(expr))
- {
- auto attrIdentifier = mAlloc->Alloc<BfAttributedIdentifierNode>();
- ReplaceNode(attrib, attrIdentifier);
- attrIdentifier->mAttributes = attrib;
- MEMBER_SET(attrIdentifier, mIdentifier, identifier);
- return attrIdentifier;
- }
- if ((expr->IsA<BfObjectCreateExpression>()) ||
- (expr->IsA<BfInvocationExpression>()) ||
- (expr->IsA<BfVariableDeclaration>()) ||
- (expr->IsA<BfStringInterpolationExpression>()) ||
- (expr->IsA<BfBlock>()))
- {
- BfAttributedExpression* attribExpr = mAlloc->Alloc<BfAttributedExpression>();
- ReplaceNode(attrib, attribExpr);
- attribExpr->mAttributes = attrib;
- MEMBER_SET(attribExpr, mExpression, expr);
- return attribExpr;
- }
- }
- Fail("Prefixed attributes can only be used on allocations, invocations, blocks, or variable declarations", attrib);
- BfAttributedExpression* attribExpr = mAlloc->Alloc<BfAttributedExpression>();
- ReplaceNode(attrib, attribExpr);
- attribExpr->mAttributes = attrib;
- if (expr != NULL)
- MEMBER_SET(attribExpr, mExpression, expr);
- return attribExpr;
- }
- auto attrIdentifier = mAlloc->Alloc<BfAttributedIdentifierNode>();
- ReplaceNode(attrib, attrIdentifier);
- attrIdentifier->mAttributes = attrib;
- auto identifier = ExpectIdentifierAfter(attrib);
- if (identifier != NULL)
- {
- MEMBER_SET(attrIdentifier, mIdentifier, identifier);
- }
- return attrIdentifier;
- }
- BfTokenNode* BfReducer::ReadArguments(BfAstNode* parentNode, BfAstNode* afterNode, SizedArrayImpl<BfExpression*>* arguments, SizedArrayImpl<BfTokenNode*>* commas, BfToken endToken, bool allowSkippedArgs, CreateExprFlags createExprFlags)
- {
- for (int paramIdx = 0; true; paramIdx++)
- {
- auto nextNode = mVisitorPos.GetNext();
- if ((nextNode == NULL) && (endToken == BfToken_None))
- return NULL;
- BfTokenNode* tokenNode = BfNodeDynCastExact<BfTokenNode>(nextNode);
- if (tokenNode != NULL)
- {
- if (tokenNode->GetToken() == endToken)
- {
- MoveNode(tokenNode, parentNode);
- mVisitorPos.MoveNext();
- return tokenNode;
- }
- if (paramIdx > 0)
- {
- if (tokenNode->GetToken() != BfToken_Comma)
- {
- Fail("Expected comma", tokenNode);
- return NULL;
- }
- commas->push_back(tokenNode);
- MoveNode(tokenNode, parentNode);
- mVisitorPos.MoveNext();
- }
- }
- else
- {
- if (paramIdx > 0)
- {
- FailAfter("Expected comma", afterNode);
- return NULL;
- }
- }
- BfExpression* argumentExpr = NULL;
- if (allowSkippedArgs)
- {
- auto nextNode = mVisitorPos.GetNext();
- if ((nextNode == NULL) && (endToken == BfToken_None))
- return NULL;
- if (auto nextToken = BfNodeDynCastExact<BfTokenNode>(nextNode))
- {
- if (nextToken->GetToken() == endToken)
- continue;
- if (nextToken->GetToken() == BfToken_Comma)
- {
- arguments->push_back(NULL);
- continue;
- }
- }
- if (auto identifierNode = BfNodeDynCastExact<BfIdentifierNode>(nextNode))
- {
- if (auto nextNextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(mVisitorPos.mReadPos + 2)))
- {
- if (nextNextToken->mToken == BfToken_Colon)
- {
- auto namedExpr = mAlloc->Alloc<BfNamedExpression>();
- ReplaceNode(identifierNode, namedExpr);
- MEMBER_SET(namedExpr, mNameNode, identifierNode);
- MEMBER_SET(namedExpr, mColonToken, nextNextToken)
- mVisitorPos.MoveNext();
- mVisitorPos.MoveNext();
- auto innerExpr = CreateExpressionAfter(namedExpr, CreateExprFlags_AllowVariableDecl);
- if (innerExpr != NULL)
- {
- MEMBER_SET(namedExpr, mExpression, innerExpr);
- }
- argumentExpr = namedExpr;
- }
- }
- }
- }
- if (argumentExpr == NULL)
- argumentExpr = CreateExpressionAfter(afterNode, CreateExprFlags_AllowVariableDecl);
- if ((argumentExpr != NULL) || (endToken != BfToken_None))
- arguments->push_back(argumentExpr);
- if (argumentExpr == NULL)
- {
- auto nextNode = mVisitorPos.GetNext();
- if (auto tokenNode = BfNodeDynCastExact<BfTokenNode>(nextNode))
- {
- // Try to continue with param list even after an error
- if ((tokenNode->GetToken() == BfToken_Comma) || (tokenNode->GetToken() == endToken))
- continue;
- }
- return NULL;
- }
- MoveNode(argumentExpr, parentNode);
- afterNode = parentNode;
- }
- }
- BfIdentifierNode* BfReducer::ExtractExplicitInterfaceRef(BfAstNode* memberDeclaration, BfIdentifierNode* nameIdentifier, BfTypeReference** outExplicitInterface, BfTokenNode** outExplicitInterfaceDotToken)
- {
- int dotTokenIdx = -1;
- if (auto qualifiedName = BfNodeDynCast<BfQualifiedNameNode>(nameIdentifier))
- {
- MoveNode(qualifiedName, memberDeclaration);
- MoveNode(qualifiedName->mDot, memberDeclaration);
- *outExplicitInterfaceDotToken = qualifiedName->mDot;
- auto explicitInterfaceRef = CreateTypeRef(qualifiedName->mLeft);
- BF_ASSERT(explicitInterfaceRef != NULL);
- MoveNode(explicitInterfaceRef, memberDeclaration);
- *outExplicitInterface = explicitInterfaceRef;
- return qualifiedName->mRight;
- }
- else if (IsTypeReference(nameIdentifier, BfToken_Dot, -1, &dotTokenIdx))
- {
- BfAstNode* dotToken = mVisitorPos.Get(dotTokenIdx);
- MoveNode(dotToken, memberDeclaration);
- *outExplicitInterfaceDotToken = (BfTokenNode*)dotToken;
- auto explicitInterfaceRef = CreateTypeRef(nameIdentifier);
- BF_ASSERT(explicitInterfaceRef != NULL);
- MoveNode(explicitInterfaceRef, memberDeclaration);
- *outExplicitInterface = explicitInterfaceRef;
- return ExpectIdentifierAfter(memberDeclaration);
- }
- return nameIdentifier;
- }
- BfFieldDtorDeclaration* BfReducer::CreateFieldDtorDeclaration(BfAstNode* srcNode)
- {
- BfFieldDtorDeclaration* firstFieldDtor = NULL;
- BfFieldDtorDeclaration* prevFieldDtor = NULL;
- auto nextNode = mVisitorPos.GetNext();
- while (auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (nextToken->GetToken() != BfToken_Tilde)
- break;
- auto fieldDtor = mAlloc->Alloc<BfFieldDtorDeclaration>();
- ReplaceNode(nextToken, fieldDtor);
- fieldDtor->mTildeToken = nextToken;
- //int prevReadPos = mVisitorPos.mReadPos;
- mVisitorPos.MoveNext();
- if (prevFieldDtor != NULL)
- {
- MEMBER_SET(prevFieldDtor, mNextFieldDtor, fieldDtor);
- }
- else
- {
- firstFieldDtor = fieldDtor;
- MoveNode(fieldDtor, srcNode);
- }
- auto statement = CreateStatementAfter(srcNode);
- if (statement == NULL)
- {
- //mVisitorPos.mReadPos = prevReadPos;
- break;
- }
- MEMBER_SET(fieldDtor, mBody, statement);
- fieldDtor->SetSrcEnd(statement->GetSrcEnd());
- prevFieldDtor = fieldDtor;
- srcNode->SetSrcEnd(fieldDtor->GetSrcEnd());
- nextNode = mVisitorPos.GetNext();
- // We used to NOT have this break here. Why were we allowing multiple ~'s when a block statement would have made more sense?
- break; // Wh
- }
- return firstFieldDtor;
- }
- BfFieldDeclaration* BfReducer::CreateFieldDeclaration(BfTokenNode* tokenNode, BfTypeReference* typeRef, BfIdentifierNode* nameIdentifier, BfFieldDeclaration* prevFieldDeclaration)
- {
- auto fieldDeclaration = mAlloc->Alloc<BfFieldDeclaration>();
- if (prevFieldDeclaration != NULL)
- {
- ReplaceNode(tokenNode, fieldDeclaration);
- MEMBER_SET(fieldDeclaration, mPrecedingComma, tokenNode);
- MEMBER_SET(fieldDeclaration, mNameNode, nameIdentifier);
- fieldDeclaration->mDocumentation = prevFieldDeclaration->mDocumentation;
- fieldDeclaration->mAttributes = prevFieldDeclaration->mAttributes;
- fieldDeclaration->mProtectionSpecifier = prevFieldDeclaration->mProtectionSpecifier;
- fieldDeclaration->mStaticSpecifier = prevFieldDeclaration->mStaticSpecifier;
- fieldDeclaration->mTypeRef = prevFieldDeclaration->mTypeRef;
- fieldDeclaration->mConstSpecifier = prevFieldDeclaration->mConstSpecifier;
- fieldDeclaration->mReadOnlySpecifier = prevFieldDeclaration->mReadOnlySpecifier;
- fieldDeclaration->mVolatileSpecifier = prevFieldDeclaration->mVolatileSpecifier;
- fieldDeclaration->mNewSpecifier = prevFieldDeclaration->mNewSpecifier;
- fieldDeclaration->mExternSpecifier = prevFieldDeclaration->mExternSpecifier;
- tokenNode = ExpectTokenAfter(fieldDeclaration, BfToken_Semicolon, BfToken_AssignEquals, BfToken_Comma, BfToken_Tilde);
- if (tokenNode == NULL)
- return fieldDeclaration;
- mVisitorPos.mReadPos--; // Go back to token
- }
- else
- {
- ReplaceNode(typeRef, fieldDeclaration);
- fieldDeclaration->mTypeRef = typeRef;
- fieldDeclaration->mInitializer = NULL;
- if (nameIdentifier != NULL)
- {
- fieldDeclaration->mNameNode = nameIdentifier;
- MoveNode(fieldDeclaration->mNameNode, fieldDeclaration);
- }
- }
- CheckMultiuseAttributeTypeRef(fieldDeclaration->mTypeRef);
- BfToken token = tokenNode->GetToken();
- if (token == BfToken_AssignEquals)
- {
- MEMBER_SET(fieldDeclaration, mEqualsNode, tokenNode);
- MoveNode(tokenNode, fieldDeclaration);
- mVisitorPos.MoveNext();
- mIsFieldInitializer = true;
- fieldDeclaration->mInitializer = CreateExpressionAfter(fieldDeclaration);
- mIsFieldInitializer = false;
- if (fieldDeclaration->mInitializer != NULL)
- {
- MoveNode(fieldDeclaration->mInitializer, fieldDeclaration);
- auto nextToken = ExpectTokenAfter(fieldDeclaration, BfToken_Semicolon, BfToken_Comma, BfToken_Tilde);
- if (nextToken != NULL)
- mVisitorPos.mReadPos--; // Backtrack, someone else eats these
- }
- }
- else if (token == BfToken_Comma)
- {
- //
- }
- else if (token == BfToken_Tilde)
- {
- //
- }
- else if (token != BfToken_Semicolon)
- {
- //MEMBER_SET(fieldDeclaration, mEqualsNode, tokenNode);
- FailAfter("';', '=', or '~' expected", nameIdentifier);
- return fieldDeclaration;
- }
- bool hasSemicolon = false;
- auto fieldDtor = CreateFieldDtorDeclaration(fieldDeclaration);
- if (fieldDtor != NULL)
- {
- fieldDeclaration->mFieldDtor = fieldDtor;
- if (fieldDtor->mBody != NULL)
- hasSemicolon = !fieldDtor->mBody->IsMissingSemicolon();
- }
- if ((!hasSemicolon) && (ExpectTokenAfter(fieldDeclaration, BfToken_Semicolon, BfToken_Comma) != NULL))
- {
- // This gets taken later
- mVisitorPos.mReadPos--;
- }
- fieldDeclaration->mDocumentation = FindDocumentation(mTypeMemberNodeStart, fieldDeclaration, true);
- return fieldDeclaration;
- }
- BfAstNode* BfReducer::ReadTypeMember(BfTokenNode* tokenNode, bool declStarted, int depth, BfAstNode* deferredHeadNode)
- {
- BfToken token = tokenNode->GetToken();
- if (token == BfToken_Semicolon)
- return tokenNode;
- if (token == BfToken_LBracket)
- {
- auto attributes = CreateAttributeDirective(tokenNode);
- if (attributes == NULL)
- return NULL;
- auto nextNode = mVisitorPos.GetNext();
- if (nextNode == NULL)
- {
- FailAfter("Expected member", attributes);
- return NULL;
- }
- SetAndRestoreValue<BfAstNode*> prevTypeMemberNodeStart(mTypeMemberNodeStart, attributes, !declStarted);
- mVisitorPos.MoveNext();
- auto memberNode = ReadTypeMember(nextNode, true, depth, (deferredHeadNode != NULL) ? deferredHeadNode : attributes);
- if (memberNode == NULL)
- return NULL;
- if (auto enumCaseDecl = BfNodeDynCast<BfEnumCaseDeclaration>(memberNode))
- {
- if (!enumCaseDecl->mEntries.IsEmpty())
- {
- enumCaseDecl->mSrcStart = attributes->mSrcStart;
- enumCaseDecl->mEntries[0]->mAttributes = attributes;
- enumCaseDecl->mEntries[0]->mSrcStart = attributes->mSrcStart;
- return enumCaseDecl;
- }
- }
- auto member = BfNodeDynCast<BfMemberDeclaration>(memberNode);
- if (member == NULL)
- {
- if (auto innerType = BfNodeDynCast<BfTypeDeclaration>(memberNode))
- {
- ReplaceNode(attributes, innerType);
- innerType->mAttributes = attributes;
- return innerType;
- }
- Fail("Invalid target for attributes", memberNode);
- return memberNode;
- }
- memberNode->mTriviaStart = attributes->mTriviaStart;
- memberNode->mSrcStart = attributes->mSrcStart;
- if (auto fieldDecl = BfNodeDynCast<BfFieldDeclaration>(member))
- {
- if (CheckInlineTypeRefAttribute(fieldDecl->mTypeRef, attributes))
- {
- return member;
- }
- }
- if (auto methodDecl = BfNodeDynCast<BfMethodDeclaration>(member))
- {
- if (CheckInlineTypeRefAttribute(methodDecl->mReturnType, attributes))
- {
- return member;
- }
- }
- ReplaceNode(attributes, member);
- member->mAttributes = attributes;
- return member;
- }
- if (token == BfToken_Operator)
- {
- auto operatorDecl = mAlloc->Alloc<BfOperatorDeclaration>();
- BfDeferredAstSizedArray<BfParameterDeclaration*> params(operatorDecl->mParams, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(operatorDecl->mCommas, mAlloc);
- ReplaceNode(tokenNode, operatorDecl);
- operatorDecl->mOperatorToken = tokenNode;
- auto typeRef = CreateTypeRefAfter(operatorDecl);
- if (typeRef == NULL)
- return operatorDecl;
- MEMBER_SET_CHECKED(operatorDecl, mReturnType, typeRef);
- CheckMultiuseAttributeTypeRef(operatorDecl->mReturnType);
- operatorDecl->mIsConvOperator = true;
- ParseMethod(operatorDecl, ¶ms, &commas);
- return operatorDecl;
- }
- if (token == BfToken_This)
- {
- auto ctorDecl = mAlloc->Alloc<BfConstructorDeclaration>();
- BfDeferredAstSizedArray<BfParameterDeclaration*> params(ctorDecl->mParams, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(ctorDecl->mCommas, mAlloc);
- ctorDecl->mReturnType = NULL;
- ReplaceNode(tokenNode, ctorDecl);
- MEMBER_SET(ctorDecl, mThisToken, tokenNode);
- if (auto block = BfNodeDynCast<BfBlock>(mVisitorPos.GetNext()))
- {
- mVisitorPos.MoveNext();
- MEMBER_SET(ctorDecl, mBody, block);
- if (IsNodeRelevant(ctorDecl))
- {
- SetAndRestoreValue<BfMethodDeclaration*> prevMethodDeclaration(mCurMethodDecl, ctorDecl);
- HandleBlock(block);
- }
- }
- else
- ParseMethod(ctorDecl, ¶ms, &commas);
- return ctorDecl;
- }
- if (token == BfToken_Tilde)
- {
- auto thisToken = ExpectTokenAfter(tokenNode, BfToken_This);
- if (thisToken == NULL)
- {
- auto nextNode = mVisitorPos.GetNext();
- auto nameIdentifier = BfNodeDynCast<BfIdentifierNode>(nextNode);
- if (nameIdentifier != NULL)
- {
- // Eat DTOR name
- AddErrorNode(nameIdentifier);
- //nameIdentifier->RemoveSelf();
- }
- else
- {
- //AddErrorNode(tokenNode);
- //return NULL;
- }
- AddErrorNode(tokenNode);
- return NULL;
- }
- auto dtorDecl = mAlloc->Alloc<BfDestructorDeclaration>();
- BfDeferredAstSizedArray<BfParameterDeclaration*> params(dtorDecl->mParams, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(dtorDecl->mCommas, mAlloc);
- dtorDecl->mReturnType = NULL;
- ReplaceNode(tokenNode, dtorDecl);
- dtorDecl->mTildeToken = tokenNode;
- if (thisToken != NULL)
- {
- MEMBER_SET(dtorDecl, mThisToken, thisToken);
- }
- ParseMethod(dtorDecl, ¶ms, &commas);
- return dtorDecl;
- }
- if (token == BfToken_Mixin)
- {
- auto methodDecl = mAlloc->Alloc<BfMethodDeclaration>();
- BfDeferredAstSizedArray<BfParameterDeclaration*> params(methodDecl->mParams, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(methodDecl->mCommas, mAlloc);
- ReplaceNode(tokenNode, methodDecl);
- methodDecl->mDocumentation = FindDocumentation(methodDecl);
- methodDecl->mMixinSpecifier = tokenNode;
- //mVisitorPos.MoveNext();
- auto nameNode = ExpectIdentifierAfter(methodDecl);
- if (nameNode != NULL)
- {
- MEMBER_SET(methodDecl, mNameNode, nameNode);
- auto nextNode = mVisitorPos.GetNext();
- if ((tokenNode = BfNodeDynCast<BfTokenNode>(nextNode)))
- {
- if (tokenNode->GetToken() == BfToken_LChevron)
- {
- auto genericParams = CreateGenericParamsDeclaration(tokenNode);
- if (genericParams != NULL)
- {
- MEMBER_SET(methodDecl, mGenericParams, genericParams);
- }
- }
- }
- ParseMethod(methodDecl, ¶ms, &commas);
- }
- return methodDecl;
- }
- if (token == BfToken_Case)
- {
- auto enumCaseDecl = mAlloc->Alloc<BfEnumCaseDeclaration>();
- BfDeferredAstSizedArray<BfFieldDeclaration*> entries(enumCaseDecl->mEntries, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(enumCaseDecl->mCommas, mAlloc);
- ReplaceNode(tokenNode, enumCaseDecl);
- enumCaseDecl->mCaseToken = tokenNode;
- while (true)
- {
- auto caseName = ExpectIdentifierAfter(enumCaseDecl);
- if (caseName == NULL)
- break;
- auto enumEntry = mAlloc->Alloc<BfEnumEntryDeclaration>();
- ReplaceNode(caseName, enumEntry);
- enumEntry->mNameNode = caseName;
- entries.push_back(enumEntry);
- tokenNode = ExpectTokenAfter(enumEntry, BfToken_Comma, BfToken_AssignEquals, BfToken_LParen, BfToken_Semicolon);
- if ((tokenNode != NULL) && (tokenNode->GetToken() == BfToken_LParen))
- {
- auto typeRef = CreateTypeRef(tokenNode, CreateTypeRefFlags_AllowSingleMemberTuple);
- tokenNode = NULL;
- auto tupleType = BfNodeDynCast<BfTupleTypeRef>(typeRef);
- if (tupleType != NULL)
- {
- MEMBER_SET(enumEntry, mTypeRef, tupleType);
- tokenNode = ExpectTokenAfter(enumEntry, BfToken_Comma, BfToken_AssignEquals, BfToken_Semicolon);
- }
- }
- if ((tokenNode != NULL) && (tokenNode->GetToken() == BfToken_AssignEquals))
- {
- MEMBER_SET(enumEntry, mEqualsNode, tokenNode);
- tokenNode = NULL;
- auto initializer = CreateExpressionAfter(enumEntry);
- if (initializer != NULL)
- {
- MEMBER_SET(enumEntry, mInitializer, initializer);
- tokenNode = ExpectTokenAfter(enumEntry, BfToken_Comma, BfToken_Semicolon);
- }
- }
- MoveNode(enumEntry, enumCaseDecl);
- if (tokenNode == NULL)
- return enumCaseDecl;
- if (tokenNode->GetToken() == BfToken_Semicolon)
- {
- mVisitorPos.mReadPos--;
- return enumCaseDecl;
- }
- MoveNode(tokenNode, enumCaseDecl);
- commas.push_back(tokenNode);
- }
- return enumCaseDecl;
- }
- auto nextNode = mVisitorPos.GetNext();
- if (nextNode == NULL)
- FailAfter("Type expected", tokenNode);
- if ((token == BfToken_Struct) || (token == BfToken_Enum) || (token == BfToken_Class) || (token == BfToken_Delegate) ||
- (token == BfToken_Function) || (token == BfToken_Interface) || (token == BfToken_Extension) || (token == BfToken_TypeAlias))
- {
- mVisitorPos.mReadPos -= depth;
- BfAstNode* startNode = mVisitorPos.GetCurrent();
- auto startToken = BfNodeDynCast<BfTokenNode>(startNode);
- auto topLevelObject = CreateTopLevelObject(startToken, NULL, deferredHeadNode);
- auto typeDecl = BfNodeDynCast<BfTypeDeclaration>(topLevelObject);
- if (typeDecl == NULL)
- {
- AddErrorNode(tokenNode);
- return NULL;
- }
- return typeDecl;
- }
- if (token == BfToken_Comma)
- {
- auto prevNode = mVisitorPos.Get(mVisitorPos.mWritePos - 1);
- auto prevFieldDecl = BfNodeDynCast<BfFieldDeclaration>(prevNode);
- if (prevFieldDecl != NULL)
- {
- auto nameIdentifier = ExpectIdentifierAfter(tokenNode);
- if (nameIdentifier == NULL)
- {
- AddErrorNode(tokenNode);
- return NULL;
- }
- return CreateFieldDeclaration(tokenNode, prevFieldDecl->mTypeRef, nameIdentifier, prevFieldDecl);
- }
- }
- switch (token)
- {
- case BfToken_Sealed:
- case BfToken_Static:
- case BfToken_Const:
- case BfToken_Mut:
- case BfToken_Public:
- case BfToken_Protected:
- case BfToken_Private:
- case BfToken_Internal:
- case BfToken_Virtual:
- case BfToken_Override:
- case BfToken_Abstract:
- case BfToken_Concrete:
- case BfToken_Append:
- case BfToken_Extern:
- case BfToken_New:
- case BfToken_Implicit:
- case BfToken_Explicit:
- case BfToken_ReadOnly:
- case BfToken_Inline:
- case BfToken_Using:
- case BfToken_Volatile:
- break;
- default:
- AddErrorNode(tokenNode);
- Fail("Unexpected token", tokenNode);
- return NULL;
- break;
- }
- int startNodeIdx = gAssertCurrentNodeIdx;
- BfAstNode* typeMember = NULL;
- nextNode = mVisitorPos.GetNext();
- if (nextNode != NULL)
- {
- if (auto nextTokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if ((nextTokenNode->mToken == BfToken_LBracket) && (depth > 0))
- {
- // We can't apply this to a custom attribute
- AddErrorNode(tokenNode);
- Fail("Unexpected token", tokenNode);
- return NULL;
- }
- }
- mVisitorPos.MoveNext();
- typeMember = ReadTypeMember(nextNode, true, depth + 1);
- }
- auto memberDecl = BfNodeDynCast<BfMemberDeclaration>(typeMember);
- if (memberDecl == NULL) // May be an embedded type
- {
- if (auto typeDecl = BfNodeDynCast<BfTypeDeclaration>(typeMember))
- return typeMember;
- }
- if (typeMember == NULL)
- {
- auto propertyDeclaration = mAlloc->Alloc<BfPropertyDeclaration>();
- ReplaceNode(tokenNode, propertyDeclaration);
- propertyDeclaration->mDocumentation = FindDocumentation(propertyDeclaration);
- typeMember = memberDecl = propertyDeclaration;
- }
- if (memberDecl == NULL)
- return NULL;
- if (token == BfToken_Static)
- {
- if (memberDecl->mStaticSpecifier != NULL)
- {
- AddErrorNode(memberDecl->mStaticSpecifier);
- Fail("Static already specified", memberDecl->mStaticSpecifier);
- }
- MEMBER_SET(memberDecl, mStaticSpecifier, tokenNode);
- auto fieldDecl = BfNodeDynCast<BfFieldDeclaration>(memberDecl);
- if (fieldDecl != NULL)
- {
- if ((fieldDecl->mStaticSpecifier != NULL) && (fieldDecl->mConstSpecifier != NULL) && (fieldDecl->mConstSpecifier->mToken == BfToken_Const))
- Fail("Cannot use 'static' and 'const' together", fieldDecl);
- }
- return memberDecl;
- }
- if ((token == BfToken_Public) ||
- (token == BfToken_Protected) ||
- (token == BfToken_Private) ||
- (token == BfToken_Internal))
- {
- if (auto fieldDecl = BfNodeDynCast<BfFieldDeclaration>(memberDecl))
- {
- if (auto usingSpecifier = BfNodeDynCastExact<BfUsingSpecifierNode>(fieldDecl->mConstSpecifier))
- {
- SetProtection(memberDecl, usingSpecifier->mProtection, tokenNode);
- usingSpecifier->mTriviaStart = tokenNode->mTriviaStart;
- return memberDecl;
- }
- }
- SetProtection(memberDecl, memberDecl->mProtectionSpecifier, tokenNode);
- return memberDecl;
- }
- if (auto methodDecl = BfNodeDynCast<BfMethodDeclaration>(memberDecl))
- {
- if ((token == BfToken_Virtual) ||
- (token == BfToken_Override) ||
- (token == BfToken_Abstract) ||
- (token == BfToken_Concrete))
- {
- if (methodDecl->mVirtualSpecifier != NULL)
- {
- AddErrorNode(methodDecl->mVirtualSpecifier);
- if (methodDecl->mVirtualSpecifier->GetToken() == tokenNode->GetToken())
- Fail(StrFormat("Already specified '%s'", BfTokenToString(tokenNode->GetToken())), methodDecl->mVirtualSpecifier);
- else
- Fail(StrFormat("Cannot specify both '%s' and '%s'", BfTokenToString(methodDecl->mVirtualSpecifier->GetToken()), BfTokenToString(tokenNode->GetToken())), methodDecl->mVirtualSpecifier);
- }
- MEMBER_SET(methodDecl, mVirtualSpecifier, tokenNode);
- return memberDecl;
- }
- if (token == BfToken_Extern)
- {
- if (methodDecl->mExternSpecifier != NULL)
- {
- AddErrorNode(methodDecl->mExternSpecifier);
- Fail("Extern already specified", methodDecl->mExternSpecifier);
- }
- MEMBER_SET(methodDecl, mExternSpecifier, tokenNode);
- return memberDecl;
- }
- if (token == BfToken_New)
- {
- if (methodDecl->mNewSpecifier != NULL)
- {
- AddErrorNode(methodDecl->mNewSpecifier);
- Fail("New already specified", methodDecl->mNewSpecifier);
- }
- MEMBER_SET(methodDecl, mNewSpecifier, tokenNode);
- return memberDecl;
- }
- if (token == BfToken_Mut)
- {
- if (methodDecl->mMutSpecifier != NULL)
- {
- AddErrorNode(methodDecl->mMutSpecifier);
- Fail("Mut already specified", methodDecl->mMutSpecifier);
- }
- MEMBER_SET(methodDecl, mMutSpecifier, tokenNode);
- return memberDecl;
- }
- if (token == BfToken_ReadOnly)
- {
- if (methodDecl->mReadOnlySpecifier == NULL)
- {
- MEMBER_SET(methodDecl, mReadOnlySpecifier, tokenNode);
- }
- return memberDecl;
- }
- }
- if (auto operatorDecl = BfNodeDynCast<BfOperatorDeclaration>(memberDecl))
- {
- if ((token == BfToken_Implicit) ||
- (token == BfToken_Explicit))
- {
- if (operatorDecl->mExplicitToken != NULL)
- {
- AddErrorNode(operatorDecl->mExplicitToken);
- Fail(StrFormat("'%s' already specified", BfTokenToString(operatorDecl->mExplicitToken->GetToken())), operatorDecl->mExplicitToken);
- }
- MEMBER_SET(operatorDecl, mExplicitToken, tokenNode);
- return memberDecl;
- }
- }
- if (auto propDecl = BfNodeDynCast<BfPropertyDeclaration>(memberDecl))
- {
- if ((token == BfToken_Virtual) ||
- (token == BfToken_Override) ||
- (token == BfToken_Abstract) ||
- (token == BfToken_Concrete))
- {
- if (propDecl->mVirtualSpecifier != NULL)
- {
- AddErrorNode(propDecl->mVirtualSpecifier);
- if (propDecl->mVirtualSpecifier->GetToken() == token)
- Fail(StrFormat("Already specified '%s'", BfTokenToString(token)), propDecl->mVirtualSpecifier);
- else
- Fail(StrFormat("Cannot specify both '%s' and '%s'", BfTokenToString(propDecl->mVirtualSpecifier->GetToken()), BfTokenToString(token)), propDecl->mVirtualSpecifier);
- }
- MEMBER_SET(propDecl, mVirtualSpecifier, tokenNode);
- return memberDecl;
- }
- }
- if (auto fieldDecl = BfNodeDynCast<BfFieldDeclaration>(memberDecl))
- {
- if (token == BfToken_Override)
- {
- // Must be typing an 'override' over a field declaration
- auto propDecl = mAlloc->Alloc<BfPropertyDeclaration>();
- propDecl->mVirtualSpecifier = tokenNode;
- typeMember = memberDecl = propDecl;
- }
- bool handled = false;
- if (token == BfToken_Const)
- {
- if ((fieldDecl->mConstSpecifier != NULL) && (fieldDecl->mConstSpecifier->mToken == BfToken_Using))
- {
- Fail("Const cannot be used with 'using' specified", tokenNode);
- }
- else if (fieldDecl->mConstSpecifier != NULL)
- {
- Fail("Const already specified", tokenNode);
- }
- MEMBER_SET(fieldDecl, mConstSpecifier, tokenNode);
- handled = true;
- }
- if (token == BfToken_Using)
- {
- if ((fieldDecl->mConstSpecifier != NULL) && (fieldDecl->mConstSpecifier->mToken == BfToken_Const))
- {
- Fail("Const cannot be used with 'using' specified", tokenNode);
- }
- else if (fieldDecl->mConstSpecifier != NULL)
- {
- Fail("Using already specified", tokenNode);
- }
- auto usingSpecifier = mAlloc->Alloc<BfUsingSpecifierNode>();
- ReplaceNode(tokenNode, usingSpecifier);
- MEMBER_SET(usingSpecifier, mUsingToken, tokenNode);
- MEMBER_SET(fieldDecl, mConstSpecifier, usingSpecifier);
- handled = true;
- }
- if (token == BfToken_ReadOnly)
- {
- if (fieldDecl->mReadOnlySpecifier == NULL)
- {
- MEMBER_SET(fieldDecl, mReadOnlySpecifier, tokenNode);
- }
- handled = true;
- }
- if (token == BfToken_Inline)
- {
- MEMBER_SET(fieldDecl, mReadOnlySpecifier, tokenNode);
- handled = true;
- }
- if (token == BfToken_Volatile)
- {
- MEMBER_SET(fieldDecl, mVolatileSpecifier, tokenNode);
- handled = true;
- }
- if (token == BfToken_Extern)
- {
- if ((fieldDecl->mExternSpecifier != NULL) && (fieldDecl->mExternSpecifier->mToken == BfToken_Append))
- {
- Fail("Extern cannot be used with 'append' specified", tokenNode);
- }
- else if (fieldDecl->mExternSpecifier != NULL)
- {
- Fail("Extern already specified", tokenNode);
- }
- MEMBER_SET(fieldDecl, mExternSpecifier, tokenNode);
- handled = true;
- }
- if (token == BfToken_Append)
- {
- if ((fieldDecl->mExternSpecifier != NULL) && (fieldDecl->mExternSpecifier->mToken == BfToken_Extern))
- {
- Fail("Append cannot be used with 'extern' specified", tokenNode);
- }
- else if (fieldDecl->mExternSpecifier != NULL)
- {
- Fail("Append already specified", tokenNode);
- }
- MEMBER_SET(fieldDecl, mExternSpecifier, tokenNode);
- handled = true;
- }
- if (token == BfToken_New)
- {
- if (fieldDecl->mNewSpecifier != NULL)
- {
- Fail("New already specified", tokenNode);
- }
- MEMBER_SET(fieldDecl, mNewSpecifier, tokenNode);
- handled = true;
- }
- if ((fieldDecl->mStaticSpecifier != NULL) && (fieldDecl->mConstSpecifier != NULL) && (fieldDecl->mConstSpecifier->mToken == BfToken_Const))
- Fail("Cannot use 'static' and 'const' together", fieldDecl);
- if ((fieldDecl->mReadOnlySpecifier != NULL) && (fieldDecl->mConstSpecifier != NULL) && (fieldDecl->mConstSpecifier->mToken == BfToken_Const))
- Fail("Cannot use 'readonly' and 'const' together", fieldDecl);
- if ((fieldDecl->mVolatileSpecifier != NULL) && (fieldDecl->mConstSpecifier != NULL) && (fieldDecl->mConstSpecifier->mToken == BfToken_Const))
- Fail("Cannot use 'volatile' and 'const' together", fieldDecl);
- if (handled)
- return fieldDecl;
- }
- // Eat node
- if (memberDecl != NULL)
- ReplaceNode(tokenNode, memberDecl);
- Fail("Invalid token", tokenNode);
- return memberDecl;
- }
- void BfReducer::ReadPropertyBlock(BfPropertyDeclaration* propertyDeclaration, BfBlock* block)
- {
- SetAndRestoreValue<BfVisitorPos> prevVisitorPos(mVisitorPos, BfVisitorPos(block));
- BfDeferredAstSizedArray<BfPropertyMethodDeclaration*> methods(propertyDeclaration->mMethods, mAlloc);
- bool hadGet = false;
- bool hadSet = false;
- while (true)
- {
- BfAstNode* protectionSpecifier = NULL;
- BfAttributeDirective* attributes = NULL;
- auto child = mVisitorPos.GetNext();
- if (child == NULL)
- break;
- String accessorName;
- BfTokenNode* mutSpecifier = NULL;
- BfTokenNode* refSpecifier = NULL;
- while (true)
- {
- auto tokenNode = BfNodeDynCast<BfTokenNode>(child);
- if (tokenNode == NULL)
- break;
- BfToken token = tokenNode->GetToken();
- if (token == BfToken_LBracket)
- {
- mVisitorPos.MoveNext();
- attributes = CreateAttributeDirective(tokenNode);
- child = mVisitorPos.GetNext();
- }
- tokenNode = BfNodeDynCast<BfTokenNode>(child);
- if (tokenNode == NULL)
- break;
- token = tokenNode->GetToken();
- if ((token == BfToken_Private) ||
- (token == BfToken_Protected) ||
- (token == BfToken_Public) ||
- (token == BfToken_Internal))
- {
- SetProtection(NULL, protectionSpecifier, tokenNode);
- mVisitorPos.MoveNext();
- child = mVisitorPos.GetCurrent();
- }
- else if (token == BfToken_Mut)
- {
- Fail("'mut' must be specified after get/set", tokenNode);
- mutSpecifier = tokenNode;
- mVisitorPos.MoveNext();
- }
- else
- break;
- child = mVisitorPos.GetNext();
- }
- auto identifierNode = child;
- auto accessorIdentifier = BfNodeDynCast<BfIdentifierNode>(child);
- if (accessorIdentifier != NULL)
- {
- accessorName = accessorIdentifier->ToString();
- mVisitorPos.MoveNext();
- child = mVisitorPos.GetNext();
- }
- if (accessorName == "get")
- {
- // if (hadGet)
- // Fail("Only one 'get' method can be specified", accessorIdentifier);
- hadGet = true;
- }
- else if (accessorName == "set")
- {
- // if (hadSet)
- // Fail("Only one 'set' method can be specified", accessorIdentifier);
- hadSet = true;
- }
- else
- {
- auto refNode = child;
- if (refNode == NULL)
- refNode = block->mCloseBrace;
- Fail("Expected 'get' or 'set'", refNode);
- }
- BfAstNode* bodyAfterNode = accessorIdentifier;
- BfAstNode* body = NULL;
- auto tokenNode = BfNodeDynCast<BfTokenNode>(child);
- if ((tokenNode != NULL) && (tokenNode->GetToken() == BfToken_Ref) && (accessorName == "set"))
- {
- refSpecifier = tokenNode;
- bodyAfterNode = tokenNode;
- mVisitorPos.MoveNext();
- child = mVisitorPos.GetNext();
- tokenNode = BfNodeDynCast<BfTokenNode>(child);
- }
- if ((tokenNode != NULL) && (tokenNode->GetToken() == BfToken_Mut))
- {
- if (mutSpecifier != NULL)
- {
- Fail("'mut' already specified", mutSpecifier);
- }
- mutSpecifier = tokenNode;
- bodyAfterNode = tokenNode;
- mVisitorPos.MoveNext();
- child = mVisitorPos.GetNext();
- }
- bool handled = false;
- BfTokenNode* fatArrowToken = NULL;
- BfAstNode* endSemicolon = NULL;
- if ((tokenNode = BfNodeDynCast<BfTokenNode>(child)))
- {
- if ((tokenNode->GetToken() == BfToken_Semicolon))
- {
- handled = true;
- endSemicolon = tokenNode;
- mVisitorPos.MoveNext();
- }
- else if (tokenNode->mToken == BfToken_FatArrow)
- {
- handled = true;
- fatArrowToken = tokenNode;
- mVisitorPos.MoveNext();
- auto expr = CreateExpressionAfter(tokenNode);
- if (expr != NULL)
- {
- body = expr;
- endSemicolon = ExpectTokenAfter(expr, BfToken_Semicolon);
- }
- }
- }
- if (!handled)
- {
- if (bodyAfterNode != NULL)
- {
- body = ExpectBlockAfter(bodyAfterNode);
- }
- else
- {
- if (auto accessorBlock = BfNodeDynCast<BfBlock>(child))
- {
- body = accessorBlock;
- mVisitorPos.MoveNext();
- }
- if (body == NULL)
- {
- if (child != NULL)
- {
- Fail("Block expected", child);
- AddErrorNode(child);
- mVisitorPos.MoveNext();
- }
- }
- }
- }
- if (auto block = BfNodeDynCast<BfBlock>(body))
- {
- if (((attributes == NULL) && (IsNodeRelevant(block))) ||
- ((attributes != NULL) && (IsNodeRelevant(attributes, block))))
- {
- HandleBlock(block);
- }
- }
- if ((body == NULL) && (!handled))
- {
- if (protectionSpecifier != NULL)
- AddErrorNode(protectionSpecifier);
- if (accessorIdentifier != NULL)
- AddErrorNode(accessorIdentifier);
- if (mutSpecifier != NULL)
- AddErrorNode(mutSpecifier);
- if (refSpecifier != NULL)
- AddErrorNode(refSpecifier);
- continue;
- }
- auto method = mAlloc->Alloc<BfPropertyMethodDeclaration>();
- method->mPropertyDeclaration = propertyDeclaration;
- if (fatArrowToken != NULL)
- MEMBER_SET(method, mFatArrowToken, fatArrowToken);
- if (endSemicolon != NULL)
- MEMBER_SET(method, mEndSemicolon, endSemicolon);
- if (protectionSpecifier != NULL)
- MEMBER_SET(method, mProtectionSpecifier, protectionSpecifier);
- if (accessorIdentifier != NULL)
- MEMBER_SET(method, mNameNode, accessorIdentifier);
- if (body != NULL)
- {
- MEMBER_SET(method, mBody, body);
- }
- if (refSpecifier != NULL)
- MEMBER_SET(method, mSetRefSpecifier, refSpecifier);
- if (mutSpecifier != NULL)
- MEMBER_SET(method, mMutSpecifier, mutSpecifier);
- // if ((accessorBlock != NULL) && (IsNodeRelevant(propertyDeclaration)))
- // HandleBlock(accessorBlock);
- if (attributes != NULL)
- MEMBER_SET(method, mAttributes, attributes);
- methods.push_back(method);
- }
- }
- BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, bool declStarted, int depth, BfAstNode* deferredHeadNode)
- {
- // SetAndRestoreValue<BfAstNode*> prevTypeMemberNodeStart(mTypeMemberNodeStart, node, false);
- // if (depth == 0)
- // prevTypeMemberNodeStart.Set();
- if (mCurTypeDecl != NULL)
- {
- if (!AssertCurrentNode(node))
- return NULL;
- }
- BfTokenNode* refToken = NULL;
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(node))
- {
- BfToken token = tokenNode->GetToken();
- bool isTypeRef = false;
- if ((token == BfToken_Delegate) || (token == BfToken_Function))
- {
- // We need to differentiate between a delegate type reference and a delegate type declaration
- int endNodeIdx = -1;
- if (IsTypeReference(node, BfToken_LParen, -1, &endNodeIdx))
- {
- isTypeRef = true;
- }
- }
- if (BfTokenIsTypeDecl(token))
- {
- int endNodeIdx = -1;
- if (IsTypeReference(node, BfToken_None, -1, &endNodeIdx))
- {
- isTypeRef = true;
- }
- }
- if ((token == BfToken_LBracket) && (depth > 0))
- {
- // The only valid option is an attributed type reference
- isTypeRef = true;
- }
- if (isTypeRef)
- {
- // Handled below
- }
- else if ((token == BfToken_Ref) || (token == BfToken_Mut))
- {
- refToken = tokenNode;
- mVisitorPos.MoveNext();
- // Read type member
- }
- else if ((token == BfToken_Var) ||
- (token == BfToken_Let) ||
- (token == BfToken_AllocType) ||
- (token == BfToken_RetType) ||
- (token == BfToken_Nullable) ||
- (token == BfToken_Comptype) ||
- (token == BfToken_Decltype) ||
- (token == BfToken_LParen))
- {
- // Read type member
- }
- else
- {
- SetAndRestoreValue<BfAstNode*> prevTypeMemberNodeStart(mTypeMemberNodeStart, tokenNode, !declStarted);
- return ReadTypeMember(tokenNode, declStarted, depth, deferredHeadNode);
- }
- }
- else if (auto block = BfNodeDynCast<BfBlock>(node))
- {
- Fail("Expected method declaration", node);
- HandleBlock(block);
- auto methodDecl = mAlloc->Alloc<BfMethodDeclaration>();
- ReplaceNode(block, methodDecl);
- methodDecl->mDocumentation = FindDocumentation(methodDecl);
- methodDecl->mBody = block;
- return methodDecl;
- }
- BfTokenNode* indexerThisToken = NULL;
- bool isIndexProp = false;
- auto origNode = node;
- if (refToken != NULL)
- {
- auto nextNode = mVisitorPos.Get(mVisitorPos.mReadPos);
- if (nextNode != NULL)
- node = nextNode;
- }
- auto typeRef = CreateTypeRef(node);
- if (typeRef == NULL)
- {
- if (refToken != NULL)
- {
- AddErrorNode(refToken);
- if (mVisitorPos.Get(mVisitorPos.mReadPos) == node)
- {
- mVisitorPos.mReadPos--;
- return NULL;
- }
- }
- #ifdef BF_AST_HAS_PARENT_MEMBER
- BF_ASSERT(node->mParent != NULL);
- #endif
- AddErrorNode(node);
- return NULL;
- }
- if (refToken != NULL)
- typeRef = CreateRefTypeRef(typeRef, refToken);
- node = typeRef;
- auto nextNode = mVisitorPos.GetNext();
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (tokenNode->GetToken() == BfToken_This)
- indexerThisToken = tokenNode;
- }
- BfTokenNode* explicitInterfaceDot = NULL;
- BfTypeReference* explicitInterface = NULL;
- bool forceIsMethod = false;
- nextNode = mVisitorPos.GetNext();
- auto nameIdentifier = BfNodeDynCast<BfIdentifierNode>(nextNode);
- if (nameIdentifier != NULL)
- {
- mVisitorPos.MoveNext();
- bool doExplicitInterface = false;
- int endNodeIdx = -1;
- //mVisitorPos.mReadPos++;
- int nameIdentifierIdx = mVisitorPos.mReadPos;
- doExplicitInterface = IsTypeReference(nameIdentifier, BfToken_LParen, -1, &endNodeIdx);
- //mVisitorPos.mReadPos--;
- BfAstNode* endNode = mVisitorPos.Get(endNodeIdx);
- if (!doExplicitInterface)
- {
- if (auto endToken = BfNodeDynCastExact<BfTokenNode>(endNode))
- {
- if (endToken->GetToken() == BfToken_This)
- {
- indexerThisToken = endToken;
- doExplicitInterface = true;
- }
- }
- else if (auto block = BfNodeDynCastExact<BfBlock>(endNode))
- {
- doExplicitInterface = true; // Qualified property
- }
- }
- // Experimental 'more permissive' explicit interface check
- if (endNodeIdx != -1)
- doExplicitInterface = true;
- if (doExplicitInterface)
- {
- auto prevEndNode = mVisitorPos.Get(endNodeIdx - 1);
- int explicitInterfaceDotIdx = QualifiedBacktrack(prevEndNode, endNodeIdx - 1);
- if (explicitInterfaceDotIdx != -1)
- {
- explicitInterfaceDot = (BfTokenNode*)mVisitorPos.Get(explicitInterfaceDotIdx);
- mVisitorPos.mReadPos = nameIdentifierIdx;
- explicitInterfaceDot->SetToken(BfToken_Bar); // Hack to stop TypeRef parsing
- explicitInterface = CreateTypeRef(nameIdentifier);
- explicitInterfaceDot->SetToken(BfToken_Dot);
- if (explicitInterface == NULL)
- return NULL;
- mVisitorPos.mReadPos = explicitInterfaceDotIdx;
- if (indexerThisToken == NULL)
- {
- nameIdentifier = ExpectIdentifierAfter(explicitInterfaceDot);
- if (nameIdentifier == NULL)
- {
- // Looks like a method declaration
- auto methodDeclaration = mAlloc->Alloc<BfMethodDeclaration>();
- BfDeferredAstSizedArray<BfParameterDeclaration*> params(methodDeclaration->mParams, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(methodDeclaration->mCommas, mAlloc);
- if (typeRef != NULL)
- ReplaceNode(typeRef, methodDeclaration);
- else
- ReplaceNode(nameIdentifier, methodDeclaration);
- methodDeclaration->mDocumentation = FindDocumentation(mTypeMemberNodeStart);
- MEMBER_SET(methodDeclaration, mReturnType, typeRef);
- CheckMultiuseAttributeTypeRef(methodDeclaration->mReturnType);
- MEMBER_SET(methodDeclaration, mExplicitInterface, explicitInterface);
- MEMBER_SET(methodDeclaration, mExplicitInterfaceDotToken, explicitInterfaceDot);
- return methodDeclaration;
- }
- }
- }
- }
- }
- else if (auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (nextToken->mToken == BfToken_Operator)
- {
- auto operatorDecl = mAlloc->Alloc<BfOperatorDeclaration>();
- BfDeferredAstSizedArray<BfParameterDeclaration*> params(operatorDecl->mParams, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(operatorDecl->mCommas, mAlloc);
- ReplaceNode(typeRef, operatorDecl);
- operatorDecl->mReturnType = typeRef;
- CheckMultiuseAttributeTypeRef(operatorDecl->mReturnType);
- mVisitorPos.MoveNext();
- MEMBER_SET(operatorDecl, mOperatorToken, nextToken);
- bool hadFailedOperator = false;
- auto nextNode = mVisitorPos.GetNext();
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if ((nextToken->mToken == BfToken_Implicit) || (nextToken->mToken == BfToken_Explicit))
- {
- operatorDecl->mIsConvOperator = true;
- MEMBER_SET(operatorDecl, mOpTypeToken, nextToken);
- mVisitorPos.MoveNext();
- }
- else
- {
- operatorDecl->mBinOp = BfTokenToBinaryOp(nextToken->GetToken());
- if (operatorDecl->mBinOp != BfBinaryOp_None)
- {
- MEMBER_SET(operatorDecl, mOpTypeToken, nextToken);
- mVisitorPos.MoveNext();
- }
- else
- {
- operatorDecl->mUnaryOp = BfTokenToUnaryOp(nextToken->GetToken());
- if (operatorDecl->mUnaryOp != BfUnaryOp_None)
- {
- MEMBER_SET(operatorDecl, mOpTypeToken, nextToken);
- mVisitorPos.MoveNext();
- }
- else
- {
- operatorDecl->mAssignOp = BfTokenToAssignmentOp(nextToken->GetToken());
- if (operatorDecl->mAssignOp == BfAssignmentOp_Assign)
- {
- Fail("The assignment operator '=' cannot be overridden", nextToken);
- }
- if (operatorDecl->mAssignOp != BfAssignmentOp_None)
- {
- MEMBER_SET(operatorDecl, mOpTypeToken, nextToken);
- mVisitorPos.MoveNext();
- }
- else if (nextToken->GetToken() != BfToken_LParen)
- {
- Fail("Invalid operator type", nextToken);
- MEMBER_SET(operatorDecl, mOpTypeToken, nextToken);
- mVisitorPos.MoveNext();
- }
- }
- }
- }
- }
- if ((operatorDecl->mOpTypeToken == NULL) && (operatorDecl->mReturnType == NULL) && (!hadFailedOperator))
- {
- FailAfter("Expected operator type", operatorDecl);
- return NULL;
- }
- ParseMethod(operatorDecl, ¶ms, &commas);
- if (params.size() == 1)
- {
- if (operatorDecl->mBinOp == BfBinaryOp_Add)
- {
- operatorDecl->mBinOp = BfBinaryOp_None;
- operatorDecl->mUnaryOp = BfUnaryOp_Positive;
- }
- else if (operatorDecl->mBinOp == BfBinaryOp_Subtract)
- {
- operatorDecl->mBinOp = BfBinaryOp_None;
- operatorDecl->mUnaryOp = BfUnaryOp_Negate;
- }
- }
- return operatorDecl;
- }
- else if (nextToken->mToken == BfToken_LParen)
- {
- Fail("Method return type expected", node);
- nameIdentifier = BfNodeDynCast<BfIdentifierNode>(origNode);
- if (nameIdentifier != NULL)
- {
- // Remove TypeRef
- ReplaceNode(typeRef, nameIdentifier);
- typeRef = NULL;
- }
- }
- else if (nextToken->mToken == BfToken_Semicolon)
- {
- forceIsMethod = true;
- }
- }
- if ((nameIdentifier != NULL) || (forceIsMethod) || (indexerThisToken != NULL))
- {
- //ExtractExplicitInterfaceRef
- int blockAfterIdx = mVisitorPos.mReadPos + 1;
- BfAstNode* blockAfterPos = nameIdentifier;
- BfPropertyDeclaration* propertyDeclaration = NULL;
- if ((indexerThisToken != NULL) && (mVisitorPos.GetNext() != indexerThisToken))
- {
- indexerThisToken = NULL;
- }
- if (indexerThisToken != NULL)
- {
- auto indexerDeclaration = mAlloc->Alloc<BfIndexerDeclaration>();
- BfDeferredAstSizedArray<BfParameterDeclaration*> params(indexerDeclaration->mParams, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(indexerDeclaration->mCommas, mAlloc);
- ReplaceNode(typeRef, indexerDeclaration);
- indexerDeclaration->mTypeRef = typeRef;
- MEMBER_SET(indexerDeclaration, mThisToken, indexerThisToken);
- mVisitorPos.MoveNext();
- if (explicitInterface != NULL)
- {
- MEMBER_SET(indexerDeclaration, mExplicitInterface, explicitInterface);
- MEMBER_SET(indexerDeclaration, mExplicitInterfaceDotToken, explicitInterfaceDot);
- //mVisitorPos.mReadPos = endNodeIdx;
- }
- auto openToken = ExpectTokenAfter(indexerDeclaration, BfToken_LBracket);
- if (openToken == NULL)
- return indexerDeclaration;
- MEMBER_SET(indexerDeclaration, mOpenBracket, openToken);
- auto endToken = ParseMethodParams(indexerDeclaration, ¶ms, &commas, BfToken_RBracket, false);
- if (endToken == NULL)
- return indexerDeclaration;
- MEMBER_SET(indexerDeclaration, mCloseBracket, endToken);
- propertyDeclaration = indexerDeclaration;
- blockAfterPos = propertyDeclaration;
- mVisitorPos.MoveNext();
- blockAfterIdx = mVisitorPos.mReadPos + 1;
- }
- else
- {
- blockAfterPos = nameIdentifier;
- }
- nextNode = mVisitorPos.Get(blockAfterIdx);
- auto block = BfNodeDynCast<BfBlock>(nextNode);
- auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- bool isExprBodyProp = (tokenNode != NULL) && ((tokenNode->mToken == BfToken_FatArrow) || (tokenNode->mToken == BfToken_Mut));
- // Property.
- // If we don't have a token afterwards then still treat it as a property for autocomplete purposes
- if ((typeRef != NULL) &&
- ((block != NULL) || (tokenNode == NULL) || (isExprBodyProp)))
- {
- if (propertyDeclaration == NULL)
- {
- if ((block == NULL) && (!isExprBodyProp))
- {
- auto propDecl = mAlloc->Alloc<BfPropertyDeclaration>();
- ReplaceNode(typeRef, propDecl);
- propDecl->mDocumentation = FindDocumentation(mTypeMemberNodeStart);
- propDecl->mTypeRef = typeRef;
- CheckMultiuseAttributeTypeRef(propDecl->mTypeRef);
- if (explicitInterface != NULL)
- {
- MEMBER_SET(propDecl, mExplicitInterface, explicitInterface);
- MEMBER_SET(propDecl, mExplicitInterfaceDotToken, explicitInterfaceDot);
- }
- // Don't set the name identifier, this could be bogus
- //mVisitorPos.mReadPos--;
- // WHY did we want to not set this?
- // If we don't, then typing a new method name will end up treating the name node as a typeRef
- // which can autocomplete incorrectly
- MEMBER_SET(propDecl, mNameNode, nameIdentifier);
- return propDecl;
- }
- mVisitorPos.mReadPos = blockAfterIdx;
- propertyDeclaration = mAlloc->Alloc<BfPropertyDeclaration>();
- ReplaceNode(typeRef, propertyDeclaration);
- propertyDeclaration->mDocumentation = FindDocumentation(mTypeMemberNodeStart);
- propertyDeclaration->mTypeRef = typeRef;
- if (explicitInterface != NULL)
- {
- MEMBER_SET(propertyDeclaration, mExplicitInterface, explicitInterface);
- MEMBER_SET(propertyDeclaration, mExplicitInterfaceDotToken, explicitInterfaceDot);
- }
- MEMBER_SET(propertyDeclaration, mNameNode, nameIdentifier);
- //mVisitorPos.MoveNext();
- }
- else
- mVisitorPos.mReadPos = blockAfterIdx;
- if (block != NULL)
- {
- MEMBER_SET(propertyDeclaration, mDefinitionBlock, block);
- ReadPropertyBlock(propertyDeclaration, block);
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if (tokenNode->mToken == BfToken_AssignEquals)
- {
- MEMBER_SET(propertyDeclaration, mEqualsNode, tokenNode);
- mVisitorPos.MoveNext();
- auto initExpr = CreateExpressionAfter(propertyDeclaration);
- if (initExpr != NULL)
- {
- MEMBER_SET(propertyDeclaration, mInitializer, initExpr);
- }
- }
- }
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if (tokenNode->mToken == BfToken_Tilde)
- {
- auto fieldDtor = CreateFieldDtorDeclaration(propertyDeclaration);
- MEMBER_SET(propertyDeclaration, mFieldDtor, fieldDtor);
- }
- }
- }
- else if (isExprBodyProp)
- {
- BfDeferredAstSizedArray<BfPropertyMethodDeclaration*> methods(propertyDeclaration->mMethods, mAlloc);
- auto propertyBodyExpr = mAlloc->Alloc<BfPropertyBodyExpression>();
- ReplaceNode(tokenNode, propertyBodyExpr);
- BfTokenNode* mutSpecifier = NULL;
- if (tokenNode->mToken == BfToken_Mut)
- {
- MEMBER_SET(propertyBodyExpr, mMutSpecifier, tokenNode);
- tokenNode = ExpectTokenAfter(tokenNode, BfToken_FatArrow);
- }
- if (tokenNode != NULL)
- {
- MEMBER_SET(propertyBodyExpr, mFatTokenArrow, tokenNode);
- auto method = mAlloc->Alloc<BfPropertyMethodDeclaration>();
- method->mPropertyDeclaration = propertyDeclaration;
- method->mNameNode = propertyDeclaration->mNameNode;
- auto expr = CreateExpressionAfter(tokenNode);
- if (expr != NULL)
- {
- MEMBER_SET(method, mBody, expr);
- propertyDeclaration->SetSrcEnd(expr->GetSrcEnd());
- auto endSemicolon = ExpectTokenAfter(expr, BfToken_Semicolon);
- if (endSemicolon != NULL)
- MEMBER_SET(method, mEndSemicolon, endSemicolon);
- }
- methods.Add(method);
- }
- MEMBER_SET(propertyDeclaration, mDefinitionBlock, propertyBodyExpr);
- }
- return propertyDeclaration;
- }
- else if (propertyDeclaration != NULL)
- {
- // Failure case
- block = ExpectBlockAfter(blockAfterPos);
- BF_ASSERT(block == NULL);
- return propertyDeclaration;
- }
- //nextNode = mVisitorPos.Get(mVisitorPos.mReadPos + 2);
- /*if (tokenNode == NULL)
- {
- mVisitorPos.MoveNext();
- ExpectTokenAfter(nameIdentifier, BfToken_Semicolon);
- // Just 'eat' the typeRef by stuffing it into a property declaration
- auto fieldDecl = mAlloc->Alloc<BfPropertyDeclaration>();
- ReplaceNode(typeRef, fieldDecl);
- fieldDecl->mTypeRef = typeRef;
- return fieldDecl;
- }*/
- if (tokenNode == NULL)
- {
- auto fieldDecl = mAlloc->Alloc<BfPropertyDeclaration>();
- ReplaceNode(nameIdentifier, fieldDecl);
- fieldDecl->mDocumentation = FindDocumentation(mTypeMemberNodeStart);
- fieldDecl->mNameNode = nameIdentifier;
- return fieldDecl;
- }
- BfToken token = tokenNode->GetToken();
- if ((token == BfToken_LParen) ||
- (token == BfToken_LChevron))
- {
- if (token == BfToken_LChevron)
- {
- bool isTypeRef = IsTypeReference(nameIdentifier, BfToken_LParen);
- if (!isTypeRef)
- {
- bool onNewLine = false;
- auto src = nameIdentifier->GetSourceData();
- int srcStart = nameIdentifier->GetSrcStart();
- for (int srcIdx = typeRef->GetSrcEnd(); srcIdx < srcStart; srcIdx++)
- if (src->mSrc[srcIdx] == '\n')
- onNewLine = false;
- if (onNewLine)
- {
- // Actually it looks like a partially formed type declaration followed by a method
- // which returns a generic type
- FailAfter("Name expected", typeRef);
- auto fieldDecl = mAlloc->Alloc<BfFieldDeclaration>();
- ReplaceNode(typeRef, fieldDecl);
- fieldDecl->mDocumentation = FindDocumentation(mTypeMemberNodeStart);
- fieldDecl->mTypeRef = typeRef;
- CheckMultiuseAttributeTypeRef(fieldDecl->mTypeRef);
- return fieldDecl;
- }
- }
- }
- // Looks like a method declaration
- auto methodDeclaration = mAlloc->Alloc<BfMethodDeclaration>();
- BfDeferredAstSizedArray<BfParameterDeclaration*> params(methodDeclaration->mParams, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(methodDeclaration->mCommas, mAlloc);
- if (typeRef != NULL)
- ReplaceNode(typeRef, methodDeclaration);
- else
- ReplaceNode(nameIdentifier, methodDeclaration);
- methodDeclaration->mDocumentation = FindDocumentation(mTypeMemberNodeStart);
- if (explicitInterface != NULL)
- {
- MEMBER_SET(methodDeclaration, mExplicitInterface, explicitInterface);
- MEMBER_SET(methodDeclaration, mExplicitInterfaceDotToken, explicitInterfaceDot);
- }
- if (token == BfToken_LChevron)
- {
- auto genericParams = CreateGenericParamsDeclaration(tokenNode);
- if (genericParams != NULL)
- {
- MEMBER_SET(methodDeclaration, mGenericParams, genericParams);
- }
- }
- methodDeclaration->mReturnType = typeRef;
- CheckMultiuseAttributeTypeRef(methodDeclaration->mReturnType);
- MEMBER_SET_CHECKED(methodDeclaration, mNameNode, nameIdentifier);
- mCurMethodDecl = methodDeclaration;
- ParseMethod(methodDeclaration, ¶ms, &commas);
- mCurMethodDecl = NULL;
- return methodDeclaration;
- }
- return CreateFieldDeclaration(tokenNode, typeRef, nameIdentifier, NULL);
- }
- FailAfter("Member name expected", node);
- // Same fail case as "expected member declaration"
- auto fieldDecl = mAlloc->Alloc<BfPropertyDeclaration>();
- ReplaceNode(typeRef, fieldDecl);
- fieldDecl->mDocumentation = FindDocumentation(mTypeMemberNodeStart);
- fieldDecl->mTypeRef = typeRef;
- return fieldDecl;
- }
- BfInvocationExpression* BfReducer::CreateInvocationExpression(BfAstNode* target, CreateExprFlags createExprFlags)
- {
- auto tokenNode = ExpectTokenAfter(target, BfToken_LParen, BfToken_LChevron, BfToken_Bang);
- auto invocationExpr = mAlloc->Alloc<BfInvocationExpression>();
- BfDeferredAstSizedArray<BfExpression*> arguments(invocationExpr->mArguments, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(invocationExpr->mCommas, mAlloc);
- invocationExpr->mTarget = target;
- ReplaceNode(target, invocationExpr);
- if (tokenNode == NULL)
- return invocationExpr;
- if (tokenNode->GetToken() == BfToken_Bang)
- {
- MoveNode(tokenNode, invocationExpr);
- if (tokenNode->GetSrcEnd() == invocationExpr->mTarget->GetSrcEnd() + 1)
- {
- BfAstNode* target = invocationExpr->mTarget;
- while (true)
- {
- if (auto qualifiedNameNode = BfNodeDynCast<BfQualifiedNameNode>(target))
- target = qualifiedNameNode->mRight;
- else if (auto memberRefExpr = BfNodeDynCast<BfMemberReferenceExpression>(target))
- target = memberRefExpr->mMemberName;
- else if (auto attribIdentifierNode = BfNodeDynCast<BfAttributedIdentifierNode>(target))
- target = attribIdentifierNode->mIdentifier;
- else
- break;
- }
- if (target != NULL)
- {
- BF_ASSERT(tokenNode->GetSrcEnd() == target->GetSrcEnd() + 1);
- target->SetSrcEnd(tokenNode->GetSrcEnd());
- invocationExpr->mTarget->SetSrcEnd(tokenNode->GetSrcEnd());
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if ((nextToken->GetToken() == BfToken_Colon) || (nextToken->GetToken() == BfToken_ColonColon))
- {
- auto scopedInvocationTarget = CreateScopedInvocationTarget(invocationExpr->mTarget, nextToken);
- invocationExpr->SetSrcEnd(scopedInvocationTarget->GetSrcEnd());
- }
- }
- }
- }
- else
- Fail("No space allowed before token", tokenNode);
- tokenNode = ExpectTokenAfter(invocationExpr, BfToken_LParen, BfToken_LChevron);
- if (tokenNode == NULL)
- return invocationExpr;
- }
- if (tokenNode->GetToken() == BfToken_LChevron)
- {
- auto genericParamsDecl = CreateGenericArguments(tokenNode, true);
- MEMBER_SET_CHECKED(invocationExpr, mGenericArgs, genericParamsDecl);
- tokenNode = ExpectTokenAfter(invocationExpr, BfToken_LParen);
- }
- MEMBER_SET_CHECKED(invocationExpr, mOpenParen, tokenNode);
- tokenNode = ReadArguments(invocationExpr, invocationExpr, &arguments, &commas, BfToken_RParen, true);
- if (tokenNode != NULL)
- {
- MEMBER_SET(invocationExpr, mCloseParen, tokenNode);
- }
- return invocationExpr;
- }
- BfInitializerExpression* BfReducer::TryCreateInitializerExpression(BfAstNode* target)
- {
- auto block = BfNodeDynCast<BfBlock>(mVisitorPos.GetNext());
- if (block == NULL)
- return NULL;
- bool allowInitializerStatement = false;
- auto objectCreateExpr = BfNodeDynCast<BfObjectCreateExpression>(target);
- if (objectCreateExpr != NULL)
- allowInitializerStatement = true;
- mVisitorPos.MoveNext();
- auto initializerExpr = mAlloc->Alloc<BfInitializerExpression>();
- ReplaceNode(target, initializerExpr);
- initializerExpr->mTarget = target;
- MEMBER_SET(initializerExpr, mOpenBrace, block->mOpenBrace);
- SetAndRestoreValue<BfVisitorPos> prevVisitorPos(mVisitorPos, BfVisitorPos(block));
- bool isDone = !mVisitorPos.MoveNext();
- BfDeferredAstNodeSizedArray<BfExpression*> values(initializerExpr, initializerExpr->mValues, mAlloc);
- BfDeferredAstNodeSizedArray<BfTokenNode*> commas(initializerExpr, initializerExpr->mCommas, mAlloc);
- int initializerStartIdx = 0;
- int minTypeDeclEnd = 0;
-
- BfAstNode* nextNode = NULL;
- while (!isDone)
- {
- BfAstNode* node = mVisitorPos.GetCurrent();
- if (node == NULL)
- break;
- initializerExpr->mSrcEnd = node->mSrcEnd;
- if ((values.IsEmpty()) && (initializerExpr->mInlineTypeRef == NULL))
- {
- if ((allowInitializerStatement) && (!IsInitializerStatement(node)))
- {
- auto defBlock = mAlloc->Alloc<BfBlock>();
- ReplaceNode(block, defBlock);
- *defBlock = *block;
- auto typeDecl = mAlloc->Alloc<BfInitializerTypeDeclaration>();
- ReplaceNode(node, typeDecl);
- defBlock->mOpenBrace = NULL;
- MEMBER_SET(typeDecl, mDefineNode, defBlock);
- InitAnonymousType(typeDecl);
- HandleTypeDeclaration(typeDecl, NULL, NULL, true);
- initializerStartIdx = mVisitorPos.mWritePos;
- auto typeRef = mAlloc->Alloc<BfInlineTypeReference>();
- ReplaceNode(typeDecl, typeRef);
- typeRef->mTypeDeclaration = typeDecl;
- MEMBER_SET(initializerExpr, mInlineTypeRef, typeRef);
- if (objectCreateExpr != NULL)
- {
- BfDeferredAstSizedArray<BfTypeReference*> baseClasses(typeDecl->mBaseClasses, mAlloc);
- baseClasses.Add(objectCreateExpr->mTypeRef);
- }
-
- continue;
- }
- }
- auto expr = CreateExpression(node, BfReducer::CreateExprFlags_AllowAnonymousIndexer);
- isDone = !mVisitorPos.MoveNext();
- if (expr != NULL)
- values.Add(expr);
- else
- AddErrorNode(node);
- if (!isDone)
- {
- bool foundComma = false;
- node = mVisitorPos.GetCurrent();
- if (node != NULL)
- {
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(node))
- {
- if (tokenNode->mToken == BfToken_Comma)
- {
- foundComma = true;
- commas.Add(tokenNode);
- isDone = !mVisitorPos.MoveNext();
- }
- }
- if (!foundComma)
- Fail("Expected ','", node);
- }
- }
- }
- mVisitorPos.Trim();
- if (initializerExpr->mInlineTypeRef != NULL)
- {
- auto typeDecl = initializerExpr->mInlineTypeRef->mTypeDeclaration;
- if (initializerStartIdx != 0)
- {
- block->SetSize(initializerStartIdx);
- int srcEnd = block->mSrcEnd;
- if (initializerStartIdx > 0)
- srcEnd = block->mChildArr[initializerStartIdx - 1]->mSrcEnd;
- typeDecl->mDefineNode->mSrcEnd = srcEnd;
- typeDecl->mSrcEnd = srcEnd;
- }
- typeDecl->mSrcEnd = BF_MAX(typeDecl->mSrcEnd, minTypeDeclEnd);
- initializerExpr->mInlineTypeRef->mSrcEnd = typeDecl->mSrcEnd;
- }
- if (block->mCloseBrace != NULL)
- MEMBER_SET(initializerExpr, mCloseBrace, block->mCloseBrace);
- return initializerExpr;
- }
- BfDelegateBindExpression* BfReducer::CreateDelegateBindExpression(BfAstNode* allocNode)
- {
- auto delegateBindExpr = mAlloc->Alloc<BfDelegateBindExpression>();
- ReplaceNode(allocNode, delegateBindExpr);
- MEMBER_SET(delegateBindExpr, mNewToken, allocNode);
- auto tokenNode = ExpectTokenAfter(delegateBindExpr, BfToken_FatArrow);
- MEMBER_SET_CHECKED(delegateBindExpr, mFatArrowToken, tokenNode);
- auto expr = CreateExpressionAfter(delegateBindExpr);
- MEMBER_SET_CHECKED(delegateBindExpr, mTarget, expr);
- auto nextNode = mVisitorPos.GetNext();
- if ((tokenNode = BfNodeDynCast<BfTokenNode>(nextNode)))
- {
- if (tokenNode->GetToken() == BfToken_LChevron)
- {
- mVisitorPos.MoveNext();
- auto genericParamsDecl = CreateGenericArguments(tokenNode);
- MEMBER_SET_CHECKED(delegateBindExpr, mGenericArgs, genericParamsDecl);
- }
- }
- return delegateBindExpr;
- }
- BfLambdaBindExpression* BfReducer::CreateLambdaBindExpression(BfAstNode* allocNode, BfTokenNode* parenToken)
- {
- auto lambdaBindExpr = mAlloc->Alloc<BfLambdaBindExpression>();
- BfDeferredAstSizedArray<BfIdentifierNode*> params(lambdaBindExpr->mParams, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(lambdaBindExpr->mCommas, mAlloc);
- BfTokenNode* tokenNode;
- if (allocNode != NULL)
- {
- ReplaceNode(allocNode, lambdaBindExpr);
- MEMBER_SET(lambdaBindExpr, mNewToken, allocNode);
- tokenNode = ExpectTokenAfter(lambdaBindExpr, BfToken_LParen, BfToken_LBracket);
- }
- else
- {
- ReplaceNode(parenToken, lambdaBindExpr);
- tokenNode = parenToken;
- }
- if (tokenNode == NULL)
- return lambdaBindExpr;
- MEMBER_SET_CHECKED(lambdaBindExpr, mOpenParen, tokenNode);
- for (int paramIdx = 0; true; paramIdx++)
- {
- bool isRParen = false;
- auto nextNode = mVisitorPos.GetNext();
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- isRParen = tokenNode->GetToken() == BfToken_RParen;
- if (!isRParen)
- {
- auto nameIdentifier = ExpectIdentifierAfter(lambdaBindExpr, "parameter name");
- if (nameIdentifier == NULL)
- return lambdaBindExpr;
- MoveNode(nameIdentifier, lambdaBindExpr);
- params.push_back(nameIdentifier);
- }
- tokenNode = ExpectTokenAfter(lambdaBindExpr, BfToken_Comma, BfToken_RParen);
- if (tokenNode == NULL)
- return lambdaBindExpr;
- if (tokenNode->GetToken() == BfToken_RParen)
- {
- MEMBER_SET(lambdaBindExpr, mCloseParen, tokenNode);
- break;
- }
- MoveNode(tokenNode, lambdaBindExpr);
- commas.push_back(tokenNode);
- }
- tokenNode = ExpectTokenAfter(lambdaBindExpr, BfToken_FatArrow);
- MEMBER_SET_CHECKED(lambdaBindExpr, mFatArrowToken, tokenNode);
- auto nextNode = mVisitorPos.GetNext();
- auto block = BfNodeDynCast<BfBlock>(nextNode);
- if (block != NULL)
- {
- HandleBlock(block, true);
- mVisitorPos.MoveNext();
- MEMBER_SET_CHECKED(lambdaBindExpr, mBody, block);
- }
- else
- {
- auto expr = CreateExpressionAfter(lambdaBindExpr);
- MEMBER_SET_CHECKED(lambdaBindExpr, mBody, expr);
- }
- auto lambdaDtor = CreateFieldDtorDeclaration(lambdaBindExpr);
- if (lambdaDtor != NULL)
- {
- if ((mIsFieldInitializer) && (!mInParenExpr))
- {
- Fail("Ambiguous destructor: could be field destructor or lambda destructor. Disambiguate with parentheses, either '(lambda) ~ fieldDtor' or '(lambda ~ lambdaDtor)'", lambdaBindExpr);
- }
- lambdaBindExpr->mDtor = lambdaDtor;
- }
- return lambdaBindExpr;
- }
- BfCollectionInitializerExpression* BfReducer::CreateCollectionInitializerExpression(BfBlock* block)
- {
- auto arrayInitializerExpression = mAlloc->Alloc<BfCollectionInitializerExpression>();
- BfDeferredAstSizedArray<BfExpression*> values(arrayInitializerExpression->mValues, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(arrayInitializerExpression->mCommas, mAlloc);
- ReplaceNode(block, arrayInitializerExpression);
- MEMBER_SET(arrayInitializerExpression, mOpenBrace, block->mOpenBrace);
- if (block->mCloseBrace != NULL)
- MEMBER_SET(arrayInitializerExpression, mCloseBrace, block->mCloseBrace);
- block->mOpenBrace = NULL;
- block->mCloseBrace = NULL;
- SetAndRestoreValue<BfVisitorPos> prevVisitorPos(mVisitorPos, BfVisitorPos(block));
- bool isDone = !mVisitorPos.MoveNext();
- while (true)
- {
- auto head = mVisitorPos.GetCurrent();
- if (head == NULL)
- break;
- BfExpression* expression;
- if (auto innerBlock = BfNodeDynCast<BfBlock>(head))
- expression = CreateCollectionInitializerExpression(innerBlock);
- else
- expression = CreateExpression(head);
- if (expression == NULL)
- break;
- auto nextNode = mVisitorPos.GetNext();
- bool atEnd = nextNode == NULL;
- auto tokenNode = atEnd ? NULL : ExpectTokenAfter(expression, BfToken_Comma, BfToken_RBrace);
- MoveNode(expression, arrayInitializerExpression);
- values.push_back(expression);
- if ((!atEnd) && (tokenNode == NULL))
- break;
- if (atEnd)
- break;
- MoveNode(tokenNode, arrayInitializerExpression);
- commas.push_back(tokenNode);
- isDone = !mVisitorPos.MoveNext();
- }
- return arrayInitializerExpression;
- }
- BfCollectionInitializerExpression* BfReducer::CreateCollectionInitializerExpression(BfTokenNode* openToken)
- {
- auto arrayInitializerExpression = mAlloc->Alloc<BfCollectionInitializerExpression>();
- BfDeferredAstSizedArray<BfExpression*> values(arrayInitializerExpression->mValues, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(arrayInitializerExpression->mCommas, mAlloc);
- ReplaceNode(openToken, arrayInitializerExpression);
- MEMBER_SET(arrayInitializerExpression, mOpenBrace, openToken);
- bool isDone = !mVisitorPos.MoveNext();
- while (true)
- {
- auto head = mVisitorPos.GetCurrent();
- if (head == NULL)
- break;
- BfExpression* expression;
- if (auto innerBlock = BfNodeDynCast<BfBlock>(head))
- expression = CreateCollectionInitializerExpression(innerBlock);
- else
- {
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(head))
- {
- if (tokenNode->mToken == BfToken_RParen)
- {
- MEMBER_SET(arrayInitializerExpression, mCloseBrace, tokenNode);
- return arrayInitializerExpression;
- }
- }
- expression = CreateExpression(head);
- }
- if (expression == NULL)
- {
- arrayInitializerExpression->mSrcEnd = head->mSrcEnd;
- break;
- }
- auto nextNode = mVisitorPos.GetNext();
- bool atEnd = nextNode == NULL;
- auto tokenNode = atEnd ? NULL : ExpectTokenAfter(expression, BfToken_Comma, BfToken_RParen);
- MoveNode(expression, arrayInitializerExpression);
- values.push_back(expression);
- if ((!atEnd) && (tokenNode == NULL))
- break;
- if (atEnd)
- break;
- MoveNode(tokenNode, arrayInitializerExpression);
- if (tokenNode->GetToken() == BfToken_RParen)
- {
- MEMBER_SET(arrayInitializerExpression, mCloseBrace, tokenNode);
- break;
- }
- commas.push_back(tokenNode);
- isDone = !mVisitorPos.MoveNext();
- }
- return arrayInitializerExpression;
- }
- BfScopedInvocationTarget* BfReducer::CreateScopedInvocationTarget(BfAstNode*& targetRef, BfTokenNode* colonToken)
- {
- auto scopedInvocationTarget = mAlloc->Alloc<BfScopedInvocationTarget>();
- ReplaceNode(targetRef, scopedInvocationTarget);
- scopedInvocationTarget->mTarget = targetRef;
- targetRef = scopedInvocationTarget;
- if (colonToken == NULL)
- return scopedInvocationTarget;
- MEMBER_SET(scopedInvocationTarget, mColonToken, colonToken);
- mVisitorPos.MoveNext();
- if (colonToken->mToken == BfToken_ColonColon)
- return scopedInvocationTarget;
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if ((nextToken->GetToken() == BfToken_Colon) || (nextToken->GetToken() == BfToken_Mixin))
- {
- MEMBER_SET(scopedInvocationTarget, mScopeName, nextToken);
- mVisitorPos.MoveNext();
- }
- }
- else if (auto identifier = BfNodeDynCast<BfIdentifierNode>(mVisitorPos.GetNext()))
- {
- MEMBER_SET(scopedInvocationTarget, mScopeName, identifier);
- mVisitorPos.MoveNext();
- }
- if (scopedInvocationTarget->mScopeName == NULL)
- {
- FailAfter("Expected scope name", scopedInvocationTarget);
- }
- return scopedInvocationTarget;
- }
- void BfReducer::InitAnonymousType(BfTypeDeclaration* typeDecl)
- {
- int blockId = 0;
- if (auto block = BfNodeDynCast<BfBlock>(typeDecl->mDefineNode))
- {
- blockId = block->mParserBlockId;
- }
- else
- {
- auto parser = mSource->ToParser();
- if (parser != NULL)
- blockId = parser->mCurBlockId + typeDecl->mSrcStart;
- }
- String name;
- auto parserData = typeDecl->GetParserData();
- name = "_Anon_";
- auto parseFileData = parserData->mParseFileData;
- int uniqueId = parseFileData->GetUniqueId(blockId);
- name += StrFormat("%d", uniqueId);
- int len = (int)name.length() + 1;
- typeDecl->mAnonymousName = (char*)mAlloc->AllocBytes(len);
- memcpy(typeDecl->mAnonymousName, name.c_str(), len);
- auto parser = typeDecl->GetParser();
- if ((parser != NULL) && (parser->mIsEmitted))
- {
- Fail("Type declarations are not allowed in emitted code", typeDecl);
- }
- else if (mCurTypeState != NULL)
- {
- mCurTypeState->mAnonymousTypeDecls.Add(typeDecl);
- }
- else
- {
- Fail("Invalid use of anonymous type declaration", typeDecl);
- }
- }
- bool BfReducer::CheckInlineTypeRefAttribute(BfAstNode* typeRef, BfAttributeDirective* attributes)
- {
- if (attributes == NULL)
- return false;
- if (auto inlineTypeRef = BfNodeDynCast<BfInlineTypeReference>(typeRef))
- {
- auto checkAttribute = attributes;
- while (checkAttribute != NULL)
- {
- checkAttribute->mIsMultiUse = true;
- checkAttribute = checkAttribute->mNextAttribute;
- }
- auto typeDecl = inlineTypeRef->mTypeDeclaration;
- typeDecl->mSrcStart = attributes->mSrcStart;
- typeDecl->mTriviaStart = typeDecl->mSrcStart;
- typeDecl->mAttributes = attributes;
- inlineTypeRef->mTriviaStart = attributes->mTriviaStart;
- inlineTypeRef->mSrcStart = attributes->mSrcStart;
- if ((typeDecl->mIgnoreDeclaration) && (IsNodeRelevant(typeDecl)))
- typeDecl->mIgnoreDeclaration = false;
- return true;
- }
- return false;
- }
- void BfReducer::CheckMultiuseAttributeTypeRef(BfAstNode* typeRef)
- {
- if (auto inlineTypeRef = BfNodeDynCast<BfInlineTypeReference>(typeRef))
- {
- auto checkAttribute = inlineTypeRef->mTypeDeclaration->mAttributes;
- while (checkAttribute != NULL)
- {
- checkAttribute->mIsMultiUse = true;
- checkAttribute = checkAttribute->mNextAttribute;
- }
- }
- }
- bool BfReducer::SetProtection(BfAstNode* parentNode, BfAstNode*& protectionNodeRef, BfTokenNode* tokenNode)
- {
- bool failed = false;
- if (protectionNodeRef != NULL)
- {
- if (auto prevToken = BfNodeDynCast<BfTokenNode>(protectionNodeRef))
- {
- if (((prevToken->mToken == BfToken_Protected) && (tokenNode->mToken == BfToken_Internal)) ||
- ((prevToken->mToken == BfToken_Internal) && (tokenNode->mToken == BfToken_Protected)))
- {
- auto tokenPair = mAlloc->Alloc<BfTokenPairNode>();
- if (prevToken->mSrcStart < tokenNode->mSrcStart)
- {
- ReplaceNode(prevToken, tokenPair);
- MEMBER_SET(tokenPair, mLeft, prevToken);
- MEMBER_SET(tokenPair, mRight, tokenNode);
- }
- else
- {
- ReplaceNode(tokenNode, tokenPair);
- MEMBER_SET(tokenPair, mLeft, tokenNode);
- MEMBER_SET(tokenPair, mRight, prevToken);
- }
- protectionNodeRef = tokenPair;
- if (parentNode != NULL)
- MoveNode(tokenPair, parentNode);
- return true;
- }
- }
- Fail("Protection already specified", protectionNodeRef);
- }
- protectionNodeRef = tokenNode;
- if (parentNode != NULL)
- MoveNode(tokenNode, parentNode);
- return !failed;
- }
- BfAstNode* BfReducer::CreateAllocNode(BfTokenNode* allocToken)
- {
- if (allocToken->GetToken() == BfToken_Scope)
- {
- auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
- if (nextToken == NULL)
- return allocToken;
- if ((nextToken->mToken != BfToken_Colon) && (nextToken->mToken != BfToken_ColonColon) && (nextToken->mToken != BfToken_LBracket))
- return allocToken;
- auto scopeNode = mAlloc->Alloc<BfScopeNode>();
- ReplaceNode(allocToken, scopeNode);
- scopeNode->mScopeToken = allocToken;
- if (nextToken->mToken == BfToken_Colon)
- {
- MEMBER_SET(scopeNode, mColonToken, nextToken);
- mVisitorPos.MoveNext();
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if ((nextToken->GetToken() == BfToken_Colon) || (nextToken->GetToken() == BfToken_Mixin))
- {
- MEMBER_SET(scopeNode, mTargetNode, nextToken);
- mVisitorPos.MoveNext();
- }
- }
- else if (auto identifier = BfNodeDynCast<BfIdentifierNode>(mVisitorPos.GetNext()))
- {
- MEMBER_SET(scopeNode, mTargetNode, identifier);
- mVisitorPos.MoveNext();
- }
- if (scopeNode->mTargetNode == NULL)
- {
- FailAfter("Expected scope name", scopeNode);
- }
- }
- else if (nextToken->mToken == BfToken_ColonColon)
- {
- MEMBER_SET(scopeNode, mColonToken, nextToken);
- mVisitorPos.MoveNext();
- }
- nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
- if (nextToken == NULL)
- return scopeNode;
- if (nextToken->mToken != BfToken_LBracket)
- return scopeNode;
- mVisitorPos.MoveNext();
- auto attributeDirective = CreateAttributeDirective(nextToken);
- MEMBER_SET(scopeNode, mAttributes, attributeDirective);
- return scopeNode;
- }
- if (allocToken->GetToken() == BfToken_New)
- {
- auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
- if (nextToken == NULL)
- return allocToken;
- if ((nextToken->mToken != BfToken_Colon) && (nextToken->mToken != BfToken_LBracket))
- return allocToken;
- auto newNode = mAlloc->Alloc<BfNewNode>();
- ReplaceNode(allocToken, newNode);
- newNode->mNewToken = allocToken;
- if (nextToken->mToken == BfToken_Colon)
- {
- MEMBER_SET(newNode, mColonToken, nextToken);
- mVisitorPos.MoveNext();
- if (auto nextTokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- BfToken nextToken = nextTokenNode->GetToken();
- if ((nextToken == BfToken_LParen) || (nextToken == BfToken_This) || (nextToken == BfToken_Null))
- {
- auto allocExpr = CreateExpressionAfter(newNode, (CreateExprFlags)(CreateExprFlags_NoCast | CreateExprFlags_ExitOnParenExpr));
- if (allocExpr != NULL)
- {
- MEMBER_SET(newNode, mAllocNode, allocExpr);
- }
- }
- }
- else
- {
- int endNodeIdx = -1;
- int nodeIdx = mVisitorPos.mReadPos;
- mVisitorPos.MoveNext();
- if (IsTypeReference(mVisitorPos.GetCurrent(), BfToken_Bang, -1, &endNodeIdx))
- {
- if (auto bangToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(endNodeIdx)))
- {
- if (auto prevIdentifier = BfNodeDynCast<BfIdentifierNode>(mVisitorPos.Get(endNodeIdx - 1)))
- {
- if (bangToken->GetSrcStart() == prevIdentifier->GetSrcEnd())
- {
- if (endNodeIdx == nodeIdx + 2)
- {
- MEMBER_SET(newNode, mAllocNode, prevIdentifier);
- prevIdentifier->SetSrcEnd(bangToken->GetSrcEnd());
- }
- else
- {
- mVisitorPos.mReadPos = nodeIdx + 1;
- BfExpression* expr = CreateExpression(mVisitorPos.Get(nodeIdx + 1), CreateExprFlags_ExitOnBang);
- expr->SetSrcEnd(bangToken->GetSrcEnd());
- MEMBER_SET(newNode, mAllocNode, expr);
- BfAstNode* memberNode = expr;
- if (auto memberRefExpr = BfNodeDynCast<BfMemberReferenceExpression>(expr))
- {
- memberNode = memberRefExpr->mMemberName;
- }
- else if (auto qualifiedIdentifier = BfNodeDynCast<BfQualifiedNameNode>(expr))
- {
- memberNode = qualifiedIdentifier->mRight;
- }
- if (memberNode != NULL)
- memberNode->SetSrcEnd(bangToken->GetSrcEnd());
- }
- newNode->SetSrcEnd(bangToken->GetSrcEnd());
- mVisitorPos.mReadPos = endNodeIdx;
- BfTokenNode* colonToken = NULL;
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(endNodeIdx + 1)))
- {
- if (nextToken->GetToken() == BfToken_Colon)
- colonToken = nextToken;
- }
- auto scopedInvocationTarget = CreateScopedInvocationTarget(newNode->mAllocNode, colonToken);
- newNode->SetSrcEnd(scopedInvocationTarget->GetSrcEnd());
- }
- }
- }
- }
- if (newNode->mAllocNode == NULL)
- {
- mVisitorPos.mReadPos = nodeIdx;
- if (auto identifier = BfNodeDynCast<BfIdentifierNode>(mVisitorPos.GetNext()))
- {
- MEMBER_SET(newNode, mAllocNode, identifier);
- mVisitorPos.MoveNext();
- }
- }
- }
- if (newNode->mAllocNode == NULL)
- {
- FailAfter("Expected allocator expression", newNode);
- }
- }
- nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
- if (nextToken == NULL)
- return newNode;
- if (nextToken->mToken != BfToken_LBracket)
- return newNode;
- mVisitorPos.MoveNext();
- auto attributeDirective = CreateAttributeDirective(nextToken);
- MEMBER_SET(newNode, mAttributes, attributeDirective);
- return newNode;
- }
- return allocToken;
- }
- BfObjectCreateExpression* BfReducer::CreateObjectCreateExpression(BfAstNode* allocNode, BfAstNode* targetNode)
- {
- auto objectCreateExpr = mAlloc->Alloc<BfObjectCreateExpression>();
- BfDeferredAstSizedArray<BfExpression*> arguments(objectCreateExpr->mArguments, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(objectCreateExpr->mCommas, mAlloc);
- BfTypeReference* typeRef = NULL;
- if (allocNode != NULL)
- {
- ReplaceNode(allocNode, objectCreateExpr);
- MEMBER_SET(objectCreateExpr, mNewNode, allocNode);
- }
- else
- {
- ReplaceNode(targetNode, objectCreateExpr);
- typeRef = CreateTypeRef(targetNode);
- if (typeRef == NULL)
- return NULL;
- }
- auto nextNode = mVisitorPos.GetNext();
- BfTokenNode* tokenNode;
- if (typeRef == NULL)
- typeRef = CreateTypeRefAfter(objectCreateExpr);
- if (typeRef == NULL)
- return objectCreateExpr;
- bool isArray = false;
- if (auto ptrType = BfNodeDynCast<BfPointerTypeRef>(typeRef))
- {
- if (auto arrayType = BfNodeDynCast<BfArrayTypeRef>(ptrType->mElementType))
- {
- MEMBER_SET(objectCreateExpr, mStarToken, ptrType->mStarNode);
- typeRef = ptrType->mElementType;
- isArray = true;
- }
- }
- else if (auto arrayType = BfNodeDynCast<BfArrayTypeRef>(typeRef))
- {
- isArray = true;
- }
- MEMBER_SET(objectCreateExpr, mTypeRef, typeRef);
- if (auto block = BfNodeDynCast<BfBlock>(mVisitorPos.GetNext()))
- {
- mPassInstance->Warn(0, "Expected '('", block->mOpenBrace);
- mVisitorPos.MoveNext();
- MEMBER_SET(objectCreateExpr, mOpenToken, block->mOpenBrace);
- //
- {
- SetAndRestoreValue<BfVisitorPos> prevVisitorPos(mVisitorPos, BfVisitorPos(block));
- ReadArguments(objectCreateExpr, objectCreateExpr, &arguments, &commas, BfToken_None, true);
- while (true)
- {
- auto nextNode = mVisitorPos.GetNext();
- if (nextNode == NULL)
- break;
- AddErrorNode(nextNode);
- mVisitorPos.MoveNext();
- }
- }
- if (block->mCloseBrace != NULL)
- MEMBER_SET(objectCreateExpr, mCloseToken, block->mCloseBrace);
- objectCreateExpr->mSrcEnd = block->mSrcEnd;
- return objectCreateExpr;
- }
- if (isArray)
- {
- tokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
- if (tokenNode == NULL)
- return objectCreateExpr;
- if (tokenNode->GetToken() != BfToken_LParen)
- return objectCreateExpr;
- mVisitorPos.MoveNext();
- }
- else
- {
- auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
- auto nextNextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(mVisitorPos.mReadPos + 2));
- if ((nextToken != NULL) && (nextToken->mToken == BfToken_Dot) &&
- (nextNextToken != NULL) && (nextNextToken->mToken == BfToken_This))
- {
- auto ctorExplicitNode = mAlloc->Alloc<BfCtorExplicitNode>();
- ReplaceNode(nextToken, ctorExplicitNode);
- ctorExplicitNode->mDotToken = nextToken;
- MEMBER_SET(ctorExplicitNode, mThisToken, nextNextToken);
- mVisitorPos.MoveNext();
- mVisitorPos.MoveNext();
- MEMBER_SET(objectCreateExpr, mCtorExplicit, ctorExplicitNode);
- }
- else if ((nextToken != NULL) && (nextToken->mToken == BfToken_This))
- {
- auto ctorExplicitNode = mAlloc->Alloc<BfCtorExplicitNode>();
- ReplaceNode(nextToken, ctorExplicitNode);
- ctorExplicitNode->mThisToken = nextToken;
- mVisitorPos.MoveNext();
- MEMBER_SET(objectCreateExpr, mCtorExplicit, ctorExplicitNode);
- }
- if (objectCreateExpr->mCtorExplicit != NULL)
- {
- if (nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if ((nextToken->mToken != NULL) && (nextToken->mToken == BfToken_LChevron))
- {
- mVisitorPos.MoveNext();
- auto genericParamsDecl = CreateGenericArguments(nextToken, true);
- if (genericParamsDecl == NULL)
- return objectCreateExpr;
- MEMBER_SET(objectCreateExpr->mCtorExplicit, mGenericArgs, genericParamsDecl);
- objectCreateExpr->mSrcEnd = objectCreateExpr->mCtorExplicit->mSrcEnd;
- }
- }
- }
- // Note- if there WERE an LBracket here then we'd have an 'isArray' case. We pass this in here for
- // error display purposes
- tokenNode = ExpectTokenAfter(objectCreateExpr, BfToken_LParen, BfToken_LBracket);
- if (tokenNode == NULL)
- return objectCreateExpr;
- }
- MEMBER_SET(objectCreateExpr, mOpenToken, tokenNode);
- BfToken endToken = (BfToken)(tokenNode->GetToken() + 1);
- tokenNode = ReadArguments(objectCreateExpr, objectCreateExpr, &arguments, &commas, BfToken_RParen, true);
- if (tokenNode == NULL)
- return objectCreateExpr;
- MEMBER_SET(objectCreateExpr, mCloseToken, tokenNode);
- return objectCreateExpr;
- }
- BfExpression* BfReducer::CreateIndexerExpression(BfExpression* target, BfTokenNode* openBracketNode)
- {
- auto tokenNode = openBracketNode;
- if (openBracketNode == NULL)
- tokenNode = ExpectTokenAfter(target, BfToken_LBracket, BfToken_QuestionLBracket);
- auto indexerExpr = mAlloc->Alloc<BfIndexerExpression>();
- BfDeferredAstSizedArray<BfExpression*> arguments(indexerExpr->mArguments, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(indexerExpr->mCommas, mAlloc);
- if (target != NULL)
- {
- indexerExpr->mTarget = target;
- ReplaceNode(target, indexerExpr);
- }
- else
- {
- ReplaceNode(openBracketNode, indexerExpr);
- }
- indexerExpr->mOpenBracket = tokenNode;
- MoveNode(indexerExpr->mOpenBracket, indexerExpr);
- BfAstNode* argAfterNode = indexerExpr;
- BfAttributeDirective* attributeDirective = NULL;
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if (tokenNode->mToken == BfToken_LBracket)
- {
- mVisitorPos.MoveNext();
- attributeDirective = CreateAttributeDirective(tokenNode);
- argAfterNode = attributeDirective;
- }
- }
- indexerExpr->mCloseBracket = ReadArguments(indexerExpr, argAfterNode, &arguments, &commas, BfToken_RBracket, false);
- if (attributeDirective != NULL)
- {
- BfAttributedExpression* attribExpr = mAlloc->Alloc<BfAttributedExpression>();
- ReplaceNode(indexerExpr, attribExpr);
- attribExpr->mExpression = indexerExpr;
- MEMBER_SET(attribExpr, mAttributes, attributeDirective);
- return attribExpr;
- }
- return indexerExpr;
- }
- BfMemberReferenceExpression* BfReducer::CreateMemberReferenceExpression(BfAstNode* target)
- {
- auto tokenNode = ExpectTokenAfter(target, BfToken_Dot, BfToken_DotDot, BfToken_QuestionDot, BfToken_Arrow);
- auto memberReferenceExpr = mAlloc->Alloc<BfMemberReferenceExpression>();
- if (target != NULL)
- {
- memberReferenceExpr->mTarget = target;
- ReplaceNode(target, memberReferenceExpr);
- }
- MEMBER_SET_CHECKED(memberReferenceExpr, mDotToken, tokenNode);
- auto nextNode = mVisitorPos.GetNext();
- if (auto literalExpr = BfNodeDynCast<BfLiteralExpression>(nextNode))
- {
- // Special case for "tuple.0" type references
- if (literalExpr->mValue.mTypeCode == BfTypeCode_IntUnknown)
- {
- MEMBER_SET(memberReferenceExpr, mMemberName, literalExpr);
- mVisitorPos.MoveNext();
- return memberReferenceExpr;
- }
- }
- if ((tokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext())))
- {
- if (tokenNode->GetToken() == BfToken_LBracket)
- {
- mVisitorPos.MoveNext();
- auto attrIdentifier = CreateAttributedExpression(tokenNode, true);
- if (attrIdentifier != NULL)
- {
- MEMBER_SET(memberReferenceExpr, mMemberName, attrIdentifier);
- }
- }
- if (tokenNode->GetToken() == BfToken_This)
- {
- mVisitorPos.MoveNext();
- MEMBER_SET(memberReferenceExpr, mMemberName, tokenNode);
- }
- }
- if (memberReferenceExpr->mMemberName == NULL)
- {
- auto memberName = ExpectIdentifierAfter(memberReferenceExpr);
- if (memberName != NULL)
- {
- MEMBER_SET(memberReferenceExpr, mMemberName, memberName);
- }
- }
- return memberReferenceExpr;
- }
- BfTupleExpression* BfReducer::CreateTupleExpression(BfTokenNode* node, BfExpression* innerExpr)
- {
- auto tupleExpr = mAlloc->Alloc<BfTupleExpression>();
- ReplaceNode(node, tupleExpr);
- tupleExpr->mOpenParen = node;
- BfDeferredAstSizedArray<BfTupleNameNode*> names(tupleExpr->mNames, mAlloc);
- BfDeferredAstSizedArray<BfExpression*> values(tupleExpr->mValues, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(tupleExpr->mCommas, mAlloc);
- while (true)
- {
- BfTokenNode* closeParenToken;
- if (innerExpr == NULL)
- {
- bool skipExpr = false;
- if (values.size() != 0)
- {
- if (auto nextToken = BfNodeDynCastExact<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if (nextToken->GetToken() == BfToken_RParen)
- {
- // Unterminated - default initialize
- skipExpr = true;
- }
- }
- }
- if (!skipExpr)
- innerExpr = CreateExpressionAfter(tupleExpr, CreateExprFlags_PermissiveVariableDecl);
- }
- if (innerExpr == NULL)
- {
- // Failed, but can we pull in the closing rparen?
- auto nextNode = mVisitorPos.GetNext();
- if ((closeParenToken = BfNodeDynCast<BfTokenNode>(nextNode)))
- {
- if (closeParenToken->GetToken() == BfToken_RParen)
- {
- MEMBER_SET(tupleExpr, mCloseParen, closeParenToken);
- mVisitorPos.MoveNext();
- }
- }
- break;
- }
- if (innerExpr->IsA<BfIdentifierNode>())
- closeParenToken = ExpectTokenAfter(innerExpr, BfToken_RParen, BfToken_Comma, BfToken_Colon);
- else
- closeParenToken = ExpectTokenAfter(innerExpr, BfToken_RParen, BfToken_Comma);
- if (closeParenToken == NULL)
- {
- values.push_back(innerExpr);
- MoveNode(innerExpr, tupleExpr);
- break;
- }
- //TODO: Why did we have this compat mode thing? It kept us from properly creating tuples with names
- if ((closeParenToken->GetToken() == BfToken_Colon) /*&& (!mCompatMode)*/)
- {
- BfTupleNameNode* tupleNameNode = mAlloc->Alloc<BfTupleNameNode>();
- ReplaceNode(innerExpr, tupleNameNode);
- tupleNameNode->mNameNode = (BfIdentifierNode*)innerExpr;
- MEMBER_SET(tupleNameNode, mColonToken, closeParenToken);
- while ((int)values.size() > names.size())
- names.push_back(NULL);
- names.push_back(tupleNameNode);
- MoveNode(tupleNameNode, tupleExpr);
- innerExpr = CreateExpressionAfter(tupleExpr);
- if (innerExpr == NULL)
- break;
- closeParenToken = ExpectTokenAfter(innerExpr, BfToken_RParen, BfToken_Comma);
- }
- values.push_back(innerExpr);
- MoveNode(innerExpr, tupleExpr);
- innerExpr = NULL;
- if (closeParenToken == NULL)
- break;
- if (closeParenToken->GetToken() == BfToken_RParen)
- {
- MEMBER_SET(tupleExpr, mCloseParen, closeParenToken);
- break;
- }
- commas.push_back(closeParenToken);
- MoveNode(closeParenToken, tupleExpr);
- }
- return tupleExpr;
- }
- BfAstNode* BfReducer::HandleTopLevel(BfBlock* node)
- {
- SetAndRestoreValue<BfVisitorPos> prevVisitorPos(mVisitorPos, BfVisitorPos(node));
- BfAstNode* prevNode = NULL;
- bool hadPrevFail = false;
- bool isDone = !mVisitorPos.MoveNext();
- auto parser = mSource->ToParser();
- if ((parser != NULL) && (parser->mEmbedKind == BfSourceEmbedKind_Type))
- {
- while (!isDone)
- {
- auto node = mVisitorPos.GetCurrent();
- if (node == prevNode)
- {
- // If we're stuck on an error and can't process any more nodes
- break;
- }
- prevNode = node;
- BfAstNode* typeMember = BfNodeDynCast<BfMemberDeclaration>(node);
- if (typeMember == NULL)
- {
- SetAndRestoreValue<BfAstNode*> prevTypeMemberNodeStart(mTypeMemberNodeStart, node);
- typeMember = ReadTypeMember(node);
- }
- //methodDeclaration->mDocumentation = FindDocumentation(methodDeclaration);
- isDone = !mVisitorPos.MoveNext();
- if (typeMember != NULL)
- {
- mVisitorPos.Write(typeMember);
- }
- }
- }
- if ((parser != NULL) && (parser->mEmbedKind == BfSourceEmbedKind_Method))
- {
- bool allowEndingExpression = false;
- BfAstNode* nextNode = NULL;
- while (!isDone)
- {
- BfAstNode* node = mVisitorPos.GetCurrent();
- CreateStmtFlags flags = (CreateStmtFlags)(CreateStmtFlags_FindTrailingSemicolon | CreateStmtFlags_AllowLocalFunction);
- if (allowEndingExpression)
- flags = (CreateStmtFlags)(flags | CreateStmtFlags_AllowUnterminatedExpression);
- auto statement = CreateStatement(node, flags);
- if ((statement == NULL) && (mSource != NULL))
- statement = mSource->CreateErrorNode(node);
- isDone = !mVisitorPos.MoveNext();
- if (statement != NULL)
- mVisitorPos.Write(statement);
- }
- }
- while (!isDone)
- {
- auto child = mVisitorPos.GetCurrent();
- if (child == prevNode)
- {
- // If we're stuck on an error and can't process any more nodes
- break;
- }
- prevNode = child;
- auto tokenNode = BfNodeDynCast<BfTokenNode>(child);
- if (tokenNode == NULL)
- {
- if (!hadPrevFail)
- Fail("Namespace or type declaration expected", child);
- hadPrevFail = true;
- isDone = !mVisitorPos.MoveNext();
- mVisitorPos.Write(child); // Just keep it...
- continue;
- }
- SetAndRestoreValue<BfAstNode*> prevTypeMemberNodeStart(mTypeMemberNodeStart, tokenNode);
- auto newNode = CreateTopLevelObject(tokenNode, NULL);
- hadPrevFail = newNode == NULL;
- isDone = !mVisitorPos.MoveNext();
- if (newNode != NULL)
- mVisitorPos.Write(newNode);
- }
- mVisitorPos.Trim();
- return node;
- }
- BfAstNode* BfReducer::CreateTopLevelObject(BfTokenNode* tokenNode, BfAttributeDirective* attributes, BfAstNode* deferredHeadNode, bool isAnonymous)
- {
- if (!AssertCurrentNode(tokenNode))
- return NULL;
- bool isSimpleEnum = false;
- if (tokenNode->GetToken() == BfToken_Enum)
- {
- int checkReadPos = mVisitorPos.mReadPos + 1;
- // Do we just have a value list with no members?
- auto nextNode = mVisitorPos.Get(checkReadPos);
- auto checkNode = nextNode;
- while (checkNode != NULL)
- {
- if (auto block = BfNodeDynCast<BfBlock>(checkNode))
- {
- SetAndRestoreValue<BfVisitorPos> prevVisitorPos(mVisitorPos, BfVisitorPos(block));
- mVisitorPos.MoveNext();
- bool hadIllegal = false;
- bool inAssignment = false;
- int bracketDepth = 0;
- int parenDepth = 0;
- int checkIdx = 0;
- while (true)
- {
- auto node = block->mChildArr.Get(checkIdx);
- if (node == NULL)
- break;
- if (auto identifierNode = BfNodeDynCast<BfIdentifierNode>(node))
- {
- // Allow
- }
- else if (auto tokenNode = BfNodeDynCast<BfTokenNode>(node))
- {
- if (tokenNode->mToken == BfToken_Comma)
- {
- // Allow
- inAssignment = false;
- }
- else if (tokenNode->mToken == BfToken_AssignEquals)
- {
- inAssignment = true;
- }
- else if (tokenNode->mToken == BfToken_LBracket)
- {
- bracketDepth++;
- }
- else if (tokenNode->mToken == BfToken_RBracket)
- {
- bracketDepth--;
- }
- else if (tokenNode->mToken == BfToken_LParen)
- {
- parenDepth++;
- }
- else if (tokenNode->mToken == BfToken_RParen)
- {
- parenDepth--;
- }
- else if ((bracketDepth > 0) || (parenDepth > 0))
- {
- // Allow
- }
- else if (tokenNode->mToken == BfToken_Semicolon)
- {
- hadIllegal = true;
- break;
- }
- else
- {
- if (!inAssignment)
- {
- hadIllegal = true;
- break;
- }
- }
- }
- else if ((bracketDepth > 0) || (parenDepth > 0))
- {
- // Allow
- }
- else
- {
- if (!inAssignment)
- {
- hadIllegal = true;
- break;
- }
- }
- checkIdx++;
- }
- if (!hadIllegal)
- {
- isSimpleEnum = true;
- }
- break;
- }
- checkReadPos++;
- auto nextCheckNode = mVisitorPos.Get(checkReadPos);
- checkNode = nextCheckNode;
- }
- }
- switch (tokenNode->GetToken())
- {
- case BfToken_Using:
- {
- if (auto nextTokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if ((nextTokenNode->mToken == BfToken_Static) || (nextTokenNode->mToken == BfToken_Internal))
- {
- auto usingDirective = mAlloc->Alloc<BfUsingModDirective>();
- ReplaceNode(tokenNode, usingDirective);
- usingDirective->mUsingToken = tokenNode;
- MEMBER_SET(usingDirective, mModToken, nextTokenNode);
- mVisitorPos.MoveNext();
- auto typeRef = CreateTypeRefAfter(usingDirective);
- if (typeRef != NULL)
- MEMBER_SET(usingDirective, mTypeRef, typeRef);
- tokenNode = ExpectTokenAfter(usingDirective, BfToken_Semicolon);
- if (tokenNode != NULL)
- MEMBER_SET(usingDirective, mTrailingSemicolon, tokenNode);
- BfExteriorNode exteriorNode;
- exteriorNode.mNode = usingDirective;
- BfSizedArrayInitIndirect(exteriorNode.mNamespaceNodes, mCurNamespaceStack, mAlloc);
- mExteriorNodes.Add(exteriorNode);
- return usingDirective;
- }
- }
- auto usingDirective = mAlloc->Alloc<BfUsingDirective>();
- ReplaceNode(tokenNode, usingDirective);
- usingDirective->mUsingToken = tokenNode;
- auto identifierNode = ExpectIdentifierAfter(usingDirective);
- if (identifierNode != NULL)
- {
- identifierNode = CompactQualifiedName(identifierNode);
- MEMBER_SET(usingDirective, mNamespace, identifierNode);
- tokenNode = ExpectTokenAfter(usingDirective, BfToken_Semicolon);
- if (tokenNode == NULL)
- {
- // Failure, but eat any following dot for autocompletion purposes
- auto nextNode = mVisitorPos.GetNext();
- if ((tokenNode = BfNodeDynCast<BfTokenNode>(nextNode)))
- {
- if (tokenNode->GetToken() == BfToken_Dot)
- {
- auto qualifiedNameNode = mAlloc->Alloc<BfQualifiedNameNode>();
- ReplaceNode(usingDirective->mNamespace, qualifiedNameNode);
- qualifiedNameNode->mLeft = usingDirective->mNamespace;
- MEMBER_SET(qualifiedNameNode, mDot, tokenNode);
- usingDirective->mNamespace = qualifiedNameNode;
- usingDirective->SetSrcEnd(qualifiedNameNode->GetSrcEnd());
- return usingDirective;
- }
- }
- }
- else if (tokenNode != NULL)
- {
- MEMBER_SET(usingDirective, mTrailingSemicolon, tokenNode);
- }
- }
- BfExteriorNode exteriorNode;
- exteriorNode.mNode = usingDirective;
- mExteriorNodes.Add(exteriorNode);
- return usingDirective;
- }
- break;
- case BfToken_Namespace:
- {
- auto namespaceDeclaration = mAlloc->Alloc<BfNamespaceDeclaration>();
- namespaceDeclaration->mNamespaceNode = tokenNode;
- auto identifierNode = ExpectIdentifierAfter(tokenNode);
- if (identifierNode == NULL)
- return namespaceDeclaration;
- identifierNode = CompactQualifiedName(identifierNode);
- namespaceDeclaration->mNameNode = identifierNode;
- ReplaceNode(tokenNode, namespaceDeclaration);
- MoveNode(identifierNode, namespaceDeclaration);
- BfAstNode* bodyNode = NULL;
- BfBlock* blockNode = NULL;
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- bodyNode = ExpectTokenAfter(namespaceDeclaration, BfToken_Semicolon);
- else
- bodyNode = blockNode = ExpectBlockAfter(namespaceDeclaration);
- if (bodyNode == NULL)
- return namespaceDeclaration;
- MoveNode(bodyNode, namespaceDeclaration);
- namespaceDeclaration->mBody = bodyNode;
- mCurNamespaceStack.Add(namespaceDeclaration);
- if (blockNode != NULL)
- HandleTopLevel(blockNode);
- mCurNamespaceStack.pop_back();
- return namespaceDeclaration;
- }
- break;
- case BfToken_LBracket:
- {
- auto attributes = CreateAttributeDirective(tokenNode);
- if (attributes == NULL)
- return NULL;
- auto nextNode = mVisitorPos.GetNext();
- auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode);
- if (nextToken == NULL)
- {
- FailAfter("Expected type declaration", tokenNode);
- return NULL;
- }
- mVisitorPos.MoveNext();
- auto topLevelObject = CreateTopLevelObject(nextToken, attributes);
- if (topLevelObject == NULL)
- return NULL;
- auto typeDeclaration = BfNodeDynCast<BfTypeDeclaration>(topLevelObject);
- if (typeDeclaration == NULL)
- {
- Fail("Invalid type specifier", tokenNode);
- return NULL;
- }
- typeDeclaration->mAttributes = attributes;
- ReplaceNode(attributes, typeDeclaration);
- return typeDeclaration;
- }
- break;
- case BfToken_Sealed:
- case BfToken_Abstract:
- case BfToken_Public:
- case BfToken_Private:
- case BfToken_Protected:
- case BfToken_Internal:
- case BfToken_Static:
- {
- auto nextNode = mVisitorPos.GetNext();
- if ((tokenNode->GetToken() == BfToken_Static) && BfNodeIsA<BfBlock>(nextNode))
- {
- // It's a global block!
- auto typeDeclaration = mAlloc->Alloc<BfTypeDeclaration>();
- ReplaceNode(tokenNode, typeDeclaration);
- typeDeclaration->mDocumentation = FindDocumentation(typeDeclaration);
- typeDeclaration->mStaticSpecifier = tokenNode;
- auto block = BfNodeDynCast<BfBlock>(nextNode);
- MEMBER_SET(typeDeclaration, mDefineNode, block);
- mVisitorPos.MoveNext();
- HandleTypeDeclaration(typeDeclaration, attributes, deferredHeadNode);
- return typeDeclaration;
- }
- nextNode = mVisitorPos.GetNext();
- auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode);
- if (nextToken == NULL)
- {
- AddErrorNode(tokenNode);
- FailAfter("Expected type declaration", tokenNode);
- return NULL;
- }
- mVisitorPos.MoveNext();
- auto topLevelObject = CreateTopLevelObject(nextToken, attributes);
- if (topLevelObject == NULL)
- {
- AddErrorNode(tokenNode);
- return NULL;
- }
- auto typeDeclaration = BfNodeDynCast<BfTypeDeclaration>(topLevelObject);
- if (typeDeclaration == NULL)
- {
- AddErrorNode(tokenNode);
- Fail("Invalid type specifier", tokenNode);
- return NULL;
- }
- ReplaceNode(tokenNode, typeDeclaration);
- BfToken token = tokenNode->GetToken();
- if ((token == BfToken_Public) ||
- (token == BfToken_Protected) ||
- (token == BfToken_Private) ||
- (token == BfToken_Internal))
- {
- SetProtection(typeDeclaration, typeDeclaration->mProtectionSpecifier, tokenNode);
- }
- if (token == BfToken_Static)
- {
- if (typeDeclaration->mStaticSpecifier != NULL)
- {
- Fail("Static already specified", tokenNode);
- }
- MEMBER_SET(typeDeclaration, mStaticSpecifier, tokenNode);
- }
- if (token == BfToken_Sealed)
- {
- if (typeDeclaration->mSealedSpecifier != NULL)
- {
- Fail("Sealed already specified", tokenNode);
- }
- MEMBER_SET(typeDeclaration, mSealedSpecifier, tokenNode);
- }
- if (token == BfToken_Abstract)
- {
- if (typeDeclaration->mAbstractSpecifier != NULL)
- {
- Fail(StrFormat("'%s' already specified", typeDeclaration->mAbstractSpecifier->ToString().c_str()), tokenNode);
- }
- MEMBER_SET(typeDeclaration, mAbstractSpecifier, tokenNode);
- }
- //TODO: Store type specifiers
- return typeDeclaration;
- }
- break;
- case BfToken_Delegate:
- case BfToken_Function:
- {
- auto typeDeclaration = mAlloc->Alloc<BfTypeDeclaration>();
- SetAndRestoreValue<BfTypeDeclaration*> prevTypeDecl(mCurTypeDecl, typeDeclaration);
- CurTypeState curTypeState(typeDeclaration, mAlloc);
- SetAndRestoreValue<CurTypeState*> prevTypeState(mCurTypeState, &curTypeState);
- ReplaceNode(tokenNode, typeDeclaration);
- typeDeclaration->mDocumentation = FindDocumentation(typeDeclaration);
- typeDeclaration->mTypeNode = tokenNode;
- auto retType = CreateTypeRefAfter(typeDeclaration);
- if (retType == NULL)
- return typeDeclaration;
- auto methodDecl = mAlloc->Alloc<BfMethodDeclaration>();
- MEMBER_SET(methodDecl, mReturnType, retType);
- CheckMultiuseAttributeTypeRef(methodDecl->mReturnType);
- BfDeferredAstSizedArray<BfParameterDeclaration*> params(methodDecl->mParams, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(methodDecl->mCommas, mAlloc);
- methodDecl->mDocumentation = FindDocumentation(methodDecl);
- BfBlock* defineBlock = mAlloc->Alloc<BfBlock>();
- MoveNode(defineBlock, typeDeclaration);
- BfDeferredAstSizedArray<BfAstNode*> members(defineBlock->mChildArr, mAlloc);
- members.push_back(methodDecl);
- MoveNode(methodDecl, typeDeclaration);
- typeDeclaration->mDefineNode = defineBlock;
- auto name = ExpectIdentifierAfter(retType);
- if (name == NULL)
- {
- ReplaceNode(retType, methodDecl);
- return typeDeclaration;
- }
- ReplaceNode(name, methodDecl);
- MEMBER_SET_CHECKED(typeDeclaration, mNameNode, name);
- auto nextNode = mVisitorPos.GetNext();
- if ((tokenNode = BfNodeDynCast<BfTokenNode>(nextNode)))
- {
- if (tokenNode->GetToken() == BfToken_LChevron)
- {
- auto genericParams = CreateGenericParamsDeclaration(tokenNode);
- MEMBER_SET_CHECKED(typeDeclaration, mGenericParams, genericParams);
- methodDecl->SetSrcEnd(genericParams->GetSrcEnd());
- }
- }
- bool failed = ParseMethod(methodDecl, ¶ms, &commas);
- if (methodDecl->mGenericConstraintsDeclaration != NULL)
- {
- typeDeclaration->mGenericConstraintsDeclaration = methodDecl->mGenericConstraintsDeclaration;
- typeDeclaration->SetSrcEnd(methodDecl->GetSrcEnd());
- methodDecl->mGenericConstraintsDeclaration = NULL;
- }
- if (methodDecl->mBody != NULL)
- {
- Fail("Unexpected method body after delegate/function type", methodDecl->mBody);
- }
- if (failed)
- return typeDeclaration;
- if ((methodDecl->mEndSemicolon == NULL) && (methodDecl->mCloseParen != NULL))
- FailAfter("Expected ';'", methodDecl->mCloseParen);
- //MEMBER_SET(methodDecl, mReturnType, retType);
- return typeDeclaration;
- }
- break;
- case BfToken_TypeAlias:
- {
- auto identifierNode = ExpectIdentifierAfter(tokenNode);
- if (identifierNode == NULL)
- return NULL;
- auto typeDeclaration = mAlloc->Alloc<BfTypeAliasDeclaration>();
- BfDeferredAstSizedArray<BfTypeReference*> baseClasses(typeDeclaration->mBaseClasses, mAlloc);
- BfDeferredAstSizedArray<BfAstNode*> baseClassCommas(typeDeclaration->mBaseClassCommas, mAlloc);
- mLastTypeDecl = typeDeclaration;
- typeDeclaration->mTypeNode = tokenNode;
- typeDeclaration->mNameNode = identifierNode;
- ReplaceNode(tokenNode, typeDeclaration);
- MoveNode(identifierNode, typeDeclaration);
- typeDeclaration->mDocumentation = FindDocumentation(typeDeclaration);
- auto nextNode = mVisitorPos.GetNext();
- auto chevronToken = BfNodeDynCast<BfTokenNode>(nextNode);
- if ((chevronToken != NULL) && (chevronToken->GetToken() == BfToken_LChevron))
- {
- auto genericMethodParams = CreateGenericParamsDeclaration(chevronToken);
- if (genericMethodParams != NULL)
- {
- MEMBER_SET(typeDeclaration, mGenericParams, genericMethodParams);
- }
- }
- auto tokenNode = ExpectTokenAfter(typeDeclaration, BfToken_AssignEquals);
- if (tokenNode != NULL)
- {
- MEMBER_SET(typeDeclaration, mEqualsToken, tokenNode);
- auto aliasToType = CreateTypeRefAfter(typeDeclaration);
- if (aliasToType != NULL)
- {
- MEMBER_SET(typeDeclaration, mAliasToType, aliasToType);
- auto tokenNode = ExpectTokenAfter(typeDeclaration, BfToken_Semicolon);
- if (tokenNode != NULL)
- MEMBER_SET(typeDeclaration, mEndSemicolon, tokenNode);
- }
- }
- if (!IsNodeRelevant(deferredHeadNode, typeDeclaration))
- typeDeclaration->mIgnoreDeclaration = true;
- return typeDeclaration;
- }
- break;
- case BfToken_Class:
- case BfToken_Struct:
- case BfToken_Interface:
- case BfToken_Enum:
- case BfToken_Extension:
- {
- if ((tokenNode->GetToken() == BfToken_Enum) && (isSimpleEnum))
- break;
- BfIdentifierNode* identifierNode = NULL;
- if (!isAnonymous)
- {
- identifierNode = ExpectIdentifierAfter(tokenNode);
- if (identifierNode == NULL)
- {
- AddErrorNode(tokenNode);
- return NULL;
- }
- }
- // We put extra effort in here to continue after failure, since 'return NULL' failure
- // means we don't parse members inside type (messes up colorization and such)
- auto typeDeclaration = mAlloc->Alloc<BfTypeDeclaration>();
- BfDeferredAstSizedArray<BfTypeReference*> baseClasses(typeDeclaration->mBaseClasses, mAlloc);
- BfDeferredAstSizedArray<BfAstNode*> baseClassCommas(typeDeclaration->mBaseClassCommas, mAlloc);
- mLastTypeDecl = typeDeclaration;
- typeDeclaration->mTypeNode = tokenNode;
- typeDeclaration->mNameNode = identifierNode;
- ReplaceNode(tokenNode, typeDeclaration);
- if (identifierNode != NULL)
- MoveNode(identifierNode, typeDeclaration);
- typeDeclaration->mDocumentation = FindDocumentation(mTypeMemberNodeStart);
- auto nextNode = mVisitorPos.GetNext();
- auto chevronToken = BfNodeDynCast<BfTokenNode>(nextNode);
- if ((chevronToken != NULL) && (chevronToken->GetToken() == BfToken_LChevron))
- {
- auto genericMethodParams = CreateGenericParamsDeclaration(chevronToken);
- if (genericMethodParams != NULL)
- {
- MEMBER_SET(typeDeclaration, mGenericParams, genericMethodParams);
- }
- }
- nextNode = mVisitorPos.GetNext();
- auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if ((tokenNode != NULL) && (tokenNode->GetToken() == BfToken_Colon))
- {
- MEMBER_SET(typeDeclaration, mColonToken, tokenNode);
- mVisitorPos.MoveNext();
- tokenNode = NULL;
- for (int baseTypeIdx = 0; true; baseTypeIdx++)
- {
- nextNode = mVisitorPos.GetNext();
- if ((baseTypeIdx > 0) && (BfNodeDynCast<BfBlock>(nextNode)))
- break;
- if (baseTypeIdx > 0)
- {
- bool hasComma = false;
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if ((tokenNode->mToken == BfToken_Semicolon) && (!isAnonymous))
- break;
- if (tokenNode->mToken == BfToken_Comma)
- hasComma = true;
- }
- if ((!hasComma) && (isAnonymous))
- {
- // End type declaration
- break;
- }
- BfTokenNode* commaToken = NULL;
- if (typeDeclaration->mGenericParams != NULL)
- {
- commaToken = ExpectTokenAfter(typeDeclaration, BfToken_Comma, BfToken_Where);
- if ((commaToken != NULL) && (commaToken->GetToken() == BfToken_Where))
- {
- mVisitorPos.mReadPos--;
- break;
- }
- }
- else
- commaToken = ExpectTokenAfter(typeDeclaration, BfToken_Comma);
- if (commaToken == NULL)
- break;
- MoveNode(commaToken, typeDeclaration);
- baseClassCommas.push_back(commaToken);
- }
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if (tokenNode->mToken == BfToken_This)
- {
- mVisitorPos.MoveNext();
- auto ctorDecl = mAlloc->Alloc<BfAutoConstructorDeclaration>();
- BfDeferredAstSizedArray<BfParameterDeclaration*> params(ctorDecl->mParams, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(ctorDecl->mCommas, mAlloc);
- ctorDecl->mReturnType = NULL;
- ReplaceNode(tokenNode, ctorDecl);
- MEMBER_SET(ctorDecl, mThisToken, tokenNode);
- ParseMethod(ctorDecl, ¶ms, &commas);
- if (!baseClassCommas.IsEmpty())
- {
- ctorDecl->mPrefix = baseClassCommas.back();
- baseClassCommas.pop_back();
- ctorDecl->mSrcStart = ctorDecl->mPrefix->mSrcStart;
- }
- if (typeDeclaration->mAutoCtor == NULL)
- {
- MEMBER_SET(typeDeclaration, mAutoCtor, ctorDecl);
- }
- else
- {
- Fail("Only one auto-constructor is allowed", ctorDecl);
- AddErrorNode(ctorDecl);
- }
- continue;
- }
- }
- auto baseType = CreateTypeRefAfter(typeDeclaration);
- if (baseType == NULL)
- break;
- MoveNode(baseType, typeDeclaration);
- baseClasses.push_back(baseType);
- }
- nextNode = mVisitorPos.GetNext();
- tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- }
- if (tokenNode != NULL)
- {
- if (tokenNode->GetToken() == BfToken_Where)
- {
- mVisitorPos.MoveNext();
- auto constraints = CreateGenericConstraintsDeclaration(tokenNode);
- if (constraints != NULL)
- {
- MEMBER_SET(typeDeclaration, mGenericConstraintsDeclaration, constraints);
- }
- nextNode = mVisitorPos.GetNext();
- tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- }
- }
- if (tokenNode != NULL)
- {
- if ((tokenNode->GetToken() == BfToken_Semicolon) && (!isAnonymous))
- {
- typeDeclaration->mDefineNode = tokenNode;
- MoveNode(tokenNode, typeDeclaration);
- mVisitorPos.MoveNext();
- return typeDeclaration;
- }
- }
- if ((isAnonymous) && (!BfNodeIsA<BfBlock>(nextNode)))
- return typeDeclaration;
- auto blockNode = ExpectBlockAfter(typeDeclaration);
- if (blockNode != NULL)
- {
- typeDeclaration->mDefineNode = blockNode;
- MoveNode(blockNode, typeDeclaration);
- HandleTypeDeclaration(typeDeclaration, attributes, (deferredHeadNode != NULL) ? deferredHeadNode : attributes);
- }
- return typeDeclaration;
- }
- break;
- default: break;
- }
- if (isSimpleEnum)
- {
- BfIdentifierNode* identifierNode = NULL;
- if (!isAnonymous)
- {
- identifierNode = ExpectIdentifierAfter(tokenNode, "enum name");
- if (identifierNode == NULL)
- return NULL;
- }
- // We put extra effort in here to continue after failure, since 'return NULL' failure
- // means we don't parse members inside type (messes up colorization and such)
- auto typeDeclaration = mAlloc->Alloc<BfTypeDeclaration>();
- BfDeferredAstSizedArray<BfTypeReference*> baseClasses(typeDeclaration->mBaseClasses, mAlloc);
- auto prevTypeDecl = mCurTypeDecl;
- mCurTypeDecl = typeDeclaration;
- typeDeclaration->mTypeNode = tokenNode;
- typeDeclaration->mNameNode = identifierNode;
- ReplaceNode(tokenNode, typeDeclaration);
- if (identifierNode != NULL)
- MoveNode(identifierNode, typeDeclaration);
- typeDeclaration->mDocumentation = FindDocumentation(typeDeclaration);
- auto nextNode = mVisitorPos.GetNext();
- auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if ((tokenNode != NULL) && (tokenNode->GetToken() == BfToken_Colon))
- {
- MEMBER_SET(typeDeclaration, mColonToken, tokenNode);
- mVisitorPos.MoveNext();
- tokenNode = NULL;
- auto baseType = CreateTypeRefAfter(typeDeclaration);
- if (baseType == NULL)
- return NULL;
- MoveNode(baseType, typeDeclaration);
- baseClasses.push_back(baseType);
- }
- auto blockNode = ExpectBlockAfter(typeDeclaration);
- if (blockNode != NULL)
- {
- SetAndRestoreValue<BfVisitorPos> prevVisitorPos(mVisitorPos, BfVisitorPos(blockNode));
- mVisitorPos.MoveNext();
- for (int fieldNum = 0; true; fieldNum++)
- {
- BfAstNode* child = mVisitorPos.GetCurrent();
- if (child == NULL)
- break;
- if (fieldNum > 0)
- {
- auto commaToken = BfNodeDynCast<BfTokenNode>(child);
- if ((commaToken == NULL) || (commaToken->GetToken() != BfToken_Comma))
- {
- Fail("Comma expected", child);
- break;
- }
- MoveNode(commaToken, mCurTypeDecl);
- mVisitorPos.MoveNext();
- mVisitorPos.Write(commaToken);
- child = mVisitorPos.GetCurrent();
- }
- if (child == NULL)
- break;
- auto fieldDecl = mAlloc->Alloc<BfEnumEntryDeclaration>();
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(child))
- {
- if (tokenNode->mToken == BfToken_LBracket)
- {
- BfAttributeDirective* attribute = CreateAttributeDirective(tokenNode);
- if (attribute != NULL)
- {
- mVisitorPos.MoveNext();
- child = mVisitorPos.GetCurrent();
- fieldDecl->mAttributes = attribute;
- if (child == NULL)
- break;
- }
- }
- }
- mVisitorPos.MoveNext();
- mVisitorPos.Write(fieldDecl);
- ReplaceNode(child, fieldDecl);
- if (fieldDecl->mAttributes != NULL)
- fieldDecl->mSrcStart = fieldDecl->mAttributes->mSrcStart;
- auto valueName = BfNodeDynCast<BfIdentifierNode>(child);
- if (valueName == NULL)
- {
- Fail("Enum value name expected", child);
- break;
- }
- MEMBER_SET(fieldDecl, mNameNode, valueName);
- auto nextNode = mVisitorPos.GetCurrent();
- if (auto equalsToken = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (equalsToken->GetToken() == BfToken_AssignEquals)
- {
- MEMBER_SET(fieldDecl, mEqualsNode, equalsToken);
- fieldDecl->mInitializer = CreateExpressionAfter(fieldDecl);
- if (fieldDecl->mInitializer != NULL)
- {
- mVisitorPos.MoveNext();
- MoveNode(fieldDecl->mInitializer, fieldDecl);
- }
- }
- }
- fieldDecl->mDocumentation = FindDocumentation(fieldDecl, NULL, true);
- MoveNode(fieldDecl, mCurTypeDecl);
- }
- mVisitorPos.Trim();
- }
- typeDeclaration->mDefineNode = blockNode;
- if (blockNode != NULL)
- {
- MoveNode(blockNode, typeDeclaration);
- }
- mCurTypeDecl = prevTypeDecl;
- return typeDeclaration;
- }
- AddErrorNode(tokenNode, false);
- Fail("Unexpected token", tokenNode);
- return NULL;
- }
- BfTokenNode* BfReducer::ExpectTokenAfter(BfAstNode* node, BfToken token)
- {
- if (!AssertCurrentNode(node))
- return NULL;
- auto nextNode = mVisitorPos.GetNext();
- auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if ((tokenNode == NULL) ||
- (tokenNode->GetToken() != token))
- {
- FailAfter(StrFormat("Expected '%s'", BfTokenToString(token)), node);
- return NULL;
- }
- mVisitorPos.MoveNext();
- return tokenNode;
- }
- BfTokenNode* BfReducer::ExpectTokenAfter(BfAstNode* node, BfToken tokenA, BfToken tokenB)
- {
- if (!AssertCurrentNode(node))
- return NULL;
- auto nextNode = mVisitorPos.GetNext();
- auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if ((tokenNode == NULL) ||
- ((tokenNode->GetToken() != tokenA) && (tokenNode->GetToken() != tokenB)))
- {
- FailAfter(StrFormat("Expected '%s' or '%s'", BfTokenToString(tokenA), BfTokenToString(tokenB)), node);
- return NULL;
- }
- mVisitorPos.MoveNext();
- return tokenNode;
- }
- BfTokenNode* BfReducer::ExpectTokenAfter(BfAstNode* node, BfToken tokenA, BfToken tokenB, BfToken tokenC)
- {
- if (!AssertCurrentNode(node))
- return NULL;
- auto nextNode = mVisitorPos.GetNext();
- auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- BfToken token = BfToken_Null;
- if (tokenNode != NULL)
- token = tokenNode->GetToken();
- if ((tokenNode == NULL) ||
- ((token != tokenA) && (token != tokenB) && (token != tokenC)))
- {
- FailAfter(StrFormat("Expected '%s', '%s', or '%s'", BfTokenToString(tokenA), BfTokenToString(tokenB), BfTokenToString(tokenC)), node);
- return NULL;
- }
- mVisitorPos.MoveNext();
- return tokenNode;
- }
- BfTokenNode* BfReducer::ExpectTokenAfter(BfAstNode* node, BfToken tokenA, BfToken tokenB, BfToken tokenC, BfToken tokenD)
- {
- if (!AssertCurrentNode(node))
- return NULL;
- auto nextNode = mVisitorPos.GetNext();
- auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- BfToken token = BfToken_Null;
- if (tokenNode != NULL)
- token = tokenNode->GetToken();
- if ((tokenNode == NULL) ||
- ((token != tokenA) && (token != tokenB) && (token != tokenC) && (token != tokenD)))
- {
- FailAfter(StrFormat("Expected '%s', '%s', '%s', or '%s'", BfTokenToString(tokenA), BfTokenToString(tokenB), BfTokenToString(tokenC), BfTokenToString(tokenD)), node);
- return NULL;
- }
- mVisitorPos.MoveNext();
- return tokenNode;
- }
- BfIdentifierNode* BfReducer::ExpectIdentifierAfter(BfAstNode* node, const char* typeName)
- {
- if (!AssertCurrentNode(node))
- return NULL;
- auto nextNode = mVisitorPos.GetNext();
- auto identifierNode = BfNodeDynCast<BfIdentifierNode>(nextNode);
- if (identifierNode == NULL)
- {
- if (typeName != NULL)
- FailAfter(StrFormat("Expected %s", typeName), node);
- else
- FailAfter("Expected identifier", node);
- return NULL;
- }
- mVisitorPos.MoveNext();
- return identifierNode;
- }
- BfBlock* BfReducer::ExpectBlockAfter(BfAstNode* node)
- {
- if (!AssertCurrentNode(node))
- return NULL;
- auto nextNode = mVisitorPos.GetNext();
- auto block = BfNodeDynCast<BfBlock>(nextNode);
- if (block == NULL)
- {
- FailAfter("Block expected", node);
- return NULL;
- }
- mVisitorPos.MoveNext();
- return block;
- }
- BfTokenNode* BfReducer::BreakDoubleChevron(BfTokenNode* tokenNode)
- {
- // Break up those chevrons
- auto firstChevron = mAlloc->Alloc<BfTokenNode>();
- firstChevron->SetToken(BfToken_RChevron);
- int triviaStart;
- int srcStart;
- int srcEnd;
- tokenNode->GetSrcPositions(triviaStart, srcStart, srcEnd);
- firstChevron->Init(triviaStart, srcStart, srcEnd - 1);
- tokenNode->SetToken(BfToken_RChevron);
- tokenNode->SetSrcStart(srcStart + 1);
- tokenNode->SetTriviaStart(srcStart);
- return firstChevron;
- }
- BfTokenNode* BfReducer::BreakQuestionLBracket(BfTokenNode* tokenNode)
- {
- // Break up those chevrons
- auto firstToken = mAlloc->Alloc<BfTokenNode>();
- firstToken->SetToken(BfToken_Question);
- int triviaStart;
- int srcStart;
- int srcEnd;
- tokenNode->GetSrcPositions(triviaStart, srcStart, srcEnd);
- firstToken->Init(triviaStart, srcStart, srcEnd - 1);
- tokenNode->SetToken(BfToken_LBracket);
- tokenNode->SetSrcStart(srcStart + 1);
- tokenNode->SetTriviaStart(srcStart);
- return firstToken;
- }
- BfCommentNode* BfReducer::FindDocumentation(BfAstNode* defNodeHead, BfAstNode* defNodeEnd, bool checkDocAfter)
- {
- if (defNodeEnd == NULL)
- defNodeEnd = defNodeHead;
- else if (defNodeHead == NULL)
- defNodeHead = defNodeEnd;
- while (mDocumentCheckIdx < mSource->mSidechannelRootNode->mChildArr.mSize)
- {
- auto checkComment = BfNodeDynCast<BfCommentNode>(mSource->mSidechannelRootNode->mChildArr[mDocumentCheckIdx]);
- if ((checkComment == NULL) || (checkComment->mCommentKind == BfCommentKind_Block) || (checkComment->mCommentKind == BfCommentKind_Line))
- {
- mDocumentCheckIdx++;
- continue;
- }
- if (checkComment->GetSrcEnd() > defNodeEnd->GetSrcStart())
- {
- if ((checkComment->mCommentKind == BfCommentKind_Documentation_Line_Post) ||
- (checkComment->mCommentKind == BfCommentKind_Documentation_Block_Post))
- {
- int defEnd = defNodeEnd->GetSrcEnd();
- if (checkDocAfter)
- {
- int endDiff = defEnd - checkComment->GetSrcStart();
- if (endDiff > 256)
- return NULL;
- for (int idx = defEnd; idx < checkComment->GetSrcStart(); idx++)
- {
- char c = mSource->mSrc[idx];
- if (idx == defEnd)
- {
- if ((c == ';') || (c == ','))
- continue;
- }
- if (c == '\n')
- return NULL; // No newline allowed
- if (!isspace((uint8)c))
- return NULL;
- }
- mDocumentCheckIdx++;
- return checkComment;
- }
- }
- return NULL;
- }
- if ((checkComment->mCommentKind != BfCommentKind_Documentation_Line_Pre) &&
- (checkComment->mCommentKind != BfCommentKind_Documentation_Block_Pre))
- {
- // Skip this, not used
- mDocumentCheckIdx++;
- continue;
- }
- if (mDocumentCheckIdx < mSource->mSidechannelRootNode->mChildArr.mSize - 1)
- {
- auto nextComment = mSource->mSidechannelRootNode->mChildArr[mDocumentCheckIdx + 1];
- if (nextComment->GetSrcEnd() <= defNodeHead->GetSrcStart())
- {
- // This comment is still before the node in question
- mDocumentCheckIdx++;
- continue;
- }
- }
- mDocumentCheckIdx++;
- int defSrcIdx = defNodeHead->GetSrcStart();
- for (int idx = checkComment->GetSrcEnd(); idx < defSrcIdx; idx++)
- {
- char c = mSource->mSrc[idx];
- if (!isspace((uint8)c))
- return NULL;
- }
- return checkComment;
- }
- return NULL;
- }
- BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl<BfParameterDeclaration*>* params, SizedArrayImpl<BfTokenNode*>* commas, BfToken endToken, bool requireNames)
- {
- BfAstNode* nameAfterNode = node;
- BfAttributeDirective* attributes = NULL;
- for (int paramIdx = 0; true; paramIdx++)
- {
- auto nextNode = ReplaceTokenStarter(mVisitorPos.GetNext(), mVisitorPos.mReadPos + 1, true);
- auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if (tokenNode != NULL)
- {
- BfToken token = tokenNode->GetToken();
- if ((paramIdx > 0) && (token == BfToken_AssignEquals))
- {
- auto paramDecl = params->back();
- MEMBER_SET(paramDecl, mEqualsNode, tokenNode);
- paramDecl->mEqualsNode = tokenNode;
- mVisitorPos.MoveNext();
- mSkipCurrentNodeAssert = true;
- auto initExpr = CreateExpressionAfter(node);
- mSkipCurrentNodeAssert = false;
- if (initExpr == NULL)
- return NULL;
- MEMBER_SET(paramDecl, mInitializer, initExpr);
- node->mSrcEnd = paramDecl->mSrcEnd;
- auto nextNode = mVisitorPos.GetNext();
- tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if (tokenNode == NULL)
- return NULL;
- token = tokenNode->GetToken();
- }
- if (token == endToken)
- return tokenNode;
- if ((paramIdx == 0) && (
- (token == BfToken_In) || (token == BfToken_Out) || (token == BfToken_Ref) || (token == BfToken_Mut) ||
- (token == BfToken_Delegate) || (token == BfToken_Function) ||
- (token == BfToken_Comptype) || (token == BfToken_Decltype) ||
- (token == BfToken_AllocType) || (token == BfToken_RetType) ||
- (token == BfToken_Params) || (token == BfToken_LParen) ||
- (token == BfToken_Var) || (token == BfToken_LBracket) ||
- (token == BfToken_ReadOnly) || (token == BfToken_DotDotDot) ||
- BfTokenIsTypeDecl(token)))
- {
- // These get picked up below
- }
- else
- {
- if ((paramIdx == 0) || (token != BfToken_Comma))
- {
- Fail("Expected ')' or parameter list", tokenNode);
- return NULL;
- }
- if (paramIdx > 0)
- commas->push_back(tokenNode);
- MoveNode(tokenNode, node);
- mVisitorPos.MoveNext();
- }
- nameAfterNode = tokenNode;
- }
- else
- {
- if (paramIdx > 0)
- {
- FailAfter("Expected ')' or additional parameters", nameAfterNode);
- return NULL;
- }
- }
- bool nextNextIsIdentifier = BfNodeIsA<BfIdentifierNode>(mVisitorPos.Get(mVisitorPos.mReadPos + 2));
- attributes = NULL;
- BfTokenNode* modTokenNode = NULL;
- nextNode = ReplaceTokenStarter(mVisitorPos.GetNext(), mVisitorPos.mReadPos + 1, nextNextIsIdentifier);
- tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- BfTypeReference* typeRef = NULL;
- if ((tokenNode != NULL) && (tokenNode->GetToken() == BfToken_LBracket))
- {
- mVisitorPos.MoveNext();
- attributes = CreateAttributeDirective(tokenNode);
- if (attributes != NULL)
- {
- nameAfterNode = attributes;
- auto nextNode = mVisitorPos.GetNext();
- tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- }
- }
- int paramStartReadPos = mVisitorPos.mReadPos;
- bool isParams = false;
- if (tokenNode != NULL)
- {
- BfToken token = tokenNode->GetToken();
- if ((token == BfToken_Var) || (token == BfToken_LParen) ||
- (token == BfToken_Delegate) || (token == BfToken_Function) ||
- (token == BfToken_Comptype) || (token == BfToken_Decltype) ||
- (token == BfToken_AllocType) || (token == BfToken_RetType) ||
- (token == BfToken_DotDotDot) || BfTokenIsTypeDecl(token))
- {
- mVisitorPos.MoveNext();
- typeRef = CreateTypeRef(tokenNode);
- }
- else
- {
- if ((token != BfToken_In) && (token != BfToken_Out) && (token != BfToken_Ref) && (token != BfToken_Mut) && (token != BfToken_Params) && (token != BfToken_ReadOnly))
- {
- if (attributes != NULL)
- {
- auto paramDecl = mAlloc->Alloc<BfParameterDeclaration>();
- ReplaceNode(attributes, paramDecl);
- MoveNode(paramDecl, node);
- params->push_back(paramDecl);
- MEMBER_SET(paramDecl, mAttributes, attributes);
- attributes = NULL;
- }
- Fail("Invalid token", tokenNode);
- return NULL;
- }
- if (token == BfToken_Params)
- isParams = true;
- modTokenNode = tokenNode;
- nameAfterNode = modTokenNode;
- mVisitorPos.MoveNext();
- }
- }
- if (typeRef == NULL)
- {
- auto nextNode = mVisitorPos.GetNext();
- if (nextNode == NULL)
- {
- FailAfter("Type expected", nameAfterNode);
- break;
- }
- mVisitorPos.MoveNext();
- typeRef = CreateTypeRef(nextNode);
- if (typeRef == NULL)
- {
- mVisitorPos.mReadPos = paramStartReadPos;
- break;
- }
- }
- BfToken modToken = BfToken_None;
- if (modTokenNode != NULL)
- modToken = modTokenNode->GetToken();
- if ((modTokenNode != NULL) && ((modToken == BfToken_Ref) || (modToken == BfToken_Mut) || (modToken == BfToken_In) || (modToken == BfToken_Out)))
- {
- typeRef = CreateRefTypeRef(typeRef, modTokenNode);
- modTokenNode = NULL;
- }
- auto paramDecl = mAlloc->Alloc<BfParameterDeclaration>();
- ReplaceNode(typeRef, paramDecl);
- MoveNode(paramDecl, node);
- params->push_back(paramDecl);
- MEMBER_SET(paramDecl, mTypeRef, typeRef);
- if (attributes != NULL)
- {
- MEMBER_SET(paramDecl, mAttributes, attributes);
- attributes = NULL;
- }
- if (modTokenNode != NULL)
- {
- MEMBER_SET(paramDecl, mModToken, modTokenNode);
- }
- if ((tokenNode != NULL) && (tokenNode->mToken == BfToken_DotDotDot))
- continue;
- bool allowNameFail = false;
- bool nextIsName = false;
- auto afterNameTokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(mVisitorPos.mReadPos + 2));
- if (afterNameTokenNode != NULL)
- {
- BfToken afterNameToken = afterNameTokenNode->GetToken();
- if ((afterNameToken == BfToken_Comma) ||
- (afterNameToken == BfToken_AssignEquals) ||
- (afterNameToken == BfToken_RParen))
- {
- nextIsName = true;
- }
- }
- // We definitely have a failure, but we want to attempt to scan to the actual param name if we can...
- if (!nextIsName)
- {
- int nameIdx = -1;
- int checkIdx = mVisitorPos.mReadPos + 1;
- bool useNameIdx = true;
- int parenDepth = 1;
- int bracketDepth = 0;
- while (true)
- {
- auto checkNode = mVisitorPos.Get(checkIdx);
- auto checkTokenNode = BfNodeDynCast<BfTokenNode>(checkNode);
- if (checkTokenNode != NULL)
- {
- BfToken checkToken = checkTokenNode->GetToken();
- if (nameIdx == -1)
- {
- if ((parenDepth == 1) && (bracketDepth == 0))
- {
- if ((checkToken == BfToken_Comma) ||
- (checkToken == BfToken_AssignEquals) ||
- (checkToken == BfToken_RParen))
- {
- if (auto nameIdentifier = BfNodeDynCast<BfIdentifierNode>(mVisitorPos.Get(checkIdx - 1)))
- {
- nameIdx = checkIdx - 1;
- }
- else
- {
- useNameIdx = false;
- break;
- }
- }
- }
- }
- if (checkToken == BfToken_RParen)
- parenDepth--;
- else if (checkToken == BfToken_LParen)
- parenDepth++;
- else if (checkToken == BfToken_LBracket)
- bracketDepth++;
- else if (checkToken == BfToken_RBracket)
- bracketDepth--;
- if (parenDepth == 0)
- {
- if (bracketDepth != 0)
- useNameIdx = false;
- break;
- }
- if (checkToken == BfToken_Semicolon)
- {
- useNameIdx = false;
- break;
- }
- }
- else if (auto identifier = BfNodeDynCast<BfIdentifierNode>(checkNode))
- {
- // Okay
- }
- else
- {
- // Nothing else is okay
- useNameIdx = false;
- break;
- }
- checkIdx++;
- }
- if ((useNameIdx) && (nameIdx != -1))
- {
- if (nameIdx <= mVisitorPos.mReadPos)
- {
- // We have a valid-enough param list but a missing name, so keep going
- allowNameFail = true;
- }
- else
- {
- for (int errIdx = mVisitorPos.mReadPos + 1; errIdx < nameIdx; errIdx++)
- {
- auto node = mVisitorPos.Get(errIdx);
- if (auto token = BfNodeDynCast<BfTokenNode>(node))
- Fail("Unexpected token", node);
- else
- Fail("Unexpected identifier", node);
- AddErrorNode(node);
- }
- auto nameIdentifierNode = BfNodeDynCast<BfIdentifierNode>(mVisitorPos.Get(nameIdx));
- paramDecl->mNameNode = nameIdentifierNode;
- MoveNode(nameIdentifierNode, paramDecl);
- nameAfterNode = nameIdentifierNode;
- mVisitorPos.mReadPos = nameIdx;
- continue;
- //mVisitorPos.mReadPos = nameIdx - 1;
- }
- }
- }
- if (auto nameToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if ((nameToken->GetToken() == BfToken_This))
- {
- bool isDelegate = false;
- bool isFunction = false;
- if (auto delegateTypeRef = BfNodeDynCast<BfDelegateTypeRef>(node))
- {
- if (delegateTypeRef->mTypeToken->GetToken() == BfToken_Function)
- isFunction = true;
- else
- isDelegate = true;
- }
- else if ((mCurTypeDecl->mTypeNode != NULL) && (mCurTypeDecl->mTypeNode->GetToken() == BfToken_Function))
- isFunction = true;
- else if ((mCurTypeDecl->mTypeNode != NULL) && (mCurTypeDecl->mTypeNode->GetToken() == BfToken_Delegate))
- isDelegate = true;
- if (isFunction || isDelegate)
- {
- if (paramIdx != 0)
- Fail("'this' can only be used as the first parameter", nameToken);
- if (!isFunction)
- Fail("'this' can only be specified on function types", nameToken);
- mVisitorPos.MoveNext();
- paramDecl->mNameNode = nameToken;
- MoveNode(nameToken, paramDecl);
- nameAfterNode = nameToken;
- }
- }
- }
- if (paramDecl->mNameNode == NULL)
- {
- BfAstNode* nameIdentifierNode;
- if (requireNames)
- {
- nameIdentifierNode = ExpectIdentifierAfter(node, "parameter name");
- if (nameIdentifierNode == NULL)
- {
- if (!allowNameFail)
- return NULL;
- }
- }
- else
- {
- nameIdentifierNode = BfNodeDynCast<BfIdentifierNode>(mVisitorPos.GetNext());
- if (nameIdentifierNode != NULL)
- mVisitorPos.MoveNext();
- }
- if (nameIdentifierNode != NULL)
- {
- paramDecl->mNameNode = nameIdentifierNode;
- MoveNode(nameIdentifierNode, paramDecl);
- nameAfterNode = nameIdentifierNode;
- }
- }
- node->mSrcEnd = paramDecl->mSrcEnd;
- }
- if (attributes != NULL)
- {
- Fail("Unexpected attributes", attributes);
- AddErrorNode(attributes);
- }
- return NULL;
- }
- bool BfReducer::ParseMethod(BfMethodDeclaration* methodDeclaration, SizedArrayImpl<BfParameterDeclaration*>* params, SizedArrayImpl<BfTokenNode*>* commas, bool alwaysIncludeBlock)
- {
- BfTokenNode* tokenNode;
- auto nextNode = mVisitorPos.GetNext();
- if (methodDeclaration->mGenericParams == NULL)
- {
- if ((tokenNode = BfNodeDynCast<BfTokenNode>(nextNode)))
- {
- if (tokenNode->GetToken() == BfToken_LChevron)
- {
- auto genericParams = CreateGenericParamsDeclaration(tokenNode);
- if (genericParams != NULL)
- {
- MEMBER_SET(methodDeclaration, mGenericParams, genericParams);
- }
- }
- }
- }
- tokenNode = ExpectTokenAfter(methodDeclaration, BfToken_LParen, BfToken_Bang);
- if (tokenNode == NULL)
- return false;
- if (tokenNode->GetToken() == BfToken_Bang)
- {
- Fail("Cannot include '!' in the method declaration", tokenNode);
- MoveNode(tokenNode, methodDeclaration);
- tokenNode = ExpectTokenAfter(methodDeclaration, BfToken_LParen);
- if (tokenNode == NULL)
- return false;
- }
- methodDeclaration->mOpenParen = tokenNode;
- MoveNode(methodDeclaration->mOpenParen, methodDeclaration);
- bool isFunction = false;
- bool isDelegate = false;
- if ((mCurTypeDecl != NULL) && (mCurTypeDecl->mTypeNode != NULL) && (mCurTypeDecl->mTypeNode->GetToken() == BfToken_Function))
- isFunction = true;
- else if ((mCurTypeDecl != NULL) && (mCurTypeDecl->mTypeNode != NULL) && (mCurTypeDecl->mTypeNode->GetToken() == BfToken_Delegate))
- isDelegate = true;
- if ((!isFunction) && (!isDelegate))
- {
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- {
- if (nextToken->mToken == BfToken_This)
- {
- MEMBER_SET(methodDeclaration, mThisToken, nextToken);
- mVisitorPos.MoveNext();
- }
- }
- }
- methodDeclaration->mCloseParen = ParseMethodParams(methodDeclaration, params, commas, BfToken_RParen, false);
- // RParen
- if (methodDeclaration->mCloseParen == NULL)
- {
- auto nextNode = mVisitorPos.GetNext();
- while (auto checkToken = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (checkToken->GetToken() == BfToken_RParen)
- {
- methodDeclaration->mCloseParen = checkToken;
- break;
- }
- else
- {
- // Just eat it - for autocompletion. This helps make cases nicer where we're typing in the "in" for "int", for example
- MoveNode(checkToken, methodDeclaration);
- AddErrorNode(checkToken);
- mVisitorPos.MoveNext();
- nextNode = mVisitorPos.GetNext();
- }
- }
- if (methodDeclaration->mCloseParen == NULL)
- return false;
- }
- MoveNode(methodDeclaration->mCloseParen, methodDeclaration);
- mVisitorPos.MoveNext();
- auto ctorDecl = BfNodeDynCast<BfConstructorDeclaration>(methodDeclaration);
- if (auto autoCtorDecl = BfNodeDynCast<BfAutoConstructorDeclaration>(ctorDecl))
- return true;
- auto typeDecl = mCurTypeDecl;
- nextNode = mVisitorPos.GetNext();
- if ((tokenNode = BfNodeDynCast<BfTokenNode>(nextNode)))
- {
- if (tokenNode->GetToken() == BfToken_Mut)
- {
- if (methodDeclaration->mMutSpecifier != NULL)
- {
- AddErrorNode(methodDeclaration->mMutSpecifier);
- Fail("Mut already specified", methodDeclaration->mMutSpecifier);
- }
- MEMBER_SET(methodDeclaration, mMutSpecifier, tokenNode);
- mVisitorPos.MoveNext();
- nextNode = mVisitorPos.GetNext();
- }
- }
- if ((tokenNode = BfNodeDynCast<BfTokenNode>(nextNode)))
- {
- if (tokenNode->GetToken() == BfToken_Where)
- {
- mVisitorPos.MoveNext();
- auto genericConstraints = CreateGenericConstraintsDeclaration(tokenNode);
- MEMBER_SET_CHECKED_BOOL(methodDeclaration, mGenericConstraintsDeclaration, genericConstraints);
- }
- }
- nextNode = mVisitorPos.GetNext();
- auto endToken = BfNodeDynCast<BfTokenNode>(nextNode);
- if ((endToken != NULL) && (endToken->GetToken() == BfToken_Colon))
- {
- if (auto ctorDecl = BfNodeDynCast<BfConstructorDeclaration>(methodDeclaration))
- {
- MEMBER_SET(ctorDecl, mInitializerColonToken, endToken);
- mVisitorPos.MoveNext();
- BfAstNode* invokeAfter = ctorDecl;
- auto nextNode = mVisitorPos.GetNext();
- BfAttributeDirective* attributeDirective = NULL;
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (nextToken->mToken == BfToken_LBracket)
- {
- mVisitorPos.MoveNext();
- attributeDirective = CreateAttributeDirective(nextToken);
- nextNode = mVisitorPos.GetNext();
- if (attributeDirective != NULL)
- invokeAfter = attributeDirective;
- }
- }
- endToken = ExpectTokenAfter(invokeAfter, BfToken_This, BfToken_Base);
- if (endToken != NULL)
- {
- auto invocationExpr = CreateInvocationExpression(endToken);
- if (invocationExpr != NULL)
- {
- MEMBER_SET(ctorDecl, mInitializer, invocationExpr);
- }
- }
- else if (auto identifierAfter = BfNodeDynCast<BfIdentifierNode>(nextNode))
- {
- // In process of typing - just eat identifier so we don't error out on whole method
- MoveNode(identifierAfter, ctorDecl);
- mVisitorPos.MoveNext();
- AddErrorNode(identifierAfter);
- }
- if (attributeDirective != NULL)
- {
- BfAttributedExpression* attribExpr = mAlloc->Alloc<BfAttributedExpression>();
- ReplaceNode(attributeDirective, attribExpr);
- attribExpr->mAttributes = attributeDirective;
- if (ctorDecl->mInitializer != NULL)
- {
- MEMBER_SET(attribExpr, mExpression, ctorDecl->mInitializer);
- }
- MEMBER_SET(ctorDecl, mInitializer, attribExpr);
- }
- }
- endToken = NULL;
- }
- if ((endToken != NULL) && (endToken->GetToken() == BfToken_Semicolon))
- {
- MEMBER_SET_CHECKED_BOOL(methodDeclaration, mEndSemicolon, endToken);
- mVisitorPos.MoveNext();
- }
- else
- {
- nextNode = mVisitorPos.GetNext();
- auto blockNode = BfNodeDynCast<BfBlock>(nextNode);
- if (blockNode != NULL)
- {
- methodDeclaration->mBody = blockNode;
- MoveNode(blockNode, methodDeclaration);
- mVisitorPos.MoveNext();
- if ((IsNodeRelevant(methodDeclaration)) || (alwaysIncludeBlock))
- {
- SetAndRestoreValue<BfMethodDeclaration*> prevMethodDeclaration(mCurMethodDecl, methodDeclaration);
- HandleBlock(blockNode, methodDeclaration->mMixinSpecifier != NULL);
- }
- return true;
- }
- else
- {
- nextNode = mVisitorPos.GetNext();
- auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if ((tokenNode != NULL) && (tokenNode->GetToken() == BfToken_FatArrow))
- {
- MEMBER_SET(methodDeclaration, mFatArrowToken, tokenNode);
- mVisitorPos.MoveNext();
- auto methodExpression = CreateExpressionAfter(methodDeclaration);
- MEMBER_SET_CHECKED_BOOL(methodDeclaration, mBody, methodExpression);
- auto semicolonToken = ExpectTokenAfter(methodDeclaration, BfToken_Semicolon);
- MEMBER_SET_CHECKED_BOOL(methodDeclaration, mEndSemicolon, semicolonToken);
- return true;
- }
- }
- FailAfter("Expected method body", methodDeclaration);
- }
- return true;
- }
- BfGenericArgumentsNode* BfReducer::CreateGenericArguments(BfTokenNode* tokenNode, bool allowPartial)
- {
- auto genericArgs = mAlloc->Alloc<BfGenericArgumentsNode>();
- BfDeferredAstSizedArray<BfAstNode*> genericArgsArray(genericArgs->mGenericArgs, mAlloc);
- BfDeferredAstSizedArray<BfAstNode*> commas(genericArgs->mCommas, mAlloc);
- ReplaceNode(tokenNode, genericArgs);
- genericArgs->mOpenChevron = tokenNode;
- while (true)
- {
- bool doAsExpr = false;
- auto nextNode = mVisitorPos.GetNext();
- if (BfNodeIsA<BfLiteralExpression>(nextNode))
- doAsExpr = true;
- else if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (tokenNode->mToken == BfToken_Question)
- doAsExpr = true;
- }
- BfAstNode* genericArg = NULL;
- if (doAsExpr)
- genericArg = CreateExpressionAfter(genericArgs, CreateExprFlags_BreakOnRChevron);
- else
- genericArg = CreateTypeRefAfter(genericArgs);
- if (genericArg == NULL)
- {
- genericArgsArray.push_back(NULL); // Leave empty for purposes of generic argument count
- auto nextNode = mVisitorPos.GetNext();
- tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if (tokenNode != NULL)
- {
- // Try to get right chevron. Reduces error count when we're typing out a generic argument list
- if (tokenNode->GetToken() == BfToken_RDblChevron)
- tokenNode = BreakDoubleChevron(tokenNode);
- if (tokenNode->GetToken() == BfToken_RChevron)
- {
- MoveNode(tokenNode, genericArgs);
- genericArgs->mCloseChevron = tokenNode;
- mVisitorPos.MoveNext();
- }
- }
- return genericArgs;
- }
- MoveNode(genericArg, genericArgs);
- genericArgsArray.push_back(genericArg);
- nextNode = mVisitorPos.GetNext();
- tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if (tokenNode == NULL)
- {
- FailAfter("Expected ',' or '>'", genericArgs);
- return genericArgs;
- }
- BfToken token = tokenNode->GetToken();
- if (token == BfToken_RDblChevron)
- tokenNode = BreakDoubleChevron(tokenNode);
- if ((token == BfToken_DotDotDot) && (allowPartial))
- {
- commas.push_back(tokenNode);
- mVisitorPos.MoveNext();
- nextNode = mVisitorPos.GetNext();
- tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- token = tokenNode->GetToken();
- }
- if (token == BfToken_RChevron)
- {
- MoveNode(tokenNode, genericArgs);
- genericArgs->mCloseChevron = tokenNode;
- mVisitorPos.MoveNext();
- break;
- }
- if (token != BfToken_Comma)
- {
- Fail("Either , or > expected", tokenNode);
- return genericArgs;
- }
- MoveNode(tokenNode, genericArgs);
- commas.push_back(tokenNode);
- mVisitorPos.MoveNext();
- }
- return genericArgs;
- }
- BfGenericParamsDeclaration* BfReducer::CreateGenericParamsDeclaration(BfTokenNode* tokenNode)
- {
- auto genericParams = mAlloc->Alloc<BfGenericParamsDeclaration>();
- BfDeferredAstSizedArray<BfIdentifierNode*> genericParamsArr(genericParams->mGenericParams, mAlloc);
- BfDeferredAstSizedArray<BfAstNode*> commas(genericParams->mCommas, mAlloc);
- ReplaceNode(tokenNode, genericParams);
- genericParams->mOpenChevron = tokenNode;
- mVisitorPos.MoveNext();
- while (true)
- {
- auto genericIdentifier = ExpectIdentifierAfter(genericParams, "generic parameters");
- if (genericIdentifier == NULL)
- return genericParams;
- MoveNode(genericIdentifier, genericParams);
- genericParamsArr.push_back(genericIdentifier);
- auto nextNode = mVisitorPos.GetNext();
- tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
- if (tokenNode == NULL)
- {
- FailAfter("Expected ',' or '>'", genericParams);
- return genericParams;
- }
- BfToken token = tokenNode->GetToken();
- if (token == BfToken_RDblChevron)
- tokenNode = BreakDoubleChevron(tokenNode);
- MoveNode(tokenNode, genericParams);
- mVisitorPos.MoveNext();
- if (token == BfToken_RChevron)
- {
- genericParams->mCloseChevron = tokenNode;
- break;
- }
- if (token != BfToken_Comma)
- {
- Fail("Either , or > expected", tokenNode);
- return genericParams;
- }
- commas.push_back(tokenNode);
- }
- return genericParams;
- }
- BfGenericConstraintsDeclaration* BfReducer::CreateGenericConstraintsDeclaration(BfTokenNode* tokenNode)
- {
- auto constraintsDeclaration = mAlloc->Alloc<BfGenericConstraintsDeclaration>();
- BfDeferredAstSizedArray<BfAstNode*> genericConstraintsArr(constraintsDeclaration->mGenericConstraints, mAlloc);
- bool isDone = false;
- for (int constraintIdx = 0; !isDone; constraintIdx++)
- {
- // if (auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- // {
- // if (nextToken->mToken == BfToken_LParen)
- // {
- // BfGenericConstraintExpression* genericConstraint = mAlloc->Alloc<BfGenericConstraintExpression>();
- // ReplaceNode(tokenNode, genericConstraint);
- // genericConstraint->mWhereToken = tokenNode;
- // constraintsDeclaration->mHasExpressions = true;
- //
- // genericConstraintsArr.push_back(genericConstraint);
- //
- // auto expr = CreateExpressionAfter(genericConstraint, CreateExprFlags_EarlyExit);
- // if (expr == NULL)
- // break;
- //
- // MEMBER_SET(genericConstraint, mExpression, expr);
- //
- // BfTokenNode* nextWhereToken = NULL;
- // if (auto checkToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
- // {
- // if (checkToken->mToken != BfToken_Where)
- // nextWhereToken = checkToken;
- // }
- //
- // auto nextNode = mVisitorPos.GetNext();
- // if (BfNodeDynCast<BfBlock>(nextNode))
- // break;
- //
- // bool handled = false;
- // if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- // {
- // if (tokenNode->mToken == BfToken_FatArrow)
- // break;
- // }
- //
- // tokenNode = ExpectTokenAfter(genericConstraint, BfToken_LBrace, BfToken_Where, BfToken_Semicolon);
- // if (tokenNode == NULL)
- // break;
- //
- // BfToken token = tokenNode->GetToken();
- // if (token != BfToken_Where)
- // {
- // mVisitorPos.mReadPos--;
- // break;
- // }
- //
- // continue;
- // }
- // }
- BfGenericConstraint* genericConstraint = mAlloc->Alloc<BfGenericConstraint>();
- BfDeferredAstSizedArray<BfAstNode*> constraintTypes(genericConstraint->mConstraintTypes, mAlloc);
- BfDeferredAstSizedArray<BfTokenNode*> commas(genericConstraint->mCommas, mAlloc);
- ReplaceNode(tokenNode, genericConstraint);
- genericConstraint->mWhereToken = tokenNode;
- genericConstraintsArr.push_back(genericConstraint);
- auto genericParamName = CreateTypeRefAfter(genericConstraint);
- if (genericParamName != NULL)
- {
- MEMBER_SET(genericConstraint, mTypeRef, genericParamName);
- tokenNode = ExpectTokenAfter(genericConstraint, BfToken_Colon);
- }
- else
- isDone = true;
- if (tokenNode != NULL)
- {
- MEMBER_SET(genericConstraint, mColonToken, tokenNode);
- }
- else
- isDone = true;
- for (int typeIdx = 0; !isDone; typeIdx++)
- {
- if (typeIdx > 0)
- {
- auto nextNode = mVisitorPos.GetNext();
- if (BfNodeDynCast<BfBlock>(nextNode))
- {
- isDone = true;
- break;
- }
- bool handled = false;
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if ((tokenNode->mToken == BfToken_FatArrow) || (tokenNode->mToken == BfToken_Colon))
- {
- isDone = true;
- break;
- }
- }
- tokenNode = ExpectTokenAfter(genericConstraint, BfToken_Comma, BfToken_LBrace, BfToken_Where, BfToken_Semicolon);
- if (tokenNode == NULL)
- {
- isDone = true;
- break;
- }
- BfToken token = tokenNode->GetToken();
- if (token == BfToken_Where)
- break;
- if ((token == BfToken_LBrace) || (token == BfToken_Semicolon))
- {
- mVisitorPos.mReadPos--;
- isDone = true;
- break;
- }
- MoveNode(tokenNode, genericConstraint);
- commas.push_back(tokenNode);
- }
- auto nextNode = mVisitorPos.GetNext();
- if (auto constraintToken = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- BfAstNode* constraintNode = NULL;
- bool addToConstraint = false;
- switch (constraintToken->GetToken())
- {
- case BfToken_Class:
- case BfToken_Struct:
- case BfToken_Const:
- case BfToken_Concrete:
- case BfToken_Var:
- case BfToken_New:
- case BfToken_Delete:
- case BfToken_Enum:
- case BfToken_Interface:
- addToConstraint = true;
- break;
- case BfToken_Operator:
- {
- BfGenericOperatorConstraint* opConstraint = mAlloc->Alloc<BfGenericOperatorConstraint>();
- constraintNode = opConstraint;
- ReplaceNode(constraintToken, opConstraint);
- MEMBER_SET(opConstraint, mOperatorToken, constraintToken);
- mVisitorPos.MoveNext();
- auto opToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
- if (opToken == NULL)
- {
- auto typeRef = CreateTypeRefAfter(opConstraint, BfReducer::CreateTypeRefFlags_SafeGenericParse);
- if (typeRef == NULL)
- break;
- MEMBER_SET(opConstraint, mLeftType, typeRef);
- opToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
- if (opToken == NULL)
- {
- if (auto pointerTypeRef = BfNodeDynCast<BfPointerTypeRef>(typeRef))
- {
- MEMBER_SET(opConstraint, mLeftType, pointerTypeRef->mElementType);
- opToken = pointerTypeRef->mStarNode;
- MEMBER_SET(opConstraint, mOpToken, opToken);
- }
- }
- }
- if (opConstraint->mOpToken == NULL)
- {
- if (opToken == NULL)
- {
- Fail("Conversion operators require either 'implicit' or 'explicit' qualifiers", opConstraint->mOperatorToken);
- break;
- }
- MEMBER_SET(opConstraint, mOpToken, opToken);
- mVisitorPos.MoveNext();
- }
- auto typeRef = CreateTypeRefAfter(opConstraint);
- if (typeRef == NULL)
- break;
- MEMBER_SET(opConstraint, mRightType, typeRef);
- }
- break;
- default: break;
- }
- if (addToConstraint)
- {
- constraintNode = constraintToken;
- bool addToConstraint = false;
- mVisitorPos.MoveNext();
- if (constraintToken->GetToken() == BfToken_Struct)
- {
- addToConstraint = true;
- nextNode = mVisitorPos.GetNext();
- if ((tokenNode = BfNodeDynCast<BfTokenNode>(nextNode)))
- {
- if (tokenNode->GetToken() == BfToken_Star)
- {
- auto tokenPair = mAlloc->Alloc<BfTokenPairNode>();
- ReplaceNode(constraintToken, tokenPair);
- MEMBER_SET(tokenPair, mLeft, constraintToken);
- MEMBER_SET(tokenPair, mRight, tokenNode);
- constraintNode = tokenPair;
- MoveNode(constraintToken, genericConstraint);
- genericConstraint->SetSrcEnd(tokenNode->GetSrcEnd());
- mVisitorPos.MoveNext();
- }
- }
- }
- else if (constraintToken->GetToken() == BfToken_Const)
- {
- constraintTypes.push_back(constraintNode);
- genericConstraint->mSrcEnd = constraintNode->mSrcEnd;
- auto typeRef = CreateTypeRefAfter(nextNode);
- if (typeRef == NULL)
- {
- isDone = true;
- break;
- }
- MoveNode(typeRef, genericConstraint);
- constraintTypes.push_back(typeRef);
- continue;
- }
- }
- if (constraintNode != NULL)
- {
- MoveNode(constraintNode, genericConstraint);
- constraintTypes.push_back(constraintNode);
- continue;
- }
- }
- auto typeRef = CreateTypeRefAfter(genericConstraint);
- if (typeRef == NULL)
- {
- isDone = true;
- break;
- }
- MoveNode(typeRef, genericConstraint);
- constraintTypes.push_back(typeRef);
- }
- if (constraintIdx == 0)
- ReplaceNode(genericConstraint, constraintsDeclaration);
- else
- MoveNode(genericConstraint, constraintsDeclaration);
- }
- return constraintsDeclaration;
- }
- void BfReducer::HandleBlock(BfBlock* block, bool allowEndingExpression)
- {
- //for (auto node : block->mChildren)
- SetAndRestoreValue<BfVisitorPos> prevVisitorPos(mVisitorPos, BfVisitorPos(block));
- bool isDone = !mVisitorPos.MoveNext();
- BfAstNode* nextNode = NULL;
- while (!isDone)
- {
- BfAstNode* node = mVisitorPos.GetCurrent();
- CreateStmtFlags flags = (CreateStmtFlags)(CreateStmtFlags_FindTrailingSemicolon | CreateStmtFlags_AllowLocalFunction);
- if (allowEndingExpression)
- flags = (CreateStmtFlags)(flags | CreateStmtFlags_AllowUnterminatedExpression);
- auto statement = CreateStatement(node, flags);
- if ((statement == NULL) && (mSource != NULL) && (!mSource->HasPendingError(node)))
- statement = mSource->CreateErrorNode(node);
- isDone = !mVisitorPos.MoveNext();
- if (statement != NULL)
- mVisitorPos.Write(statement);
- }
- mVisitorPos.Trim();
- }
- bool BfReducer::IsInitializerStatement(int checkIdx)
- {
- SetAndRestoreValue<int> prevReadPos(mVisitorPos.mReadPos);
- int nodeCount = 0;
- while (true)
- {
- mVisitorPos.mReadPos = checkIdx;
- auto checkNode = mVisitorPos.GetCurrent();
- if (checkNode == NULL)
- return false;
- if (auto checkToken = BfNodeDynCast<BfTokenNode>(checkNode))
- {
- switch (checkToken->mToken)
- {
- case BfToken_Dot:
- if (nodeCount == 0)
- return true;
- break;
- case BfToken_Public:
- case BfToken_Private:
- case BfToken_Internal:
- case BfToken_Protected:
- case BfToken_This:
- case BfToken_Semicolon:
- case BfToken_Case:
- case BfToken_Const:
- case BfToken_Static:
- case BfToken_TypeAlias:
- case BfToken_Mixin:
- case BfToken_Class:
- case BfToken_Struct:
- case BfToken_Enum:
- case BfToken_Interface:
- case BfToken_Override:
- return false;
- case BfToken_AssignEquals:
- if (nodeCount > 0)
- return true;
- break;
- case BfToken_Comma:
- if (nodeCount == 0)
- return false;
- else
- return true;
- }
- }
- else if (auto literalExpr = BfNodeDynCast<BfLiteralExpression>(checkNode))
- {
- return true;
- }
- else if (auto block = BfNodeDynCast<BfBlock>(checkNode))
- {
- if (nodeCount == 0)
- return true;
- }
-
- int endNode = -1;
- bool coundBeExpr = false;
- if (IsTypeReference(checkNode, BfToken_None, -1, &endNode, &coundBeExpr))
- {
- auto nextNode = mVisitorPos.Get(endNode);
- if (nextNode == NULL)
- {
- // At end
- return true;
- }
- if (BfNodeIsA<BfIdentifierNode>(nextNode))
- return false;
- if (auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- switch (nextToken->mToken)
- {
- case BfToken_This:
- return false;
- }
- }
- nodeCount++;
- checkIdx = BF_MAX(checkIdx + 1, endNode);
- continue;
- }
- else if (endNode != -1)
- {
- auto nextNode = mVisitorPos.Get(endNode);
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
- {
- if (tokenNode->mToken == BfToken_LParen)
- {
- int checkEndNode = -1;
- if (IsTypeReference(checkNode, tokenNode->mToken, -1, &checkEndNode, &coundBeExpr))
- {
- if (checkEndNode == endNode)
- {
- // Is method call
- return true;
- }
- }
- }
- }
-
- }
- nodeCount++;
- checkIdx++;
- }
- return false;
- }
- bool BfReducer::IsInitializerStatement(BfAstNode* node)
- {
- AssertCurrentNode(node);
- return IsInitializerStatement(mVisitorPos.mReadPos);
- }
- bool BfReducer::InitializerBlockHasInlineTypeDecl(BfBlock* block)
- {
- if (block->mChildArr.mSize == 0)
- return false;
- SetAndRestoreValue<BfVisitorPos> prevVisitorPos(mVisitorPos, BfVisitorPos(block));
- return !IsInitializerStatement(0);
- }
- void BfReducer::HandleTypeDeclaration(BfTypeDeclaration* typeDecl, BfAttributeDirective* attributes, BfAstNode* deferredHeadNode, bool findInitializer)
- {
- SetAndRestoreValue<BfTypeDeclaration*> prevTypeDecl(mCurTypeDecl, typeDecl);
- CurTypeState curTypeState(typeDecl, mAlloc);
- SetAndRestoreValue<CurTypeState*> prevTypeState(mCurTypeState, &curTypeState);
- SetAndRestoreValue<BfVisitorPos> prevVisitorPos(mVisitorPos, BfVisitorPos(BfNodeDynCast<BfBlock>(typeDecl->mDefineNode)));
- if (findInitializer)
- prevVisitorPos.CancelRestore();
- if (attributes != NULL)
- {
- MEMBER_SET(typeDecl, mAttributes, attributes);
- typeDecl->mTriviaStart = BF_MIN(typeDecl->mAttributes->mTriviaStart, attributes->mTriviaStart);
- }
- if ((!IsNodeRelevant(deferredHeadNode, typeDecl)) && (!typeDecl->IsTemporary()) && (!findInitializer))
- {
- typeDecl->mIgnoreDeclaration = true;
- return;
- }
- BfAstNode* prevNode = NULL;
- bool isDone = !mVisitorPos.MoveNext();
- while (!isDone)
- {
- auto node = mVisitorPos.GetCurrent();
- if (node == prevNode)
- {
- BF_FATAL("Should have handled node already");
- // If we're stuck on an error and can't process any more nodes
- break;
- }
- prevNode = node;
- BfAstNode* typeMember = BfNodeDynCast<BfMemberDeclaration>(node);
- if (typeMember == NULL)
- {
- if (findInitializer)
- {
- bool isInitializerStatement = IsInitializerStatement(node);
- if (isInitializerStatement)
- return;
- }
- SetAndRestoreValue<BfAstNode*> prevTypeMemberNodeStart(mTypeMemberNodeStart, node);
- typeMember = ReadTypeMember(node);
- }
- //methodDeclaration->mDocumentation = FindDocumentation(methodDeclaration);
- isDone = !mVisitorPos.MoveNext();
- if (typeMember != NULL)
- {
- mVisitorPos.Write(typeMember);
- }
- }
- mVisitorPos.Trim();
- }
- void BfReducer::HandleRoot(BfRootNode* rootNode)
- {
- String fileName;
- auto parser = rootNode->GetSourceData()->ToParserData();
- if (parser != NULL)
- fileName = parser->mFileName;
- BP_ZONE_F("BfReducer::HandleRoot %s", fileName.c_str());
- mAlloc = &rootNode->GetSourceData()->mAlloc;
- mSystem = mSource->mSystem;
- HandleTopLevel(rootNode);
- BfSizedArrayInitIndirect(mSource->mSourceData->mExteriorNodes, mExteriorNodes, mAlloc);
- mAlloc = NULL;
- if (mPassInstance->HasFailed())
- mSource->mParsingFailed = true;
- }
- static String NodeToString(BfAstNode* node)
- {
- return String(&node->GetSourceData()->mSrc[node->GetSrcStart()], node->GetSrcLength());
- }
- BfInlineAsmStatement* BfReducer::CreateInlineAsmStatement(BfAstNode* asmNode)
- {
- auto asmToken = BfNodeDynCast<BfTokenNode>(asmNode);
- auto nextNode = mVisitorPos.GetNext();
- auto blockNode = BfNodeDynCast<BfInlineAsmStatement>(nextNode);
- if (blockNode == NULL)
- return (BfInlineAsmStatement*)Fail("Expected inline assembly block", asmNode);
- ReplaceNode(asmToken, blockNode);
- BfInlineAsmStatement* asmStatement = (BfInlineAsmStatement*)blockNode;
- {
- auto processInstrNodes = [&](const Array<BfAstNode*>& nodes) -> BfInlineAsmInstruction*
- {
- int nodeCount = (int)nodes.size();
- int curNodeIdx = 0;
- auto instNode = mAlloc->Alloc<BfInlineAsmInstruction>();
- //instNode->mSource = asmStatement->mSource;
- int srcStart = nodes.front()->GetSrcStart();
- int srcEnd = nodes.back()->GetSrcEnd();
- instNode->Init(srcStart, srcStart, srcEnd);
- auto replaceWithLower = [](String& s)
- {
- std::transform(s.begin(), s.end(), s.begin(), ::tolower);
- };
- auto readIdent = [&](String& outStr, bool forceLowerCase, const StringImpl& errorExpectation, bool peekOnly) -> bool
- {
- if (curNodeIdx >= nodeCount)
- {
- if (!peekOnly)
- Fail(StrFormat("Expected %s", errorExpectation.c_str()), instNode);
- return false;
- }
- BfAstNode* curNode = nodes[curNodeIdx];
- if (!peekOnly)
- ++curNodeIdx;
- if (!BfNodeDynCast<BfIdentifierNode>(curNode))
- {
- if (!peekOnly)
- Fail(StrFormat("Found \"%s\", expected %s", NodeToString(curNode).c_str(), errorExpectation.c_str()), instNode);
- return false;
- }
- outStr = NodeToString(curNode);
- if (forceLowerCase)
- replaceWithLower(outStr);
- return true;
- };
- auto readToken = [&](BfToken tokenType, const StringImpl& errorExpectation, bool peekOnly) -> bool
- {
- if (curNodeIdx >= nodeCount)
- {
- if (!peekOnly)
- Fail(StrFormat("Expected %s", errorExpectation.c_str()), instNode);
- return false;
- }
- BfAstNode* curNode = nodes[curNodeIdx];
- if (!peekOnly)
- ++curNodeIdx;
- auto tokenNode = BfNodeDynCast<BfTokenNode>(curNode);
- if (!tokenNode || tokenNode->GetToken() != tokenType)
- {
- if (!peekOnly)
- Fail(StrFormat("Found \"%s\", expected %s", NodeToString(curNode).c_str(), errorExpectation.c_str()), instNode);
- return false;
- }
- return true;
- };
- auto readInteger = [&](int& outInt, const StringImpl& errorExpectation, bool peekOnly, int& outAdvanceTokenCount) -> bool
- {
- int origCurNodeIdx = curNodeIdx;
- outAdvanceTokenCount = 0;
- bool negate = false;
- if (readToken(BfToken_Minus, "", true))
- {
- ++curNodeIdx;
- ++outAdvanceTokenCount;
- negate = true;
- }
- if (curNodeIdx >= nodeCount)
- {
- if (!peekOnly)
- Fail(StrFormat("Expected %s", errorExpectation.c_str()), instNode);
- else
- curNodeIdx = origCurNodeIdx;
- return false;
- }
- BfAstNode* curNode = nodes[curNodeIdx];
- ++curNodeIdx;
- ++outAdvanceTokenCount;
- auto litNode = BfNodeDynCast<BfLiteralExpression>(curNode);
- if (!litNode || litNode->mValue.mTypeCode != BfTypeCode_Int32)
- {
- if (!peekOnly)
- Fail(StrFormat("Found \"%s\", expected %s", NodeToString(curNode).c_str(), errorExpectation.c_str()), instNode);
- else
- curNodeIdx = origCurNodeIdx;
- return false;
- }
- outInt = litNode->mValue.mInt32;
- if (negate)
- outInt = -outInt;
- if (peekOnly)
- curNodeIdx = origCurNodeIdx;
- return true;
- };
- auto readArgMemPrimaryExpr = [&](BfInlineAsmInstruction::AsmArg& outArg) -> bool
- {
- String primaryIdent;
- int primaryInt;
- int advanceTokenCount = 0;
- if (readIdent(primaryIdent, false, "", true))
- {
- outArg.mMemFlags = BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg;
- outArg.mReg = primaryIdent;
- ++curNodeIdx;
- return true;
- }
- else if (readInteger(primaryInt, "", true, advanceTokenCount))
- {
- outArg.mMemFlags = BfInlineAsmInstruction::AsmArg::ARGMEMF_ImmediateDisp;
- outArg.mInt = primaryInt;
- curNodeIdx += advanceTokenCount;
- return true;
- }
- else
- {
- Fail(StrFormat("Found \"%s\", expected integer or identifier", NodeToString(nodes[curNodeIdx]).c_str()), instNode);
- return false;
- }
- };
- std::function<bool(BfInlineAsmInstruction::AsmArg&)> readArgMemMulExpr = [&](BfInlineAsmInstruction::AsmArg& outArg) -> bool
- {
- BfInlineAsmInstruction::AsmArg exprArgLeft, exprArgRight;
- if (!readArgMemPrimaryExpr(exprArgLeft))
- return false;
- if (!readToken(BfToken_Star, "", true))
- {
- outArg = exprArgLeft;
- return true;
- }
- ++curNodeIdx;
- if (!readArgMemMulExpr(exprArgRight))
- return false;
- bool leftIdent = (exprArgLeft.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg) != 0;
- bool rightIdent = (exprArgRight.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg) != 0;
- if (leftIdent && rightIdent)
- {
- Fail(StrFormat("Memory expressions can only scale by an integer", NodeToString(nodes[curNodeIdx]).c_str()), instNode);
- return false;
- }
- else if (leftIdent || rightIdent)
- {
- if (leftIdent)
- {
- outArg = exprArgLeft;
- outArg.mAdjRegScalar = exprArgRight.mInt;
- }
- else
- {
- outArg = exprArgRight;
- outArg.mAdjRegScalar = exprArgLeft.mInt;
- }
- outArg.mMemFlags &= ~BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg;
- outArg.mMemFlags |= BfInlineAsmInstruction::AsmArg::ARGMEMF_AdjReg;
- outArg.mAdjReg = outArg.mReg;
- outArg.mReg.clear();
- }
- else
- {
- outArg = exprArgLeft;
- outArg.mInt = exprArgLeft.mInt * exprArgRight.mInt;
- }
- return true;
- };
- std::function<bool(BfInlineAsmInstruction::AsmArg&, bool)> readArgMemAddExpr = [&](BfInlineAsmInstruction::AsmArg& outArg, bool subtractLeft) -> bool // can't use 'auto' here since it's recursive
- {
- BfInlineAsmInstruction::AsmArg exprArgLeft, exprArgRight;
- if (!readArgMemMulExpr(exprArgLeft))
- return false;
- if (subtractLeft)
- {
- if (exprArgLeft.mMemFlags != BfInlineAsmInstruction::AsmArg::ARGMEMF_ImmediateDisp)
- {
- Fail("Memory expressions can only subtract by an integer", instNode);
- return false;
- }
- exprArgLeft.mInt = -exprArgLeft.mInt;
- }
- bool subtract = false;
- if (!readToken(BfToken_Plus, "", true))
- {
- if (!readToken(BfToken_Minus, "", true))
- {
- outArg = exprArgLeft;
- return true;
- }
- else
- subtract = true;
- }
- ++curNodeIdx;
- if (!readArgMemAddExpr(exprArgRight, subtract))
- return false;
- bool leftScaling = (exprArgLeft.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_AdjReg) != 0;
- bool rightScaling = (exprArgRight.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_AdjReg) != 0;
- if (leftScaling && rightScaling)
- {
- Fail("Memory expressions can only have one scaling register and one non-scaling register", instNode);
- return false;
- }
- BfInlineAsmInstruction::AsmArg* scaledArg = leftScaling ? &exprArgLeft : (rightScaling ? &exprArgRight : nullptr);
- if (scaledArg)
- {
- BfInlineAsmInstruction::AsmArg* otherArg = leftScaling ? &exprArgRight : &exprArgLeft;
- outArg = *scaledArg;
- outArg.mMemFlags |= otherArg->mMemFlags;
- if (otherArg->mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg)
- {
- if (scaledArg->mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg)
- {
- Fail("Memory expressions can involve at most two registers", instNode);
- return false;
- }
- outArg.mReg = otherArg->mReg;
- }
- if (otherArg->mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_ImmediateDisp)
- {
- outArg.mInt += otherArg->mInt;
- }
- }
- else
- {
- outArg.mInt = 0;
- if (exprArgLeft.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_ImmediateDisp)
- {
- outArg.mMemFlags |= BfInlineAsmInstruction::AsmArg::ARGMEMF_ImmediateDisp;
- outArg.mInt += exprArgLeft.mInt;
- }
- if (exprArgRight.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_ImmediateDisp)
- {
- outArg.mMemFlags |= BfInlineAsmInstruction::AsmArg::ARGMEMF_ImmediateDisp;
- outArg.mInt += exprArgRight.mInt;
- }
- bool leftIdent = (exprArgLeft.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg) != 0;
- bool rightIdent = (exprArgRight.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg) != 0;
- if (leftIdent && rightIdent)
- {
- outArg.mMemFlags |= (BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg | BfInlineAsmInstruction::AsmArg::ARGMEMF_AdjReg);
- outArg.mReg = exprArgLeft.mReg;
- outArg.mAdjReg = exprArgRight.mReg;
- outArg.mAdjRegScalar = 1;
- }
- else if (leftIdent)
- {
- outArg.mMemFlags |= BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg;
- outArg.mReg = exprArgLeft.mReg;
- }
- else if (rightIdent)
- {
- outArg.mMemFlags |= BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg;
- outArg.mReg = exprArgRight.mReg;
- }
- }
- return true;
- };
- auto parseArg = [&](BfInlineAsmInstruction::AsmArg& outArg) -> bool
- {
- bool keepGoing = true;
- while (keepGoing)
- {
- keepGoing = false;
- int peekInt;
- String peekStr;
- int advanceTokenCount;
- if (readInteger(peekInt, "", true, advanceTokenCount))
- {
- outArg.mType = BfInlineAsmInstruction::AsmArg::ARGTYPE_Immediate;
- outArg.mInt = peekInt;
- curNodeIdx += advanceTokenCount;
- }
- else if (readIdent(peekStr, false, "", true))
- {
- ++curNodeIdx;
- String s(peekStr);
- replaceWithLower(s);
- String tempIdent;
- if ((s == "cs" || s == "ds" || s == "es" || s == "fs" || s == "gs" || s == "ss") && readToken(BfToken_Colon, "", true))
- {
- ++curNodeIdx;
- outArg.mSegPrefix = s;
- keepGoing = true;
- }
- else if (s == "st" && readToken(BfToken_LParen, "", true))
- {
- ++curNodeIdx;
- outArg.mType = BfInlineAsmInstruction::AsmArg::ARGTYPE_FloatReg;
- if (!readInteger(peekInt, "integer floating-point register number", false, advanceTokenCount))
- return false;
- outArg.mInt = peekInt;
- if (!readToken(BfToken_RParen, "')'", false))
- return false;
- }
- else if ((s == "byte" || s == "word" || s == "dword" || s == "qword" || s == "xword" || s == "xmmword" || s == "opaque") && readIdent(tempIdent, true, "", true))
- {
- if (tempIdent != "ptr")
- {
- Fail(StrFormat("Found \"%s\", expected \"ptr\"", NodeToString(nodes[curNodeIdx]).c_str()), instNode);
- return false;
- }
- ++curNodeIdx;
- outArg.mSizePrefix = s;
- keepGoing = true;
- }
- else
- {
- outArg.mType = BfInlineAsmInstruction::AsmArg::ARGTYPE_IntReg;
- outArg.mReg = peekStr;
- }
- }
- else if (readToken(BfToken_LBracket, "", true))
- {
- ++curNodeIdx;
- BfInlineAsmInstruction::AsmArg exprArgLeft;
- if (!readArgMemAddExpr(exprArgLeft, false))
- return false;
- if (!readToken(BfToken_RBracket, "']'", false))
- return false;
- if (readToken(BfToken_Dot, "", true))
- {
- ++curNodeIdx;
- if (!readIdent(outArg.mMemberSuffix, false, "struct member suffix identifier", false))
- return false;
- }
- outArg.mType = BfInlineAsmInstruction::AsmArg::ARGTYPE_Memory;
- outArg.mMemFlags = exprArgLeft.mMemFlags;
- //outArg.mSegPrefix = already_set_leave_me_alone;
- //outArg.mSizePrefix = already_set_leave_me_alone;
- outArg.mInt = exprArgLeft.mInt;
- outArg.mReg = exprArgLeft.mReg;
- outArg.mAdjReg = exprArgLeft.mAdjReg;
- outArg.mAdjRegScalar = exprArgLeft.mAdjRegScalar;
- //outArg.mMemberSuffix = already_set_leave_me_alone;
- return true;
- }
- else
- return false;
- }
- return true;
- };
- BfInlineAsmInstruction::AsmInst& outInst = instNode->mAsmInst;
- // instruction / instruction prefix / label
- String opStr;
- if (!readIdent(opStr, false, "instruction, instruction prefix, or label", false))
- return nullptr;
- if (readToken(BfToken_Colon, "", true))
- {
- ++curNodeIdx;
- outInst.mLabel = opStr;
- if (curNodeIdx >= nodeCount)
- return instNode;
- if (!readIdent(opStr, false, "instruction or instruction prefix", false))
- return nullptr;
- }
- replaceWithLower(opStr);
- // check for instruction prefix(s)
- while (opStr == "lock" || opStr == "rep" || opStr == "repe" || opStr == "repne" || opStr == "repz" || opStr == "repnz")
- {
- if (curNodeIdx >= nodeCount) // in case prefix is listed like a separate instruction
- break;
- outInst.mOpPrefixes.push_back(opStr);
- if (!readIdent(opStr, true, "instruction or instruction prefix", false))
- return nullptr;
- }
- outInst.mOpCode = opStr;
- BfInlineAsmInstruction::AsmArg asmArg;
- while (parseArg(asmArg))
- {
- outInst.mArgs.push_back(asmArg);
- asmArg = BfInlineAsmInstruction::AsmArg();
- if (!readToken(BfToken_Comma, "", true))
- break;
- ++curNodeIdx;
- }
- if (curNodeIdx < nodeCount)
- return (BfInlineAsmInstruction*)Fail(StrFormat("Found unexpected \"%s\"", NodeToString(nodes[curNodeIdx]).c_str()), instNode);
- //String testStr = outInst.ToString();
- int unusedLineChar = 0;
- auto bfParser = instNode->GetSourceData()->ToParserData();
- if (bfParser != NULL)
- bfParser->GetLineCharAtIdx(instNode->GetSrcStart(), outInst.mDebugLine, unusedLineChar);
- //return (BfInlineAsmInstruction*)Fail(StrFormat("Line %d\n", outInst.mDebugLine), instNode);
- return instNode;
- };
- // split nodes by newlines into individual instructions, skipping empty lines
- Array<BfAstNode*> instrNodes;
- Array<BfInlineAsmInstruction*> dstInstructions;
- //BCF: Add this back
- /*for (auto child = asmStatement->mChildren.mHead; child; child = child->mNext)
- {
- auto childToken = BfNodeDynCast<BfTokenNode>(child);
- if (childToken && childToken->GetToken() == BfToken_AsmNewline)
- {
- if (!instrNodes.empty())
- {
- BfInlineAsmInstruction* instNode = processInstrNodes(instrNodes);
- if (instNode)
- dstInstructions.push_back(instNode);
- instrNodes.clear();
- }
- }
- else if (childToken && childToken->GetToken() == BfToken_Asm)
- {
- // ignore the actual 'asm' keyword as we no longer need it
- continue; //CDH FIXME this is because ReplaceNode adds the original 'asm' keyword as a child, which I don't need; maybe I'm missing how the CST->AST replacment pattern is intended to work?
- }
- else
- {
- instrNodes.push_back(child);
- }
- }*/
- if (!instrNodes.empty())
- {
- BfInlineAsmInstruction* instNode = processInstrNodes(instrNodes);
- if (instNode)
- dstInstructions.push_back(instNode);
- instrNodes.Clear();
- }
- for (auto& instNode : dstInstructions)
- MoveNode(instNode, asmStatement);
- asmStatement->mInstructions = std::move(dstInstructions);
- }
- return asmStatement;
- }
|