parser.bmx 124 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721
  1. ' Copyright (c) 2013-2020 Bruce A Henderson
  2. '
  3. ' Based on the public domain Monkey "trans" by Mark Sibly
  4. '
  5. ' This software is provided 'as-is', without any express or implied
  6. ' warranty. In no event will the authors be held liable for any damages
  7. ' arising from the use of this software.
  8. '
  9. ' Permission is granted to anyone to use this software for any purpose,
  10. ' including commercial applications, and to alter it and redistribute it
  11. ' freely, subject to the following restrictions:
  12. '
  13. ' 1. The origin of this software must not be misrepresented; you must not
  14. ' claim that you wrote the original software. If you use this software
  15. ' in a product, an acknowledgment in the product documentation would be
  16. ' appreciated but is not required.
  17. '
  18. ' 2. Altered source versions must be plainly marked as such, and must not be
  19. ' misrepresented as being the original software.
  20. '
  21. ' 3. This notice may not be removed or altered from any source
  22. ' distribution.
  23. '
  24. SuperStrict
  25. Import BRL.MaxUtil
  26. Import "toker.bmx"
  27. Include "iparser.bmx"
  28. Global FILE_EXT$="bmx"
  29. Type TForEachinStmt Extends TLoopStmt
  30. Field varid$
  31. Field varty:TType
  32. Field varlocal:Int
  33. Field expr:TExpr
  34. Field varExpr:TExpr
  35. Method Create:TForEachinStmt( varid$,varty:TType,varlocal:Int,expr:TExpr,block:TBlockDecl,loopLabel:TLoopLabelDecl,varExpr:TExpr )
  36. Self.varid=varid
  37. Self.varty=varty
  38. Self.varlocal=varlocal
  39. Self.expr=expr
  40. Self.block=block
  41. block.extra = Self
  42. Self.loopLabel=loopLabel
  43. Self.varExpr = varExpr
  44. Return Self
  45. End Method
  46. Method OnCopy:TStmt( scope:TScopeDecl )
  47. If loopLabel Then
  48. If varExpr Then
  49. Return New TForEachinStmt.Create( varid,varty,varlocal,expr.Copy(),block.CopyBlock( scope ),TLoopLabelDecl(loopLabel.Copy()), varExpr.Copy() )
  50. Else
  51. Return New TForEachinStmt.Create( varid,varty,varlocal,expr.Copy(),block.CopyBlock( scope ),TLoopLabelDecl(loopLabel.Copy()), Null )
  52. End If
  53. Else
  54. If varExpr Then
  55. Return New TForEachinStmt.Create( varid,varty,varlocal,expr.Copy(),block.CopyBlock( scope ),Null, varExpr.Copy() )
  56. Else
  57. Return New TForEachinStmt.Create( varid,varty,varlocal,expr.Copy(),block.CopyBlock( scope ),Null, Null )
  58. End If
  59. End If
  60. End Method
  61. Method OnSemant()
  62. Const NotIterableError:String = "EachIn requires a type that implements IIterable or has a suitable ObjectEnumerator method."
  63. expr=expr.Semant()
  64. If TArrayType( expr.exprType ) Or TStringType( expr.exprType )
  65. Local exprTmp:TLocalDecl=New TLocalDecl.Create( "",Null,expr,,True )
  66. Local indexTmp:TLocalDecl=New TLocalDecl.Create( "",Null,New TConstExpr.Create( New TUIntType,"0" ),,True )
  67. Local lenExpr:TExpr=New TIdentExpr.Create( "Length",New TVarExpr.Create( exprTmp ) )
  68. Local cmpExpr:TExpr=New TBinaryCompareExpr.Create( "<",New TVarExpr.Create( indexTmp ),lenExpr )
  69. Local indexExpr:TExpr=New TIndexExpr.Create( New TVarExpr.Create( exprTmp ),[New TVarExpr.Create( indexTmp )] )
  70. Local addExpr:TExpr=New TBinaryMathExpr.Create( "+",New TVarExpr.Create( indexTmp ),New TConstExpr.Create( New TIntType,"1" ) )
  71. Local cont:TContinueStmt
  72. If varlocal
  73. ' array of object ?
  74. If TArrayType( expr.exprType ) And TObjectType(TArrayType( expr.exprType ).elemType) And (Not TObjectType(TArrayType( expr.exprType ).elemType).classdecl.IsExtern() ..
  75. Or (TObjectType(TArrayType( expr.exprType ).elemType).classdecl.IsExtern() ..
  76. And IsPointerType(TArrayType( expr.exprType ).elemType))) Then
  77. Local isStruct:Int = TObjectType(TArrayType( expr.exprType ).elemType).classdecl.IsStruct()
  78. Local cExpr:TExpr
  79. Local varObjTmp:TLocalDecl
  80. Local varObjStmt:TStmt
  81. exprTmp.Semant()
  82. indexTmp.Semant()
  83. If TIdentType(varty) And TIdentType(varty).ident = "Object" Then
  84. cExpr = indexExpr
  85. Else
  86. If TStringType(varty) Then
  87. varObjTmp = New TLocalDecl.Create( "",TType.objectType,indexExpr,,True)
  88. varObjTmp.Semant()
  89. Local varObjExpr:TExpr=New TVarExpr.Create( varObjTmp )
  90. Local expr:TExpr = New TFuncCallExpr.Create( New TIdentExpr.Create( "ObjectIsString"), [varObjExpr])
  91. expr=New TBinaryCompareExpr.Create( "=",expr, New TConstExpr.Create( New TIntType,"0" ))
  92. Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope, True, BLOCK_IF )
  93. Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope, True, BLOCK_ELSE )
  94. cont = New TContinueStmt.Create(Null, True)
  95. thenBlock.AddStmt cont
  96. varObjStmt = New TIfStmt.Create( expr,thenBlock,elseBlock, True )
  97. 'block.stmts.AddFirst New TIfStmt.Create( expr,thenBlock,elseBlock, True )
  98. cExpr = New TCastExpr.Create( varty, varObjExpr,CAST_EXPLICIT )
  99. Else
  100. cExpr = New TCastExpr.Create( varty, indexExpr,CAST_EXPLICIT )
  101. End If
  102. 'cExpr = New TCastExpr.Create( varty, indexExpr,CAST_EXPLICIT )
  103. End If
  104. ' local variable
  105. Local varTmp:TLocalDecl=New TLocalDecl.Create( varid,varty,cExpr )
  106. ' local var as expression
  107. Local expr:TExpr=New TVarExpr.Create( varTmp )
  108. If Not isStruct And Not varObjTmp Then
  109. ' var = Null
  110. expr=New TBinaryCompareExpr.Create( "=",expr, New TNullExpr.Create(TType.nullObjectType))
  111. ' then continue
  112. Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope, , BLOCK_IF )
  113. Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope, , BLOCK_ELSE )
  114. cont = New TContinueStmt
  115. thenBlock.AddStmt cont
  116. block.stmts.AddFirst New TIfStmt.Create( expr,thenBlock,elseBlock )
  117. End If
  118. block.stmts.AddFirst New TAssignStmt.Create( "=",New TVarExpr.Create( indexTmp ),addExpr )
  119. block.stmts.AddFirst New TDeclStmt.Create( varTmp )
  120. If varObjTmp Then
  121. block.stmts.AddFirst varObjStmt
  122. block.stmts.AddFirst New TDeclStmt.Create( varObjTmp, True )
  123. End If
  124. Else
  125. Local varTmp:TLocalDecl=New TLocalDecl.Create( varid,varty,indexExpr )
  126. block.stmts.AddFirst New TAssignStmt.Create( "=",New TVarExpr.Create( indexTmp ),addExpr, True )
  127. block.stmts.AddFirst New TDeclStmt.Create( varTmp, True )
  128. End If
  129. Else
  130. If TArrayType( expr.exprType ) And TObjectType(TArrayType( expr.exprType ).elemType) Then
  131. ' var = Null
  132. If Not varty Then
  133. varExpr = varExpr.Semant()
  134. varty = varExpr.exprType
  135. 'Local decl:TValDecl = block.scope.FindValDecl(varid.ToLower())
  136. 'If decl Then
  137. ' decl.Semant()
  138. '
  139. ' varty = decl.ty.Copy()
  140. 'End If
  141. End If
  142. Local isStruct:Int = TObjectType(TArrayType( expr.exprType ).elemType).classdecl.IsStruct()
  143. ' expr=New TBinaryCompareExpr.Create( "=",New TIdentExpr.Create( varid ), New TNullExpr.Create(TType.nullObjectType))
  144. If Not isStruct Then
  145. expr=New TBinaryCompareExpr.Create( "=",varExpr, New TNullExpr.Create(TType.nullObjectType))
  146. ' then continue
  147. Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope, , BLOCK_IF )
  148. Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope, , BLOCK_ELSE )
  149. cont = New TContinueStmt
  150. thenBlock.AddStmt cont
  151. block.stmts.AddFirst New TIfStmt.Create( expr,thenBlock,elseBlock )
  152. End If
  153. 'block.stmts.AddFirst New TDeclStmt.Create( varTmp )
  154. block.stmts.AddFirst New TAssignStmt.Create( "=",New TVarExpr.Create( indexTmp ),addExpr, True )
  155. ' block.stmts.AddFirst New TAssignStmt.Create( "=",New TIdentExpr.Create( varid ),New TCastExpr.Create( varty, indexExpr,CAST_EXPLICIT ), True )
  156. block.stmts.AddFirst New TAssignStmt.Create( "=",varExpr,New TCastExpr.Create( varty, indexExpr,CAST_EXPLICIT ), True )
  157. Else
  158. block.stmts.AddFirst New TAssignStmt.Create( "=",New TVarExpr.Create( indexTmp ),addExpr, True )
  159. ' block.stmts.AddFirst New TAssignStmt.Create( "=",New TIdentExpr.Create( varid ),indexExpr, True )
  160. block.stmts.AddFirst New TAssignStmt.Create( "=",varExpr,indexExpr, True )
  161. End If
  162. EndIf
  163. Local whileStmt:TWhileStmt=New TWhileStmt.Create( cmpExpr,block,loopLabel, True )
  164. block=New TBlockDecl.Create( block.scope, True, BLOCK_LOOP )
  165. block.AddStmt New TDeclStmt.Create( exprTmp, True )
  166. block.AddStmt New TDeclStmt.Create( indexTmp, True )
  167. block.AddStmt whileStmt
  168. If cont Then
  169. cont.loop = whileStmt
  170. End If
  171. Else If TObjectType( expr.exprType )
  172. Local tmpDecl:TDeclStmt
  173. Local iterable:Int
  174. ' ensure semanted
  175. TObjectType(expr.exprType).classDecl.Semant()
  176. If TObjectType(expr.exprType).classDecl.ImplementsInterface("iiterable") Or (TObjectType(expr.exprType).classDecl.ident="IIterable" And TObjectType(expr.exprType).classDecl.IsInterface()) Then
  177. iterable = True
  178. Else
  179. Local declList:TFuncDeclList = TFuncDeclList(TObjectType(expr.exprType).classDecl.GetDecl("objectenumerator"))
  180. If Not declList Then
  181. Err NotIterableError
  182. End If
  183. End If
  184. If TInvokeExpr(expr) Or TInvokeMemberExpr(expr) Then
  185. Local tmpVar:TLocalDecl=New TLocalDecl.Create( "",expr.exprType,expr,,True )
  186. tmpVar.Semant()
  187. tmpDecl = New TDeclStmt.Create( tmpVar, True )
  188. expr = New TVarExpr.Create( tmpVar )
  189. End If
  190. Local enumerInit:TExpr
  191. If iterable Then
  192. enumerInit = New TFuncCallExpr.Create( New TIdentExpr.Create( "GetIterator",expr ) )
  193. Else
  194. enumerInit = New TFuncCallExpr.Create( New TIdentExpr.Create( "ObjectEnumerator",expr ) )
  195. End If
  196. Local enumerTmp:TLocalDecl=New TLocalDecl.Create( "",Null,enumerInit,,True )
  197. enumerTmp.Semant()
  198. Local hasNextExpr:TExpr
  199. If iterable Then
  200. hasNextExpr = New TFuncCallExpr.Create( New TIdentExpr.Create( "MoveNext",New TVarExpr.Create( enumerTmp ) ) )
  201. Else
  202. hasNextExpr = New TFuncCallExpr.Create( New TIdentExpr.Create( "HasNext",New TVarExpr.Create( enumerTmp ) ) )
  203. End If
  204. Local nextObjExpr:TExpr
  205. If iterable Then
  206. nextObjExpr = New TFuncCallExpr.Create( New TIdentExpr.Create( "Current",New TVarExpr.Create( enumerTmp ) ) )
  207. Else
  208. nextObjExpr = New TFuncCallExpr.Create( New TIdentExpr.Create( "NextObject",New TVarExpr.Create( enumerTmp ) ) )
  209. End If
  210. Local cont:TContinueStmt
  211. If varlocal
  212. ' Local varTmp:TLocalDecl=New TLocalDecl.Create( varid,varty,nextObjExpr )
  213. ' block.stmts.AddFirst New TDeclStmt.Create( varTmp )
  214. Local cExpr:TExpr
  215. Local varObjTmp:TLocalDecl
  216. Local varObjStmt:TStmt
  217. If iterable Or (TIdentType(varty) And TIdentType(varty).ident = "Object") Then
  218. cExpr = nextObjExpr
  219. Else
  220. If TStringType(varty) Then
  221. varObjTmp = New TLocalDecl.Create( "",TType.objectType,nextObjExpr,,True)
  222. varObjTmp.Semant()
  223. Local varObjExpr:TExpr=New TVarExpr.Create( varObjTmp )
  224. Local expr:TExpr = New TFuncCallExpr.Create( New TIdentExpr.Create( "ObjectIsString"), [varObjExpr])
  225. expr=New TBinaryCompareExpr.Create( "=",expr, New TConstExpr.Create( New TIntType,"0" ))
  226. Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope, True, BLOCK_IF )
  227. Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope, True, BLOCK_ELSE )
  228. cont = New TContinueStmt.Create(Null, True)
  229. thenBlock.AddStmt cont
  230. varObjStmt = New TIfStmt.Create( expr,thenBlock,elseBlock, True )
  231. 'block.stmts.AddFirst New TIfStmt.Create( expr,thenBlock,elseBlock, True )
  232. cExpr = New TCastExpr.Create( varty, varObjExpr,CAST_EXPLICIT )
  233. Else
  234. cExpr = New TCastExpr.Create( varty, nextObjExpr,CAST_EXPLICIT )
  235. End If
  236. End If
  237. ' local variable
  238. Local varTmp:TLocalDecl=New TLocalDecl.Create( varid,varty,cExpr)
  239. If Not TNumericType(varty) And Not varObjTmp Then
  240. ' local var as expression
  241. Local expr:TExpr=New TVarExpr.Create( varTmp )
  242. ' var = Null
  243. expr=New TBinaryCompareExpr.Create( "=",expr, New TNullExpr.Create(TType.nullObjectType))
  244. ' then continue
  245. Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope, True, BLOCK_IF )
  246. Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope, True, BLOCK_ELSE )
  247. cont = New TContinueStmt.Create(Null, True)
  248. thenBlock.AddStmt cont
  249. block.stmts.AddFirst New TIfStmt.Create( expr,thenBlock,elseBlock, True )
  250. End If
  251. block.stmts.AddFirst New TDeclStmt.Create( varTmp, True )
  252. If varObjTmp Then
  253. block.stmts.AddFirst varObjStmt
  254. block.stmts.AddFirst New TDeclStmt.Create( varObjTmp, True )
  255. End If
  256. Else
  257. If Not varty Then
  258. varExpr = varExpr.Semant()
  259. varty = varExpr.exprType
  260. End If
  261. Local varObjTmp:TLocalDecl
  262. Local varObjStmt:TStmt
  263. Local cExpr:TExpr
  264. If TStringType(varty) Then
  265. varObjTmp = New TLocalDecl.Create( "",TType.objectType,nextObjExpr,,True)
  266. varObjTmp.Semant()
  267. Local varObjExpr:TExpr=New TVarExpr.Create( varObjTmp )
  268. Local expr:TExpr = New TFuncCallExpr.Create( New TIdentExpr.Create( "ObjectIsString"), [varObjExpr])
  269. expr=New TBinaryCompareExpr.Create( "=",expr, New TConstExpr.Create( New TIntType,"0" ))
  270. Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope, True, BLOCK_IF )
  271. Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope, True, BLOCK_ELSE )
  272. cont = New TContinueStmt.Create(Null, True)
  273. thenBlock.AddStmt cont
  274. varObjStmt = New TIfStmt.Create( expr,thenBlock,elseBlock, True )
  275. 'block.stmts.AddFirst New TIfStmt.Create( expr,thenBlock,elseBlock, True )
  276. cExpr = New TCastExpr.Create( varty, varObjExpr,CAST_EXPLICIT )
  277. Else
  278. cExpr = New TCastExpr.Create( varty, nextObjExpr,CAST_EXPLICIT )
  279. End If
  280. ' If Not varty Then
  281. ' Local decl:TValDecl = block.scope.FindValDecl(varid.ToLower())
  282. '
  283. ' If decl Then
  284. ' decl.Semant()
  285. '
  286. ' varty = decl.ty.Copy()
  287. ' End If
  288. ' End If
  289. ' var = Null
  290. ' Local expr:TExpr=New TBinaryCompareExpr.Create( "=",New TIdentExpr.Create( varid ), New TNullExpr.Create(TType.nullObjectType))
  291. If Not TNumericType(varty) And Not varObjTmp Then
  292. Local expr:TExpr=New TBinaryCompareExpr.Create( "=",varExpr, New TNullExpr.Create(TType.nullObjectType))
  293. ' then continue
  294. Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope, ,BLOCK_IF )
  295. Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope, ,BLOCK_ELSE )
  296. cont = New TContinueStmt
  297. thenBlock.AddStmt cont
  298. block.stmts.AddFirst New TIfStmt.Create( expr,thenBlock,elseBlock )
  299. 'block.stmts.AddFirst New TDeclStmt.Create( varTmp )
  300. End If
  301. ' block.stmts.AddFirst New TAssignStmt.Create( "=",New TIdentExpr.Create( varid ),New TCastExpr.Create( varty, nextObjExpr,CAST_EXPLICIT ))
  302. block.stmts.AddFirst New TAssignStmt.Create( "=",varExpr,cExpr)
  303. If varObjTmp Then
  304. block.stmts.AddFirst varObjStmt
  305. block.stmts.AddFirst New TDeclStmt.Create( varObjTmp, True )
  306. End If
  307. EndIf
  308. Local whileStmt:TWhileStmt=New TWhileStmt.Create( hasNextExpr,block, loopLabel, True )
  309. block=New TBlockDecl.Create( block.scope, True, BLOCK_LOOP )
  310. If tmpDecl Then
  311. block.AddStmt tmpDecl
  312. End If
  313. block.AddStmt New TDeclStmt.Create( enumerTmp, True )
  314. block.AddStmt whileStmt
  315. If cont Then
  316. cont.loop = whileStmt
  317. End If
  318. Else
  319. Err NotIterableError
  320. EndIf
  321. block.Semant
  322. End Method
  323. Method Trans$()
  324. _trans.EmitBlock block
  325. End Method
  326. End Type
  327. Type TIncbin
  328. Field file:String
  329. Field path:String
  330. Field id:Int
  331. Field length:Int
  332. Global count:Int
  333. Method Create:TIncbin(file:String, source:String)
  334. count :+ 1
  335. Self.file = file
  336. ' find the file
  337. If Not FileType(file) Then
  338. ' maybe relative to source
  339. Local dir:String = ExtractDir(source) + "/" + file
  340. If FileType(dir) = FILETYPE_FILE Then
  341. path = RealPath(dir)
  342. Else
  343. Return Null
  344. End If
  345. Else
  346. path = RealPath(file)
  347. End If
  348. id = count
  349. Return Self
  350. End Method
  351. End Type
  352. '***** Parser *****
  353. Type TParser Extends TGenProcessor
  354. Field _toker:TToker
  355. Field _toke:String
  356. Field _tokeType:Int
  357. Field _block:TBlockDecl
  358. Field _blockStack:TList=New TList'<TBlockDecl>
  359. Field _errStack:TStringList=New TStringList
  360. Field _app:TAppDecl
  361. Field _module:TModuleDecl
  362. Field _externCasts:TMap = New TMap
  363. Field unknownIdentsEvalFalse:Int
  364. Method SetErr(toker:TToker = Null)
  365. Local t:TToker = _toker
  366. If toker Then
  367. t = toker
  368. End If
  369. If t.Path()
  370. _errInfo=FormatError(t.Path(),t.Line(),0)
  371. EndIf
  372. End Method
  373. Method DoErr(error:String, toker:TToker = Null)
  374. SetErr(toker)
  375. Err error
  376. End Method
  377. Method PushBlock( block:TBlockDecl )
  378. If _block <> Null Then
  379. _blockStack.AddLast _block
  380. End If
  381. _errStack.AddLast _errInfo
  382. _block=block
  383. End Method
  384. Method PopBlock()
  385. _block=TBlockDecl(_blockStack.RemoveLast())
  386. _errInfo=String(_errStack.RemoveLast())
  387. End Method
  388. Method RealPath$( path$ )
  389. Local popDir$=CurrentDir()
  390. ChangeDir ExtractDir( _toker.Path() )
  391. path=BRL.FileSystem.RealPath( path )
  392. ChangeDir popDir
  393. Return path
  394. End Method
  395. Method ActualPath:String(path:String)
  396. Local dir:String = ExtractDir(path)
  397. Local origFile:String = StripDir(path)
  398. Local lowerFile:String = origFile.ToLower()
  399. Local actualDir:String = ExtractDir(RealPath(path))
  400. Local files:String[] = LoadDir(actualDir)
  401. For Local file:String = EachIn files
  402. If file.ToLower() = lowerFile Then
  403. If file <> origFile Then
  404. ' we could raise as a warning instead, but an error encourages the user to fix their code ;-)
  405. Err "Actual file '" + file + "' differs in case with import '" + origFile + "'"
  406. ' what we might do were we to warn instead...
  407. If dir Then
  408. Return dir + "/" + file
  409. Else
  410. Return file
  411. End If
  412. End If
  413. Exit
  414. End If
  415. Next
  416. Return path
  417. End Method
  418. Method NextToke$()
  419. Local toke$=_toke
  420. Repeat
  421. _toke=_toker.NextToke()
  422. _tokeType=_toker.TokeType()
  423. Until _tokeType<>TOKE_SPACE
  424. If _tokeType=TOKE_KEYWORD _toke=_toker._tokeLower
  425. If toke="," SkipEols
  426. Return _toke
  427. End Method
  428. Method NextTokeToker$(toker:TToker)
  429. ' Local toke$=toker._toke
  430. Repeat
  431. toker.NextToke()
  432. Until toker.tokeType()<>TOKE_SPACE
  433. Return toker._toke
  434. End Method
  435. Method DescribeToke:String( toke:String )
  436. Select toke
  437. Case "~n"
  438. Return "end-of-line"
  439. End Select
  440. Local uni:String
  441. If toke.length > 0 And toke[0] > 255 Then
  442. uni = " (unicode : " + _toker._lastTCHR + ")"
  443. End If
  444. Return "'" + toke + "'" + uni
  445. End Method
  446. Method CParse:Int( toke$ )
  447. If _toke.ToLower()<>toke
  448. Return False
  449. EndIf
  450. NextToke
  451. Return True
  452. End Method
  453. Method CParseToker:Int( toker:TToker, toke$ )
  454. If toker._toke.ToLower()<>toke
  455. Return False
  456. EndIf
  457. NextTokeToker(toker)
  458. Return True
  459. End Method
  460. Method Parse( toke$ )
  461. If Not CParse( toke )
  462. DoErr "Syntax error - expecting '"+toke+"' but found " + DescribeToke(toke)
  463. EndIf
  464. End Method
  465. Method ParseToker( toker:TToker, toke$ )
  466. If Not CParseToker( toker, toke )
  467. DoErr "Syntax error - expecting '"+toke+"'.", toker
  468. EndIf
  469. End Method
  470. Method AtEos:Int()
  471. Return _toke="" Or _toke=";" Or _toke="~n" Or _toke="else"
  472. End Method
  473. Method SkipEols()
  474. While CParse( "~n" ) Or CParse(";")
  475. Wend
  476. SetErr
  477. End Method
  478. Method SkipEolsToker(toker:TToker)
  479. While CParseToker( toker, "~n" )
  480. Wend
  481. SetErr
  482. End Method
  483. Method ParseStringLit$()
  484. If _tokeType<>TOKE_STRINGLIT Err "Expecting string literal."
  485. Local str$=BmxUnquote( _toke )
  486. NextToke
  487. Return str
  488. End Method
  489. Method ParseIdent$()
  490. Select _toke
  491. Case "@" NextToke
  492. Case "string","object", "self"
  493. Default
  494. If _tokeType<>TOKE_IDENT Then
  495. Local kw:String
  496. If _tokeType = TOKE_KEYWORD Then
  497. kw = " keyword"
  498. End If
  499. Err "Syntax error - expecting identifier, but found" + kw + " '" + EscapeLines(_toke) + "'"
  500. End If
  501. End Select
  502. Local id$=_toke
  503. NextToke
  504. Return id
  505. End Method
  506. Method ParseIdentType:TIdentType()
  507. Local id$=ParseIdent()
  508. If CParse( "." ) id:+"."+ParseIdent()
  509. If CParse( "." ) id:+"."+ParseIdent()
  510. Local args:TType[]
  511. If CParse( "<" )
  512. Local nargs:Int
  513. Repeat
  514. Local arg:TType = ParseType()
  515. Repeat
  516. If (_toke = "[" Or _toke = "[]") And IsArrayDef()
  517. arg = ParseArrayType(arg)
  518. Else If _toke = "(" Then
  519. Local argDecls:TArgDecl[] = ParseFuncParamDecl()
  520. arg = New TFunctionPtrType.Create(New TFuncDecl.CreateF("", arg, argDecls, FUNC_PTR))
  521. Else
  522. Exit
  523. End If
  524. Forever
  525. If args.Length=nargs args=args+ New TType[10]
  526. args[nargs]=arg
  527. nargs:+1
  528. Until Not CParse(",")
  529. args=args[..nargs]
  530. Parse ">"
  531. EndIf
  532. Return New TIdentType.Create( id,args )
  533. End Method
  534. Method CParseIdentType:TIdentType( inner:Int=False )
  535. If _tokeType<>TOKE_IDENT Return Null
  536. Local id$=ParseIdent()
  537. While CParse( "." )
  538. If _tokeType<>TOKE_IDENT Return Null
  539. id:+"."+ParseIdent()
  540. Wend
  541. If Not CParse( "<" )
  542. If inner Return New TIdentType.Create( id,Null )
  543. Return Null
  544. EndIf
  545. Local args:TType[]
  546. Local nargs:Int
  547. Repeat
  548. Local arg:TType=CParsePrimitiveType()
  549. If Not arg
  550. arg=CParseIdentType( True )
  551. If Not arg Return Null
  552. EndIf
  553. While IsArrayDef()
  554. arg = ParseArrayType(arg)
  555. Wend
  556. ' While CParse( "[]" )
  557. ' arg=arg.ArrayOf()
  558. ' Wend
  559. args = args + [arg]
  560. nargs :+ 1
  561. Until Not CParse(",")
  562. If Not CParse( ">" ) Return Null
  563. Return New TIdentType.Create( id,args )
  564. End Method
  565. Method CParsePrimitiveType:TType()
  566. If CParse( "string" ) Return TType.stringType
  567. If CParse( "object" ) Return New TIdentType.Create( "brl.classes.object" )
  568. Local ty:TType
  569. If CParse( "short" )
  570. ty = New TShortType
  571. Else If CParse( "byte" )
  572. ty = New TByteType
  573. Else If CParse( "int" )
  574. ty = New TIntType
  575. Else If CParse( "uint" )
  576. ty = New TUIntType
  577. Else If CParse( "float" )
  578. ty = New TFloatType
  579. Else If CParse( "long" )
  580. ty = New TLongType
  581. Else If CParse( "ulong" )
  582. ty = New TULongType
  583. Else If CParse( "double" )
  584. ty = New TDoubleType
  585. Else If CParse( "size_t" )
  586. ty = New TSizeTType
  587. Else If CParse( "int128" ) Then
  588. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  589. ty = New TInt128Type
  590. Else If CParse( "float128" ) Then
  591. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  592. ty = New TFloat128Type
  593. Else If CParse( "double128" ) Then
  594. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  595. ty = New TDouble128Type
  596. Else If CParse( "float64" ) Then
  597. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  598. ty = New TFloat64Type
  599. Else If CParse( "wparam" ) Then
  600. If opt_platform <> "win32" Err "WParam types only available on Win32"
  601. ty = New TWParamType
  602. Else If CParse( "lparam" ) Then
  603. If opt_platform <> "win32" Err "LParam types only available on Win32"
  604. ty = New TLParamType
  605. End If
  606. While CParse("ptr")
  607. ty = TType.MapToPointerType(ty)
  608. Wend
  609. Return ty
  610. End Method
  611. Method CParsePrimitiveNumberType:TType()
  612. If CParse( "short" ) Return New TShortType
  613. If CParse( "byte" ) Return New TByteType
  614. If CParse( "int" ) Return New TIntType
  615. If CParse( "uint" ) Return New TUIntType
  616. If CParse( "float" ) Return New TFloatType
  617. If CParse( "long" ) Return New TLongType
  618. If CParse( "ulong" ) Return New TULongType
  619. If CParse( "double" ) Return New TDoubleType
  620. If CParse( "size_t" ) Return New TSizeTType
  621. If CParse( "int128" ) Then
  622. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  623. Return New TInt128Type
  624. End If
  625. If CParse( "float128" ) Then
  626. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  627. Return New TFloat128Type
  628. End If
  629. If CParse( "double128" ) Then
  630. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  631. Return New TDouble128Type
  632. End If
  633. If CParse( "float64" ) Then
  634. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  635. Return New TFloat64Type
  636. End If
  637. If CParse( "wparam" ) Then
  638. If opt_platform <> "win32" Err "WParam types only available on Win32"
  639. Return New TWParamType
  640. End If
  641. If CParse( "lparam" ) Then
  642. If opt_platform <> "win32" Err "LParam types only available on Win32"
  643. Return New TLParamType
  644. End If
  645. End Method
  646. Method ParseNewType:TType()
  647. If CParse( "void" ) Return New TVoidType
  648. If CParse( "short" ) Return New TShortType
  649. If CParse( "byte" ) Return New TByteType
  650. If CParse( "int" ) Return New TIntType
  651. If CParse( "uint" ) Return New TUIntType
  652. If CParse( "float" ) Return New TFloatType
  653. If CParse( "string" ) Return TType.stringType
  654. If CParse( "object" ) Return New TIdentType.Create( "brl.classes.object" )
  655. If CParse( "long" ) Return New TLongType
  656. If CParse( "ulong" ) Return New TULongType
  657. If CParse( "double" ) Return New TDoubleType
  658. If CParse( "size_t" ) Return New TSizeTType
  659. If CParse( "int128" ) Then
  660. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  661. Return New TInt128Type
  662. End If
  663. If CParse( "float128" ) Then
  664. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  665. Return New TFloat128Type
  666. End If
  667. If CParse( "double128" ) Then
  668. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  669. Return New TDouble128Type
  670. End If
  671. If CParse( "float64" ) Then
  672. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  673. Return New TFloat64Type
  674. End If
  675. If CParse( "wparam" ) Then
  676. If opt_platform <> "win32" Err "WParam types only available on Win32"
  677. Return New TWParamType
  678. End If
  679. If CParse( "lparam" ) Then
  680. If opt_platform <> "win32" Err "LParam types only available on Win32"
  681. Return New TLParamType
  682. End If
  683. Return ParseIdentType()
  684. End Method
  685. Method ParseType:TType()
  686. Local ty:TType=CParsePrimitiveType()
  687. If ty Return ty
  688. Return ParseIdentType()
  689. End Method
  690. Method ParseConstNumberType:TType()
  691. Local ty:TType
  692. Select _toke
  693. Case "@"
  694. NextToke
  695. ty=New TByteType
  696. While CParse("ptr")
  697. ty = TType.MapToPointerType(ty)
  698. Wend
  699. Case "@@"
  700. NextToke
  701. ty=New TShortType
  702. While CParse("ptr")
  703. ty = TType.MapToPointerType(ty)
  704. Wend
  705. Case "%"
  706. NextToke
  707. ty=New TIntType
  708. While CParse("ptr")
  709. ty = TType.MapToPointerType(ty)
  710. Wend
  711. Case "#"
  712. NextToke
  713. ty=New TFloatType
  714. While CParse("ptr")
  715. ty = TType.MapToPointerType(ty)
  716. Wend
  717. Case "$"
  718. NextToke
  719. ty=New TStringType
  720. Case "!"
  721. NextToke
  722. ty=New TDoubleType
  723. While CParse("ptr")
  724. ty = TType.MapToPointerType(ty)
  725. Wend
  726. Case "%%"
  727. NextToke
  728. ty=New TLongType
  729. While CParse("ptr")
  730. ty = TType.MapToPointerType(ty)
  731. Wend
  732. Case ":"
  733. NextToke
  734. ty=CParsePrimitiveNumberType()
  735. If Not ty Then
  736. If CParse("string") Then
  737. ty=New TStringType
  738. Else
  739. ty = ParseIdentType()
  740. End If
  741. Else
  742. While CParse("ptr")
  743. ty = TType.MapToPointerType(ty)
  744. Wend
  745. End If
  746. End Select
  747. While IsArrayDef()
  748. ty = ParseArrayType(ty)
  749. Wend
  750. 'While CParse( "[]" )
  751. ' ty=New TArrayType.Create( ty )
  752. 'Wend
  753. Return ty
  754. End Method
  755. Method ParseDeclType:TType(attr:Int = 0)
  756. Local ty:TType
  757. Select _toke
  758. Case "@"
  759. NextToke
  760. ty=New TByteType
  761. While CParse("ptr")
  762. ty = TType.MapToPointerType(ty)
  763. Wend
  764. Case "@@"
  765. NextToke
  766. ty=New TShortType
  767. While CParse("ptr")
  768. ty = TType.MapToPointerType(ty)
  769. Wend
  770. Case "%"
  771. NextToke
  772. ty=New TIntType
  773. While CParse("ptr")
  774. ty = TType.MapToPointerType(ty)
  775. Wend
  776. Case "%%"
  777. NextToke
  778. ty=New TLongType
  779. While CParse("ptr")
  780. ty = TType.MapToPointerType(ty)
  781. Wend
  782. Case "#"
  783. NextToke
  784. ty=New TFloatType
  785. If CParse("ptr") Then
  786. ty = TType.MapToPointerType(ty)
  787. End If
  788. Case "$"
  789. NextToke
  790. ty=New TStringType
  791. If CParse("z") Then
  792. ty._flags :| TType.T_CHAR_PTR
  793. Else If CParse("w") Then
  794. ty._flags :| TType.T_SHORT_PTR
  795. End If
  796. Case "!"
  797. NextToke
  798. ty=New TDoubleType
  799. While CParse("ptr")
  800. ty = TType.MapToPointerType(ty)
  801. Wend
  802. Case ":"
  803. NextToke
  804. ty=ParseType()
  805. If CParse("ptr") Then
  806. ' FIXME #200
  807. 'If TStringType(ty) = Null And (TObjectType(ty) = Null Or (TObjectType(ty) <> Null And TObjectType(ty).classDecl.IsExtern())) And TArrayType(ty) = Null Then
  808. ty = TType.MapToPointerType(ty)
  809. While CParse("ptr")
  810. ty = TType.MapToPointerType(ty)
  811. Wend
  812. 'Else
  813. ' ty = Null
  814. 'End If
  815. If Not ty DoErr "Invalid Pointer type."
  816. End If
  817. Case "("
  818. ' for Strict code, void will be converted to Int during semanting.
  819. ty=New TVoidType
  820. Default
  821. If _module.IsSuperStrict() Err "Missing type specifier."
  822. ty=New TIntType
  823. While CParse("ptr")
  824. ty = TType.MapToPointerType(ty)
  825. Wend
  826. End Select
  827. ' array or function pointer?
  828. Repeat
  829. If (_toke = "[" Or _toke = "[]") And IsArrayDef(attr & DECL_STATIC > 0)
  830. ty = ParseArrayType(ty, attr & DECL_STATIC > 0)
  831. Else If _toke = "(" Then
  832. Local args:TArgDecl[] = ParseFuncParamDecl()
  833. attr :| ParseCallConvention(attr & DECL_API_STDCALL)
  834. ty = New TFunctionPtrType.Create(New TFuncDecl.CreateF("", ty, args, FUNC_PTR | (attr & DECL_API_STDCALL)))
  835. Else
  836. Exit
  837. End If
  838. Forever
  839. Return ty
  840. End Method
  841. Method ParseArrayExpr:TArrayExpr()
  842. Parse "["
  843. Local args:TExpr[],nargs:Int
  844. Repeat
  845. Local arg:TExpr=ParseExpr()
  846. If args.Length=nargs args=args + New TExpr[10]
  847. args[nargs]=arg
  848. nargs:+1
  849. Until Not CParse(",")
  850. args=args[..nargs]
  851. Parse "]"
  852. Return New TArrayExpr.Create( args )
  853. End Method
  854. ' replaces While CParse( "[]" ) sections, with support for multi-dimension arrays
  855. Method ParseArrayType:TType(ty:TType, isStatic:Int = False)
  856. If isStatic Then
  857. Parse("[")
  858. Local expr:TExpr = ParseUnaryExpr()
  859. ty = New TArrayType.Create( ty )
  860. TArrayType(ty).isStatic = True
  861. TArrayType(ty).length = expr.Eval()
  862. Parse("]")
  863. Return ty
  864. End If
  865. While True
  866. Local dims:Int = 1
  867. If CParse("[]") Then
  868. ty=New TArrayType.Create( ty )
  869. ' test for array of arrays
  870. If IsArrayTypeNext(_toker) Continue
  871. Exit
  872. End If
  873. If Not CParse("[") Then
  874. Exit
  875. End If
  876. While CParse( ",")
  877. dims :+ 1
  878. Wend
  879. Parse "]"
  880. ty=New TArrayType.Create( ty, dims )
  881. ' test for array of arrays
  882. If IsArrayTypeNext(_toker) Continue
  883. Exit
  884. Wend
  885. Return ty
  886. End Method
  887. Method IsArrayTypeNext:Int(tok:TToker)
  888. Local toker:TToker=New TToker.Copy(tok)
  889. If CParseToker(toker, "[]") Return True
  890. If CParseToker(toker, "[") Then
  891. ' look ahead to see if this is an array decl, or something else..
  892. If CParseToker(toker, "]") Or CParseToker(toker, ",") Then
  893. Return True
  894. End If
  895. End If
  896. Return False
  897. End Method
  898. Method IsArrayDef:Int(isStatic:Int = False)
  899. Local isDef:Int = True
  900. Local toker:TToker=New TToker.Copy(_toker)
  901. If isStatic Then
  902. If Not CParseToker(toker, "[") Then
  903. Return False
  904. End If
  905. NextTokeToker(toker)
  906. If Not CParseToker(toker, "]") Then
  907. Return False
  908. End If
  909. Return True
  910. End If
  911. While True
  912. 'Local dims:Int = 1
  913. If CParseToker(toker, "[]") Then
  914. Exit
  915. End If
  916. If Not CParseToker(toker, "[") Then
  917. isDef = False
  918. Exit
  919. End If
  920. While CParseToker(toker, ",")
  921. 'dims :+ 1
  922. Wend
  923. If Not CParseToker(toker, "]") Then
  924. isDef = False
  925. Exit
  926. End If
  927. Exit
  928. Wend
  929. Return isDef
  930. End Method
  931. Method ParseArgs:TExpr[]( stmt:Int )
  932. Local args:TExpr[]
  933. If stmt
  934. If AtEos() Return args
  935. Else
  936. If _toke<>"(" Return args
  937. EndIf
  938. Local nargs:Int,eat:Int
  939. If _toke="("
  940. If stmt
  941. Local toker:TToker=New TToker.Copy(_toker),bra:Int=1
  942. Repeat
  943. toker.NextToke
  944. toker.SkipSpace
  945. Select toker.Toke().ToLower()
  946. Case "","else"
  947. Err "Parenthesis mismatch error."
  948. Case "(","["
  949. bra:+1
  950. Case "]",")"
  951. bra:-1
  952. If bra Continue
  953. toker.NextToke
  954. toker.SkipSpace
  955. Select toker.Toke().ToLower()
  956. Case ".","(","[","",";","~n","else"
  957. eat=True
  958. End Select
  959. Exit
  960. Case ","
  961. If bra<>1 Continue
  962. eat=True
  963. Exit
  964. End Select
  965. Forever
  966. Else
  967. eat=True
  968. EndIf
  969. If eat And NextToke()=")"
  970. NextToke
  971. Return args
  972. EndIf
  973. EndIf
  974. Repeat
  975. Local arg:TExpr
  976. If _toke And _toke<>"," arg=ParseExpr()
  977. If args.Length=nargs args=args + New TExpr[10]
  978. args[nargs]=arg
  979. nargs:+1
  980. Until Not CParse(",")
  981. args=args[..nargs]
  982. If eat Parse ")"
  983. Return args
  984. End Method
  985. Method ParsePrimaryExpr:TExpr( stmt:Int )
  986. Local expr:TExpr
  987. Select _toke.ToLower()
  988. Case "("
  989. NextToke
  990. expr=ParseExpr()
  991. Parse ")"
  992. Case "["
  993. expr=ParseArrayExpr()
  994. Case "[]"
  995. NextToke
  996. expr=New TConstExpr.Create( TType.emptyArrayType,"" )
  997. Case "."
  998. expr=New TScopeExpr.Create( _module )
  999. Case "new"
  1000. NextToke
  1001. If _toke = "(" Then
  1002. ' call constructor
  1003. expr=New TNewExpr.Create( ParseArgs(stmt) )
  1004. Else
  1005. Local ty:TType=ParseType()
  1006. While CParse("ptr")
  1007. ty = TType.MapToPointerType(ty)
  1008. Wend
  1009. If _toke = "[" Or _toke = "[]" Then
  1010. Local depth:Int = 0
  1011. Local ln:TExpr[]
  1012. Local tmpTy:TType = ty.Copy()
  1013. Repeat
  1014. Local dims:Int = 1
  1015. If CParse("[]") Then
  1016. tmpTy=New TArrayType.Create( tmpTy )
  1017. depth :+ 1
  1018. Continue
  1019. End If
  1020. ' looking for an array with expression
  1021. If Not ln Then
  1022. Parse "["
  1023. Else
  1024. If Not CParse("[") Then
  1025. Exit
  1026. Else
  1027. Err "Unexpected '[' after array size declaration"
  1028. End If
  1029. End If
  1030. Repeat
  1031. If CParse(",") Then
  1032. dims :+ 1
  1033. Continue
  1034. End If
  1035. If CParse("]") Exit
  1036. ln = ln + [ParseExpr()]
  1037. If CParse("]") Exit
  1038. Parse(",")
  1039. dims :+ 1
  1040. Forever
  1041. If Not ln Then
  1042. tmpTy=New TArrayType.Create( tmpTy, dims )
  1043. End If
  1044. Forever
  1045. If ln Then
  1046. ty = tmpTy
  1047. End If
  1048. ' Repeat
  1049. 'If CParse( "[" )
  1050. ' Repeat
  1051. ' ln = ln + [ParseExpr()]
  1052. ' If CParse("]") Exit
  1053. ' Parse ","
  1054. ' Forever
  1055. 'Parse "]"
  1056. ' ty = ParseArrayType(ty)
  1057. ' Forever
  1058. 'While CParse( "[]" )
  1059. ' ty=New TArrayType.Create( ty)
  1060. 'Wend
  1061. expr=New TNewArrayExpr.Create( ty,ln )
  1062. Else
  1063. expr=New TNewObjectExpr.Create( ty,ParseArgs( stmt ) )
  1064. EndIf
  1065. End If
  1066. Case "null"
  1067. NextToke
  1068. expr = New TNullExpr.Create(TType.nullObjectType)
  1069. 'expr=New TConstExpr.Create( TType.nullObjectType,"" )
  1070. Case "true"
  1071. NextToke
  1072. expr=New TConstExpr.Create( New TIntType,"1" )
  1073. Case "false"
  1074. NextToke
  1075. expr=New TConstExpr.Create( New TIntType,"" )
  1076. Case "int","long","float","double","object","short","byte","size_t","uint","ulong","int128","float64","float128","double128","lparam","wparam","string"
  1077. Local id$=_toke
  1078. Local ty:TType=ParseType()
  1079. If TIntType(ty) And id.ToLower() <> "int" Then
  1080. Select id.ToLower()
  1081. Case "byte"
  1082. ty = New TByteType
  1083. Case "short"
  1084. ty = New TShortType
  1085. Case "uint"
  1086. ty = New TUIntType
  1087. Case "long"
  1088. ty = New TLongType
  1089. Case "ulong"
  1090. ty = New TULongType
  1091. Case "float"
  1092. ty = New TFloatType
  1093. Case "double"
  1094. ty = New TDoubleType
  1095. Case "size_t"
  1096. ty = New TSizeTType
  1097. Case "int128"
  1098. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  1099. ty = New TInt128Type
  1100. Case "float128"
  1101. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  1102. ty = New TFloat128Type
  1103. Case "double128"
  1104. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  1105. ty = New TDouble128Type
  1106. Case "float64"
  1107. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  1108. ty = New TFloat64Type
  1109. Case "wparam"
  1110. If opt_platform <> "win32" Err "WParam types only available on Win32"
  1111. ty = New TWParamType
  1112. Case "lparam"
  1113. If opt_platform <> "win32" Err "LParam types only available on Win32"
  1114. ty = New TLParamType
  1115. End Select
  1116. End If
  1117. While CParse("ptr")
  1118. ty = TType.MapToPointerType(ty)
  1119. Wend
  1120. ' array
  1121. ty = ParseArrayType(ty)
  1122. ' optional brackets
  1123. If CParse( "(" )
  1124. expr=ParseExpr()
  1125. Parse ")"
  1126. expr=New TCastExpr.Create( ty,expr,CAST_EXPLICIT )
  1127. Else
  1128. Local tok:TToker=New TToker.Copy( _toker )
  1129. If id="string" And CParseToker(tok, ".") Then
  1130. expr=New TIdentExpr.Create( id )
  1131. Else
  1132. expr=ParseExpr()
  1133. If TBinaryExpr(expr) Then
  1134. ' cast lhs and apply to rhs
  1135. Local cexpr:TCastExpr=New TCastExpr.Create( ty,TBinaryExpr(expr).lhs,CAST_EXPLICIT )
  1136. TBinaryExpr(expr).lhs = cexpr
  1137. Else
  1138. expr=New TCastExpr.Create( ty,expr,CAST_EXPLICIT )
  1139. End If
  1140. End If
  1141. EndIf
  1142. Case "sizeof"
  1143. NextToke
  1144. Local ty:TType = ParseConstNumberType()
  1145. If ty Then
  1146. If Not TIntType(ty) Then
  1147. Err "Return type for 'SizeOf' must be Int"
  1148. End If
  1149. End If
  1150. ' optional brackets
  1151. If CParse( "(" )
  1152. expr=ParseExpr()
  1153. Parse ")"
  1154. expr=New TSizeOfExpr.Create( expr )
  1155. Else
  1156. expr=ParseExpr()
  1157. expr=New TSizeOfExpr.Create( expr )
  1158. EndIf
  1159. Case "len"
  1160. NextToke
  1161. Local ty:TType = ParseConstNumberType()
  1162. If ty Then
  1163. If Not TIntType(ty) Then
  1164. Err "Return type for 'Len' must be Int"
  1165. End If
  1166. End If
  1167. ' optional brackets
  1168. If CParse( "(" )
  1169. expr=ParseExpr()
  1170. Parse ")"
  1171. expr=New TLenExpr.Create( expr )
  1172. Else
  1173. expr=ParseExpr()
  1174. expr=New TLenExpr.Create( expr )
  1175. EndIf
  1176. Case "asc"
  1177. NextToke
  1178. Local ty:TType = ParseConstNumberType()
  1179. If ty Then
  1180. If Not TIntType(ty) Then
  1181. Err "Return type for 'Asc' must be Int"
  1182. End If
  1183. End If
  1184. ' optional brackets
  1185. If CParse( "(" )
  1186. expr=ParseExpr()
  1187. Parse ")"
  1188. expr=New TAscExpr.Create( expr )
  1189. Else
  1190. expr=ParseExpr()
  1191. expr=New TAscExpr.Create( expr )
  1192. EndIf
  1193. Case "chr"
  1194. NextToke
  1195. Local ty:TType = ParseConstNumberType()
  1196. If ty Then
  1197. If Not TStringType(ty) Then
  1198. Err "Return type for 'Chr' must be String"
  1199. End If
  1200. End If
  1201. ' optional brackets
  1202. If CParse( "(" )
  1203. expr=ParseExpr()
  1204. Parse ")"
  1205. expr=New TChrExpr.Create( expr )
  1206. Else
  1207. expr=ParseExpr()
  1208. expr=New TChrExpr.Create( expr )
  1209. EndIf
  1210. Case "varptr"
  1211. NextToke
  1212. expr=ParseExpr()
  1213. expr=New TCastExpr.Create( New TVarPtrType, expr, CAST_EXPLICIT )
  1214. Case "pi"
  1215. NextToke
  1216. expr=New TConstExpr.Create( New TDoubleType, Pi )
  1217. Case "self"
  1218. NextToke
  1219. expr=New TSelfExpr
  1220. Case "super"
  1221. NextToke
  1222. Parse "."
  1223. If _toke="new"
  1224. Err "Call to super class constructor must be first statement in a constructor."
  1225. EndIf
  1226. Local id$=ParseIdent()
  1227. ' eat any type stuff
  1228. ParseConstNumberType()
  1229. expr=New TInvokeSuperExpr.Create( id,ParseArgs( stmt ) )
  1230. Case "stackalloc"
  1231. NextToke
  1232. ' optional brackets
  1233. If CParse( "(" )
  1234. expr=ParseExpr()
  1235. Parse ")"
  1236. expr=New TStackAllocExpr.Create( expr )
  1237. Else
  1238. expr=ParseExpr()
  1239. expr=New TStackAllocExpr.Create( expr )
  1240. EndIf
  1241. Case "fieldoffset"
  1242. NextToke
  1243. Local withBrackets:Int
  1244. If CParse("(")
  1245. withBrackets = True
  1246. End If
  1247. Local typeExpr:TExpr = ParseExpr()
  1248. Parse ","
  1249. Local fieldExpr:TExpr = ParseExpr()
  1250. If withBrackets Then
  1251. Parse(")")
  1252. End If
  1253. expr=New TFieldOffsetExpr.Create( typeExpr, fieldExpr )
  1254. Default
  1255. Select _tokeType
  1256. Case TOKE_IDENT
  1257. Local tok:TToker=New TToker.Copy( _toker )
  1258. Local ty:TType=CParseIdentType()
  1259. If ty
  1260. expr=New TIdentTypeExpr.Create( ty )
  1261. Else
  1262. _toker=tok
  1263. _toke=_toker.Toke()
  1264. _tokeType=_toker.TokeType()
  1265. expr=New TIdentExpr.Create( ParseIdent(),,,unknownIdentsEvalFalse )
  1266. ty = ParseConstNumberType()
  1267. If TArrayType(ty) Then
  1268. If Not TArrayType(ty).elemType Then
  1269. TArrayType(ty).elemType = New TIdentType.Create(TIdentExpr(expr).ident)
  1270. expr=New TIdentTypeExpr.Create( ty )
  1271. End If
  1272. End If
  1273. EndIf
  1274. 'expr=New TIdentExpr.Create( ParseIdent() )
  1275. Case TOKE_INTLIT
  1276. expr=New TConstExpr.Create( New TIntType,_toke )
  1277. NextToke
  1278. Local ty:TType = ParseConstNumberType()
  1279. If ty Then
  1280. TConstExpr(expr).UpdateType(ty)
  1281. End If
  1282. Case TOKE_LONGLIT
  1283. expr=New TConstExpr.Create( New TLongType,_toke )
  1284. NextToke
  1285. Local ty:TType = ParseConstNumberType()
  1286. If ty Then
  1287. TConstExpr(expr).UpdateType(ty)
  1288. End If
  1289. Case TOKE_FLOATLIT
  1290. expr=New TConstExpr.Create( New TFloatType,_toke )
  1291. NextToke
  1292. Local ty:TType = ParseConstNumberType()
  1293. If ty Then
  1294. TConstExpr(expr).ty = ty
  1295. End If
  1296. Case TOKE_STRINGLIT
  1297. Local s:String = BmxUnquote( _toke )
  1298. expr=New TConstExpr.Create( TType.stringType,s )
  1299. _app.mapStringConsts(s)
  1300. NextToke
  1301. Case TOKE_STRINGMULTI
  1302. Local s:String = BmxProcessMultiString( _toke )
  1303. expr=New TConstExpr.Create( TType.stringType,s )
  1304. _app.mapStringConsts(s)
  1305. NextToke
  1306. Default
  1307. Err "Expecting expression but encountered "+DescribeToke(_toke)
  1308. End Select
  1309. End Select
  1310. Repeat
  1311. Select _toke
  1312. Case "."
  1313. NextToke
  1314. expr=New TIdentExpr.Create( ParseIdent(),expr )
  1315. ParseConstNumberType()
  1316. 'DebugLog expr.ToString()
  1317. Case "("
  1318. If expr = Null Then
  1319. NextToke
  1320. expr=ParseExpr()
  1321. Parse ")"
  1322. Else
  1323. expr=New TFuncCallExpr.Create( expr,ParseArgs( stmt ) )
  1324. End If
  1325. Case "["
  1326. NextToke
  1327. If CParse( ".." )
  1328. If _toke="]"
  1329. expr=New TSliceExpr.Create( expr,Null,Null )
  1330. Else
  1331. expr=New TSliceExpr.Create( expr,Null,ParseExpr() )
  1332. EndIf
  1333. Parse "]"
  1334. Else
  1335. Local from:TExpr=ParseExpr()
  1336. If CParse( ".." )
  1337. If _toke="]"
  1338. expr=New TSliceExpr.Create( expr,from,Null )
  1339. Else
  1340. expr=New TSliceExpr.Create( expr,from,ParseExpr() )
  1341. EndIf
  1342. Parse "]"
  1343. Else
  1344. Local ind:TExpr[] = [from]
  1345. Repeat
  1346. If CParse("]") Then
  1347. Exit
  1348. End If
  1349. Parse ","
  1350. ind = ind + [ParseExpr()]
  1351. Forever
  1352. expr=New TIndexExpr.Create( expr,ind )
  1353. EndIf
  1354. EndIf
  1355. Default
  1356. Return expr
  1357. End Select
  1358. Forever
  1359. End Method
  1360. Method ParseUnaryExpr:TExpr()
  1361. Local op$=_toke
  1362. Select op
  1363. Case "+","-","~~","not"
  1364. NextToke
  1365. Local expr:TExpr=ParseUnaryExpr()
  1366. Return New TUnaryExpr.Create( op,expr )
  1367. End Select
  1368. Return ParsePrimaryExpr( False )
  1369. End Method
  1370. Method ParsePowExpr:TExpr()
  1371. Local expr:TExpr=ParseUnaryExpr()
  1372. Repeat
  1373. Local op$=_toke
  1374. Select op
  1375. Case "^"
  1376. NextToke
  1377. Local rhs:TExpr=ParseUnaryExpr()
  1378. expr=New TBinaryMathExpr.Create( op,expr,rhs )
  1379. Default
  1380. Return expr
  1381. End Select
  1382. Forever
  1383. End Method
  1384. Method ParseMulDivExpr:TExpr()
  1385. Local expr:TExpr=ParsePowExpr()
  1386. Repeat
  1387. Local op$=_toke
  1388. Select op
  1389. Case "*","/","mod","shl","shr", "sar"
  1390. NextToke
  1391. Local rhs:TExpr=ParsePowExpr()
  1392. expr=New TBinaryMathExpr.Create( op,expr,rhs )
  1393. Default
  1394. Return expr
  1395. End Select
  1396. Forever
  1397. End Method
  1398. Method ParseAddSubExpr:TExpr()
  1399. Local expr:TExpr=ParseMulDivExpr()
  1400. Repeat
  1401. Local op$=_toke
  1402. Select op
  1403. Case "+","-"
  1404. NextToke
  1405. Local rhs:TExpr=ParseMulDivExpr()
  1406. expr=New TBinaryMathExpr.Create( op,expr,rhs )
  1407. Default
  1408. Return expr
  1409. End Select
  1410. Forever
  1411. End Method
  1412. Method ParseBitandExpr:TExpr()
  1413. Local expr:TExpr=ParseAddSubExpr()
  1414. Repeat
  1415. Local op$=_toke
  1416. Select op
  1417. Case "&","~~"
  1418. NextToke
  1419. Local rhs:TExpr=ParseAddSubExpr()
  1420. expr=New TBinaryMathExpr.Create( op,expr,rhs )
  1421. Default
  1422. Return expr
  1423. End Select
  1424. Forever
  1425. End Method
  1426. Method ParseBitorExpr:TExpr()
  1427. Local expr:TExpr=ParseBitandExpr()
  1428. Repeat
  1429. Local op$=_toke
  1430. Select op
  1431. Case "|"
  1432. NextToke
  1433. Local rhs:TExpr=ParseBitandExpr()
  1434. expr=New TBinaryMathExpr.Create( op,expr,rhs )
  1435. Default
  1436. Return expr
  1437. End Select
  1438. Forever
  1439. End Method
  1440. Method ParseCompareExpr:TExpr()
  1441. Local expr:TExpr=ParseBitorExpr()
  1442. Repeat
  1443. Local op$=_toke
  1444. Select op
  1445. Case "=","<",">","<=","=<",">=","=>","<>"
  1446. NextToke
  1447. ' <= or =>
  1448. If (op=">" And (_toke="=")) Or (op="=" And (_toke=">"))
  1449. op:+_toke
  1450. NextToke
  1451. ' <> or <= or =<
  1452. Else If (op="<" And _toke=">") Or (op="<" And _toke="=") Or (op="=" And _toke="<")
  1453. op:+_toke
  1454. NextToke
  1455. EndIf
  1456. Local rhs:TExpr=ParseBitorExpr()
  1457. expr=New TBinaryCompareExpr.Create( op,expr,rhs )
  1458. Default
  1459. Return expr
  1460. End Select
  1461. Forever
  1462. End Method
  1463. Method ParseAndExpr:TExpr()
  1464. Local expr:TExpr=ParseCompareExpr()
  1465. Repeat
  1466. Local op$=_toke
  1467. If op="and"
  1468. NextToke
  1469. Local rhs:TExpr=ParseCompareExpr()
  1470. expr=New TBinaryLogicExpr.Create( op,expr,rhs )
  1471. Else
  1472. Return expr
  1473. EndIf
  1474. Forever
  1475. End Method
  1476. Method ParseOrExpr:TExpr()
  1477. Local expr:TExpr=ParseAndExpr()
  1478. Repeat
  1479. Local op$=_toke
  1480. If op="or"
  1481. NextToke
  1482. Local rhs:TExpr=ParseAndExpr()
  1483. expr=New TBinaryLogicExpr.Create( op,expr,rhs )
  1484. Else
  1485. Return expr
  1486. EndIf
  1487. Forever
  1488. End Method
  1489. Method ParseExpr:TExpr()
  1490. Return ParseOrExpr()
  1491. End Method
  1492. Rem
  1493. unused atm
  1494. Method ReadTillNextToken:string(amount:int=1)
  1495. 'copy current toker and move one token forward
  1496. local tok:TToker = New TToker.Copy(_toker)
  1497. local result:string = _toker._toke
  1498. for local i:int = 0 until amount
  1499. NextTokeToker(tok)
  1500. result :+ " "+ tok._toke
  1501. Next
  1502. return _toker._toke+" "+tok._toke
  1503. End Method
  1504. End Rem
  1505. Method ParseIfStmt( term$, elseIfEndIfReadAheadCheck:Int = False )
  1506. Local tok:TToker
  1507. 'rules:
  1508. '- the command "end" cannot be used as condition
  1509. '- "endif" or "end if" is not allowed in singleline-ifs
  1510. 'if current toke is "if", move on to the next toke
  1511. CParse "if"
  1512. 'read in the expression/condition following after "if"
  1513. Local expr:TExpr=ParseExpr()
  1514. 'if current toke is "then", move to next, else stay at this
  1515. 'position -> makes "then" usage voluntary
  1516. CParse "then"
  1517. 'create empty blocks for then/else
  1518. Local thenBlock:TBlockDecl=New TBlockDecl.Create( _block, ,BLOCK_IF )
  1519. Local elseBlock:TBlockDecl=New TBlockDecl.Create( _block, ,BLOCK_ELSE )
  1520. 'define if the current if is a "singleline if"
  1521. '"singleline ifs" are not allowed to contain "endif" "end if"
  1522. Local singleLineIf:Int = True
  1523. 'to know if it is a multiline or singleline if we have to check
  1524. 'for certain situations
  1525. Select _toke
  1526. Case "~n"
  1527. 'if a <- newline
  1528. ' print "a"
  1529. 'endif
  1530. singleLineIf = False
  1531. Case "if"
  1532. 'another "if" means the outer one is a singleline if!
  1533. singleLineIf = True
  1534. Case "else"
  1535. 'if ReadTillNextToken().toLower() = "else if"
  1536. ' print "IF: found if X then Y else if ..."
  1537. 'else
  1538. ' print "IF: found if X then Y else ..."
  1539. 'endif
  1540. 'also read "else if"
  1541. singleLineIf = True
  1542. Case "elseif"
  1543. singleLineIf = True
  1544. End Select
  1545. 'set thenBlock as the active block
  1546. PushBlock( thenBlock )
  1547. 'now check each toke until we reach our desired term
  1548. 'for singleline-if this is "~n", for multiline-if this is
  1549. '"endif" or "end if"
  1550. If singleLineIf
  1551. term = "~n"
  1552. Else
  1553. term = "end" 'endif, end if
  1554. EndIf
  1555. 'only read until reaching the limit - or no valid toke was returned
  1556. While _toke <> term
  1557. Local currentToke:String = _toke
  1558. Select currentToke
  1559. 'file end before endif/end/elseif
  1560. Case ""
  1561. Err("Expecting expression but encountered end-of-file")
  1562. '"endif" / "end if"
  1563. Case "endif", "end"
  1564. NextToke()
  1565. If singleLineIf Then
  1566. 'check for "end"-command ("if a=1 end")
  1567. If currentToke = "end" And (currentToke + _toke) <> "endif" Then
  1568. ParseEndStmt(False)
  1569. 'found "end if"
  1570. Else
  1571. Err "'End If' without matching 'If'"
  1572. Exit
  1573. EndIf
  1574. EndIf
  1575. 'If currentToke = "endif" or (currentToke + _toke)="endif"
  1576. ' 'do something if "endif/end if" happens ?
  1577. 'Endif
  1578. 'finish this if-statement
  1579. Exit
  1580. '"else" and "elseif" / "else if"
  1581. Case "else","elseif"
  1582. ' print "parsing "+currentToke
  1583. If _block = elseBlock
  1584. Err("If statement can only have one 'else' block.")
  1585. EndIf
  1586. 'switch from thenBlock to elseBlock
  1587. PopBlock()
  1588. PushBlock(elseBlock)
  1589. 'move to next token, might contain "if" for "else if"
  1590. 'doing it this way avoids to parse "elseif if" as
  1591. 'else-statement
  1592. NextToke()
  1593. If currentToke = "elseif" Or (currentToke + _toke)="elseif"
  1594. 'create a new if-statement and exit current handling
  1595. SetErr
  1596. ParseIfStmt(term, True)
  1597. Exit
  1598. EndIf
  1599. Default
  1600. 'parse the current and next tokens
  1601. ParseStmt()
  1602. currentToke = _toke
  1603. 'handle the end-function and "end if"
  1604. Select currentToke
  1605. Case "end"
  1606. 'check next toke too
  1607. NextToke()
  1608. 'found end-function
  1609. If currentToke = "end" And (currentToke + _toke)<>"endif"
  1610. ' print " parsing end .... handling"
  1611. ParseEndStmt(False)
  1612. 'found "end if"
  1613. Else
  1614. If CParse("if") Then
  1615. If singleLineIf Then
  1616. Err "'End If' without matching 'If'"
  1617. End If
  1618. Exit
  1619. End If
  1620. 'NextToke()
  1621. EndIf
  1622. End Select
  1623. End Select
  1624. Wend
  1625. 'change block
  1626. PopBlock()
  1627. 'create a if-then[-else]-statement
  1628. Local stmt:TIfStmt=New TIfStmt.Create( expr,thenBlock,elseBlock )
  1629. _block.AddStmt stmt
  1630. End Method
  1631. Method ParseWhileStmt(loopLabel:TLoopLabelDecl = Null)
  1632. Parse "while"
  1633. Local expr:TExpr=ParseExpr()
  1634. Local block:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_LOOP )
  1635. PushBlock block
  1636. While Not CParse( "wend" ) And Not CParse( "endwhile" )
  1637. ' If CParse( "end" )
  1638. ' CParse "while"
  1639. ' Exit
  1640. ' EndIf
  1641. ParseStmt
  1642. ' to handle "end" statement
  1643. If _toke = "end" Then
  1644. NextToke
  1645. If _toke = "while" Then
  1646. NextToke
  1647. Exit
  1648. Else
  1649. ParseEndStmt(False)
  1650. End If
  1651. End If
  1652. Wend
  1653. PopBlock
  1654. Local stmt:TWhileStmt=New TWhileStmt.Create( expr,block,loopLabel )
  1655. _block.AddStmt stmt
  1656. End Method
  1657. Method ParseRepeatStmt(loopLabel:TLoopLabelDecl = Null)
  1658. Parse "repeat"
  1659. Local block:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_LOOP )
  1660. PushBlock block
  1661. While _toke<>"until" And _toke<>"forever"
  1662. ParseStmt
  1663. Wend
  1664. PopBlock
  1665. SetErr
  1666. Local expr:TExpr
  1667. If CParse( "until" )
  1668. expr=ParseExpr()
  1669. Else
  1670. Parse "forever"
  1671. expr=New TConstExpr.Create( New TBoolType,"" )
  1672. EndIf
  1673. Local stmt:TRepeatStmt=New TRepeatStmt.Create( block,expr,loopLabel )
  1674. _block.AddStmt stmt
  1675. End Method
  1676. Method ParseForStmt(loopLabel:TLoopLabelDecl = Null)
  1677. Parse "for"
  1678. Local varid$,varty:TType,varlocal:Int
  1679. Local varExpr:TExpr
  1680. If CParse( "local" )
  1681. varlocal=True
  1682. varid=ParseIdent()
  1683. varty=ParseDeclType()
  1684. If varty._flags & (TType.T_CHAR_PTR | TType.T_SHORT_PTR) Then
  1685. DoErr "Illegal variable type"
  1686. End If
  1687. Parse( "=" )
  1688. ' use an ident expr to pass the variable to different parts of the statement.
  1689. ' the original implementation passed decl references, which cause problems if we wanted to
  1690. ' copy the statement later.
  1691. varExpr = New TIdentExpr.Create(varid)
  1692. Else
  1693. varlocal=False
  1694. varExpr=ParsePrimaryExpr( False )
  1695. Parse "="
  1696. EndIf
  1697. If CParse( "eachin" )
  1698. Local expr:TExpr=ParseExpr()
  1699. Local block:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_LOOP )
  1700. PushBlock block
  1701. While Not CParse( "next" )
  1702. ParseStmt
  1703. Wend
  1704. PopBlock
  1705. Local stmt:TForEachinStmt=New TForEachinStmt.Create( varid,varty,varlocal,expr,block,loopLabel, varExpr )
  1706. _block.AddStmt stmt
  1707. Return
  1708. EndIf
  1709. Local from:TExpr=ParseExpr()
  1710. Local op$
  1711. If CParse( "to" )
  1712. op="<="
  1713. Else If CParse( "until" )
  1714. op="<"
  1715. Else
  1716. Err "Expecting 'To' or 'Until'."
  1717. EndIf
  1718. Local term:TExpr=ParseExpr()
  1719. Local stp:TExpr
  1720. If CParse( "step" )
  1721. stp=ParseExpr()
  1722. Else
  1723. stp=New TConstExpr.Create( New TIntType,"1" )
  1724. EndIf
  1725. Local init:TStmt,expr:TExpr,incr:TStmt
  1726. If varlocal
  1727. Local indexVar:TLocalDecl=New TLocalDecl.Create( varid,varty,New TCastExpr.Create( varty,from,CAST_EXPLICIT ),0 )
  1728. init=New TDeclStmt.Create( indexVar )
  1729. ' expr=New TBinaryCompareExpr.Create( op,New TVarExpr.Create( indexVar ),New TCastExpr.Create( varty,term,1 ) )
  1730. ' incr=New TAssignStmt.Create( "=",New TVarExpr.Create( indexVar ),New TBinaryMathExpr.Create( "+",New TVarExpr.Create( indexVar ),New TCastExpr.Create( varty,stp,1 ) ) )
  1731. expr=New TBinaryCompareExpr.Create( op, varExpr,New TCastExpr.Create( varty,term,CAST_EXPLICIT ) )
  1732. incr=New TAssignStmt.Create( "=",varExpr,New TBinaryMathExpr.Create( "+",varExpr,New TCastExpr.Create( varty,stp,CAST_EXPLICIT ) ) )
  1733. Else
  1734. ' varty is NULL here for the casts. We will back-populate it later.
  1735. ' init=New TAssignStmt.Create( "=",New TIdentExpr.Create( varid ),from )
  1736. ' expr=New TBinaryCompareExpr.Create( op,New TIdentExpr.Create( varid ),New TCastExpr.Create( varty,term,1 ) )
  1737. ' incr=New TAssignStmt.Create( "=",New TIdentExpr.Create( varid ),New TBinaryMathExpr.Create( "+",New TIdentExpr.Create( varid ),New TCastExpr.Create( varty,stp,1 ) ) )
  1738. init=New TAssignStmt.Create( "=",varExpr,from )
  1739. expr=New TBinaryCompareExpr.Create( op,varExpr,New TCastExpr.Create( varty,term,CAST_EXPLICIT ) )
  1740. incr=New TAssignStmt.Create( "=",varExpr,New TBinaryMathExpr.Create( "+",varExpr,New TCastExpr.Create( varty,stp,CAST_EXPLICIT ) ) )
  1741. EndIf
  1742. Local block:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_LOOP )
  1743. PushBlock block
  1744. While Not CParse( "next" )
  1745. ParseStmt
  1746. Wend
  1747. PopBlock
  1748. NextToke
  1749. Local stmt:TForStmt=New TForStmt.Create( init,expr,incr,block,loopLabel )
  1750. _block.AddStmt stmt
  1751. End Method
  1752. Method ParseDefDataStmt(label:TLoopLabelDecl = Null)
  1753. Parse "defdata"
  1754. If AtEos() Then
  1755. Err "Expecting expression but encountered " + DescribeToke(_toke)
  1756. End If
  1757. Local args:TExpr[]
  1758. Local nargs:Int
  1759. Repeat
  1760. Local arg:TExpr
  1761. If _toke And _toke<>"," arg=ParseExpr()
  1762. If args.Length=nargs args=args + New TExpr[10]
  1763. args[nargs]=arg
  1764. nargs:+1
  1765. Until Not CParse(",")
  1766. args=args[..nargs]
  1767. Local dataLabel:TDataLabelDecl
  1768. If label Then
  1769. dataLabel = New TDataLabelDecl.Create(label.ident, label.attrs)
  1770. End If
  1771. Local decl:TDefDataDecl = New TDefDataDecl.Create(args, dataLabel)
  1772. _app.dataDefs.AddLast(decl)
  1773. End Method
  1774. Method ParseReadDataStmt()
  1775. Parse "readdata"
  1776. Local args:TExpr[]
  1777. Local nargs:Int
  1778. If Not AtEos() Then
  1779. Repeat
  1780. Local arg:TExpr
  1781. If _toke And _toke<>"," arg=ParseExpr()
  1782. If args.Length=nargs args=args + New TExpr[10]
  1783. args[nargs]=arg
  1784. nargs:+1
  1785. Until Not CParse(",")
  1786. args=args[..nargs]
  1787. End If
  1788. _block.AddStmt New TReadDataStmt.Create( args )
  1789. End Method
  1790. Method ParseRestoreDataStmt()
  1791. Parse "restoredata"
  1792. Local expr:TExpr = ParseExpr()
  1793. _block.AddStmt New TRestoreDataStmt.Create( expr )
  1794. End Method
  1795. Method ParseReturnStmt()
  1796. Parse "return"
  1797. Local expr:TExpr
  1798. If Not AtEos() expr=ParseExpr()
  1799. _block.AddStmt New TReturnStmt.Create( expr )
  1800. End Method
  1801. Method ParseExitStmt()
  1802. Parse "exit"
  1803. Local expr:TExpr
  1804. If Not AtEos() expr=ParseExpr()
  1805. _block.AddStmt New TBreakStmt.Create(expr)
  1806. End Method
  1807. Method ParseContinueStmt()
  1808. Parse "continue"
  1809. Local expr:TExpr
  1810. If Not AtEos() expr=ParseExpr()
  1811. _block.AddStmt New TContinueStmt.Create(expr)
  1812. End Method
  1813. Method ParseTryStmt()
  1814. Parse "try"
  1815. Local tryStmtDecl:TTryStmtDecl = TTryStmtDecl(New TTryStmtDecl.Create( _block ))
  1816. PushBlock tryStmtDecl
  1817. Local block:TBlockDecl=New TBlockDecl.Create( tryStmtDecl, , BLOCK_TRY )
  1818. Local catches:TList=New TList
  1819. Local finallyStmt:TFinallyStmt = Null
  1820. PushBlock block
  1821. While _toke<>"end" And _toke<>"endtry"
  1822. If CParse( "catch" )
  1823. If finallyStmt Then Err "'Catch' can not appear after 'Finally'."
  1824. Local id:String=ParseIdent()
  1825. Local ty:TType
  1826. If Not CParse(":") Then
  1827. Parse "$"
  1828. ty= TType.stringType
  1829. Else
  1830. ty=ParseType()
  1831. While IsArrayDef()
  1832. ty=ParseArrayType(ty)
  1833. Wend
  1834. End If
  1835. Local init:TLocalDecl=New TLocalDecl.Create( id,ty,Null,0 )
  1836. Local block:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_CATCH )
  1837. catches.AddLast(New TCatchStmt.Create( init,block ))
  1838. PopBlock
  1839. PushBlock block
  1840. Else If CParse("finally") Then
  1841. If finallyStmt Then Err "Try statement cannot have more than one Finally block."
  1842. Local block:TBlockDecl = New TBlockDecl.Create(_block, , BLOCK_FINALLY)
  1843. finallyStmt = New TFinallyStmt.Create(block)
  1844. PopBlock
  1845. PushBlock block
  1846. Else
  1847. ParseStmt
  1848. If _toke = "end" Then
  1849. NextToke
  1850. If _toke = "try" Then
  1851. ' we are done with the try statement
  1852. Exit
  1853. Else
  1854. ParseEndStmt(False)
  1855. End If
  1856. End If
  1857. End If
  1858. Wend
  1859. If catches.Count() = 0 And Not finallyStmt Then Err "Expecting 'Catch' or 'Finally'."
  1860. PopBlock ' try block
  1861. If Not CParse("endtry") Then
  1862. NextToke
  1863. CParse "try"
  1864. End If
  1865. PopBlock ' tryStmtDecl
  1866. Local tryStmt:TTryStmt = New TTryStmt.Create(block,TCatchStmt[](catches.ToArray()), finallyStmt)
  1867. tryStmtDecl.tryStmt = tryStmt
  1868. _block.AddStmt tryStmt
  1869. End Method
  1870. Method ParseThrowStmt()
  1871. Parse "throw"
  1872. Local expr:TExpr = ParseExpr()
  1873. _block.AddStmt New TThrowStmt.Create( expr )
  1874. End Method
  1875. Method ParseReleaseStmt()
  1876. Parse "release"
  1877. Local expr:TExpr = ParseExpr()
  1878. _block.AddStmt New TReleaseStmt.Create( expr )
  1879. End Method
  1880. Method ParseAssertStmt()
  1881. Parse "assert"
  1882. Local expr:TExpr = ParseExpr()
  1883. Local elseExpr:TExpr
  1884. If _toke = "," Or _toke = "else" Then
  1885. NextToke
  1886. elseExpr = ParseExpr()
  1887. End If
  1888. _block.AddStmt New TAssertStmt.Create( expr, elseExpr )
  1889. End Method
  1890. Method ParseEndStmt(eatEnd:Int = True)
  1891. If eatEnd Then
  1892. Parse "end"
  1893. End If
  1894. _block.AddStmt New TEndStmt.Create( )
  1895. End Method
  1896. Method ParseSelectStmt()
  1897. Parse "select"
  1898. Local block:TBlockDecl=_block
  1899. Local tmpVar:TLocalDecl
  1900. Local selectExpr:TExpr = ParseExpr()
  1901. If Not TNullType(selectExpr.exprType)
  1902. tmpVar = New TLocalDecl.Create("", Null, selectExpr, , True)
  1903. block.AddStmt New TDeclStmt.Create(tmpVar)
  1904. End If
  1905. While _toke<>"end" And _toke<>"default" And _toke<>"endselect"
  1906. SetErr
  1907. Select _toke
  1908. Case "~n"
  1909. NextToke
  1910. Case "case"
  1911. NextToke
  1912. Local comp:TExpr
  1913. Repeat
  1914. Local expr:TExpr
  1915. If TNullType(selectExpr.exprType)
  1916. expr = New TNullExpr.Create(TType.nullObjectType)
  1917. Else
  1918. expr = New TVarExpr.Create(tmpVar)
  1919. End If
  1920. expr=New TBinaryCompareExpr.Create( "=",expr,ParseExpr() )
  1921. If comp
  1922. comp=New TBinaryLogicExpr.Create( "or",comp,expr )
  1923. Else
  1924. comp=expr
  1925. EndIf
  1926. Until Not CParse(",")
  1927. Local thenBlock:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_IF )
  1928. Local elseBlock:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_ELSE )
  1929. Local ifstmt:TIfStmt=New TIfStmt.Create( comp,thenBlock,elseBlock )
  1930. block.AddStmt ifstmt
  1931. block=ifstmt.thenBlock
  1932. PushBlock block
  1933. Local fin:Int = False
  1934. While _toke<>"case" And _toke<>"default" And _toke<>"end" And _toke<>"endselect"
  1935. ParseStmt
  1936. If _toke = "end" Then
  1937. NextToke
  1938. If _toke = "select" Then
  1939. ' we are done with the select statement, full exit
  1940. fin = True
  1941. Exit
  1942. Else
  1943. ParseEndStmt(False)
  1944. End If
  1945. End If
  1946. Wend
  1947. PopBlock
  1948. block=elseBlock
  1949. If fin Exit
  1950. Default
  1951. Err "Syntax error - expecting 'Case', 'Default' or 'End'."
  1952. End Select
  1953. Wend
  1954. If _toke="default"
  1955. NextToke
  1956. PushBlock block
  1957. While _toke<>"end" And _toke<>"endselect"
  1958. SetErr
  1959. Select _toke
  1960. Case "case"
  1961. Err "Case can not appear after Default."
  1962. Case "default"
  1963. Err "Select statement can have only one Default block."
  1964. End Select
  1965. ParseStmt
  1966. If _toke = "end" Then
  1967. NextToke
  1968. If _toke = "select" Then
  1969. Exit
  1970. Else
  1971. ParseEndStmt(False)
  1972. End If
  1973. End If
  1974. Wend
  1975. PopBlock
  1976. EndIf
  1977. SetErr
  1978. If Not CParse("endselect") Then
  1979. If Not CParse("select")
  1980. Parse "end"
  1981. Parse "select"
  1982. End If
  1983. End If
  1984. End Method
  1985. Method ParseExternBlock(mdecl:TModuleDecl, attrs:Int)
  1986. NextToke
  1987. attrs :| ParseCallConvention()
  1988. attrs = attrs | DECL_EXTERN
  1989. If CParse( "private" ) attrs=attrs|DECL_PRIVATE
  1990. While _toke<>"endextern"
  1991. If CParse( "end" )
  1992. Parse "extern"
  1993. Exit
  1994. EndIf
  1995. SetErr
  1996. Select _toke
  1997. Case "~n"
  1998. NextToke
  1999. Case "const"
  2000. mdecl.InsertDecls ParseDecls( _toke,attrs )
  2001. Case "global"
  2002. ParseDeclStmts(True, attrs, mdecl)
  2003. Case "struct"
  2004. mdecl.InsertDecl ParseClassDecl( _toke,attrs | CLASS_STRUCT )
  2005. Case "type"
  2006. mdecl.InsertDecl ParseClassDecl( _toke,attrs )
  2007. Case "function"
  2008. mdecl.InsertDecl ParseFuncDecl( _toke,attrs )
  2009. Case "interface"
  2010. mdecl.InsertDecl ParseClassDecl( _toke,attrs | CLASS_INTERFACE )
  2011. Default
  2012. If _toke <> "end" And _toke <> "endextern" Then
  2013. Err "Expecting expression but encountered '"+_toke+"'"
  2014. End If
  2015. End Select
  2016. Wend
  2017. If _toke="endextern" Then
  2018. NextToke
  2019. End If
  2020. End Method
  2021. Method ParseStmt()
  2022. SetErr
  2023. Select _toke
  2024. Case ";","~n"
  2025. NextToke
  2026. Case "const","local","global"
  2027. ParseDeclStmts
  2028. ' nested function - needs to get added to the "module"
  2029. Case "function"
  2030. _block.InsertDecl ParseFuncDecl( _toke,FUNC_NESTED)
  2031. Case "type"
  2032. _block.InsertDecl ParseClassDecl( _toke,DECL_NESTED)
  2033. Case "return"
  2034. ParseReturnStmt()
  2035. Case "exit"
  2036. ParseExitStmt()
  2037. Case "continue"
  2038. ParseContinueStmt()
  2039. Case "if"
  2040. ParseIfStmt( "" )
  2041. Case "while"
  2042. ParseWhileStmt()
  2043. Case "repeat"
  2044. ParseRepeatStmt()
  2045. Case "for"
  2046. ParseForStmt()
  2047. Case "select"
  2048. ParseSelectStmt()
  2049. Case "assert"
  2050. ParseAssertStmt()
  2051. Case "try"
  2052. ParseTryStmt()
  2053. Case "throw"
  2054. ParseThrowStmt()
  2055. Case "end"
  2056. ParseEndStmt()
  2057. Case "extern"
  2058. ParseExternBlock(_module, 0)
  2059. Case "#"
  2060. Local decl:TLoopLabelDecl = ParseLoopLabelDecl()
  2061. NextToke
  2062. While _toke
  2063. SetErr
  2064. Select _toke.ToLower()
  2065. Case "~n"
  2066. NextToke
  2067. Case "while"
  2068. ParseWhileStmt(decl)
  2069. Exit
  2070. Case "repeat"
  2071. ParseRepeatStmt(decl)
  2072. Exit
  2073. Case "for"
  2074. ParseForStmt(decl)
  2075. Exit
  2076. Case "defdata"
  2077. ParseDefDataStmt(decl)
  2078. Exit
  2079. Default
  2080. Err "Labels must appear before a loop or DefData statement"
  2081. End Select
  2082. Wend
  2083. Case "release"
  2084. ParseReleaseStmt()
  2085. Case "defdata"
  2086. ParseDefDataStmt()
  2087. Case "readdata"
  2088. ParseReadDataStmt()
  2089. Case "restoredata"
  2090. ParseRestoreDataStmt()
  2091. Default
  2092. If _toke.StartsWith("'!") Then
  2093. If _tokeType = TOKE_NATIVE Then
  2094. ParseNativeStmt()
  2095. End If
  2096. Else
  2097. Local expr:TExpr=ParsePrimaryExpr( True )
  2098. Select _toke.ToLower()
  2099. '"=","*=","/=","+=","-=","&=","|=","~~=","Mod","Shl","Shr"
  2100. Case "=",":*",":/",":+",":-",":&",":|",":~~","mod","shl","shr", ":shl", ":shr", "sar", ":sar", ":mod"
  2101. ' remap symbols...
  2102. 'For Local i:Int = 0 Until TToker._symbols.length
  2103. ' Local sym$= TToker._symbols[i]
  2104. ' If _toke.ToLower() = sym
  2105. ' _toke = TToker._symbols_map[i]
  2106. ' Exit
  2107. ' EndIf
  2108. 'Next
  2109. If TIdentExpr( expr ) Or TIndexExpr( expr )
  2110. Local op$=_toke.ToLower()
  2111. NextToke
  2112. ' If Not op.EndsWith( "=" ) And Not op.StartsWith("=")
  2113. ' Parse "="
  2114. ' op:+"="
  2115. ' EndIf
  2116. _block.AddStmt New TAssignStmt.Create( op,expr,ParseExpr() )
  2117. Else
  2118. Err "Assignment operator '"+_toke+"' cannot be used this way."
  2119. EndIf
  2120. Return
  2121. End Select
  2122. If TIdentExpr( expr )
  2123. expr=New TFuncCallExpr.Create( expr,ParseArgs( True ) )
  2124. Else If TFuncCallExpr( expr) Or TInvokeSuperExpr( expr ) Or TNewObjectExpr( expr ) Or TNewExpr(expr)
  2125. Else If TIndexExpr(expr)
  2126. expr = New TFuncCallExpr.Create( expr, ParseArgs( True ) )
  2127. Else
  2128. Err "Expression cannot be used as a statement."
  2129. EndIf
  2130. _block.AddStmt New TExprStmt.Create( expr )
  2131. End If
  2132. End Select
  2133. End Method
  2134. Method ParseDecl:TDecl( toke$,attrs:Int )
  2135. SetErr
  2136. If CParse("staticarray") Then
  2137. If attrs & DECL_STATIC Then
  2138. Err "Already declared as a static array"
  2139. End If
  2140. attrs :| DECL_STATIC
  2141. End If
  2142. Local id$=ParseIdent()
  2143. Local ty:TType
  2144. Local init:TExpr
  2145. If attrs & DECL_EXTERN
  2146. ty=ParseDeclType(attrs & DECL_API_STDCALL)
  2147. If toke = "const" Then
  2148. If CParse("=") Then
  2149. init=ParseExpr()
  2150. End If
  2151. End If
  2152. ' Else If CParse( ":=" )
  2153. ' init=ParseExpr()
  2154. ' ty = init.exprType
  2155. Else
  2156. ty=ParseDeclType(attrs & DECL_API_STDCALL)
  2157. If CParse( "=" )
  2158. If (attrs & DECL_STATIC) Then
  2159. Err "Static arrays cannot be initialized in this way"
  2160. End If
  2161. init=ParseExpr()
  2162. Else If CParse( "[" ) ' an initialised array?
  2163. If (attrs & DECL_STATIC) Then
  2164. init = ParseExpr()
  2165. Parse "]"
  2166. ty=New TArrayType.Create( ty,1,, attrs & DECL_STATIC > 0 )
  2167. Else
  2168. Local ln:TExpr[]
  2169. Repeat
  2170. If CParse(",") Then
  2171. ln = ln + [New TNullExpr]
  2172. Continue
  2173. End If
  2174. If CParse("]") Exit
  2175. ln = ln + [ParseExpr()]
  2176. If CParse("]") Exit
  2177. Parse(",")
  2178. Forever
  2179. 'Parse "]"
  2180. ty = ParseArrayType(ty)
  2181. 'While CParse( "[]" )
  2182. ' ty=New TArrayType.Create(ty)
  2183. 'Wend
  2184. init=New TNewArrayExpr.Create( ty,ln)
  2185. ty=New TArrayType.Create( ty, ln.length,, attrs & DECL_STATIC > 0 )
  2186. End If
  2187. Else If toke <> "const"
  2188. If toke="global" Or toke="local" Then
  2189. init=New TConstExpr.Create( ty,"" )
  2190. End If
  2191. Else
  2192. Err "Constants must be initialized."
  2193. EndIf
  2194. EndIf
  2195. Local decl:TValDecl
  2196. Select toke
  2197. Case "global"
  2198. decl=New TGlobalDecl.Create( id,ty,init,attrs )
  2199. Case "field"
  2200. decl=New TFieldDecl.Create( id,ty,init,attrs )
  2201. If TFunctionPtrType(ty) Then
  2202. TFunctionPtrType(ty).func.attrs :| FUNC_FIELD
  2203. End If
  2204. Case "const" decl=New TConstDecl.Create( id,ty,init,attrs )
  2205. Case "local" decl=New TLocalDecl.Create( id,ty,init,attrs )
  2206. End Select
  2207. If decl.IsExtern()
  2208. Local cdets:TCastDets
  2209. If CParse( "=" )
  2210. Local munged:String = ParseStringLit()
  2211. If munged.Find("(") > 0 Then
  2212. cdets = ParseExternCast(munged, True)
  2213. If cdets Then
  2214. decl.munged = cdets.name
  2215. End If
  2216. Else
  2217. decl.munged = munged
  2218. End If
  2219. Else
  2220. decl.munged=decl.ident
  2221. EndIf
  2222. If TFunctionPtrType(ty) Then
  2223. TFunctionPtrType(ty).func.munged = decl.munged
  2224. If Not cdets Then
  2225. cdets = TCastDets(_externCasts.ValueForKey(TFunctionPtrType(ty).func.munged))
  2226. End If
  2227. If cdets Then
  2228. TFunctionPtrType(ty).func.castTo = cdets.retType
  2229. If cdets.noGen Then
  2230. TFunctionPtrType(ty).func.noCastGen = True
  2231. End If
  2232. For Local i:Int = 0 Until cdets.args.length
  2233. If i < TFunctionPtrType(ty).func.argDecls.length Then
  2234. TFunctionPtrType(ty).func.argDecls[i].castTo = cdets.args[i]
  2235. End If
  2236. Next
  2237. End If
  2238. End If
  2239. EndIf
  2240. ' apply any function ptr metadata to decl
  2241. If TFunctionPtrType(ty) Then
  2242. If TFunctionPtrType(ty).func And TFunctionPtrType(ty).func.metadata Then
  2243. decl.metadata = TFunctionPtrType(ty).func.metadata
  2244. End If
  2245. End If
  2246. 'meta data for variables
  2247. Local meta:TMetaData = ParseMetaData()
  2248. If meta Then
  2249. decl.metadata = meta
  2250. End If
  2251. Return decl
  2252. End Method
  2253. Method ParseDecls:TList( toke$,attrs:Int, isField:Int = False )
  2254. If toke Parse toke
  2255. If isField Then
  2256. Repeat
  2257. If CParse("readonly") Then
  2258. If attrs & DECL_READ_ONLY
  2259. Err "Duplicate modifier 'ReadOnly'."
  2260. End If
  2261. attrs :| DECL_READ_ONLY
  2262. Else If CParse("staticarray") Then
  2263. If attrs & DECL_STATIC
  2264. Err "Duplicate modifier 'Static'."
  2265. End If
  2266. attrs :| DECL_STATIC
  2267. Else
  2268. Exit
  2269. End If
  2270. Forever
  2271. End If
  2272. Local decls:TList=New TList'<Decl>
  2273. Repeat
  2274. Local decl:TDecl=ParseDecl( toke,attrs )
  2275. decls.AddLast decl
  2276. If Not CParse(",") Return decls
  2277. Forever
  2278. End Method
  2279. Method ParseDeclStmts(initOnly:Int = False, attrs:Int = 0, mdecl:TModuleDecl = Null)
  2280. Local toke$=_toke
  2281. NextToke
  2282. Repeat
  2283. Local decl:TDecl=ParseDecl( toke,attrs )
  2284. If Not (attrs & DECL_EXTERN) Then
  2285. _block.AddStmt New TDeclStmt.Create( decl )
  2286. End If
  2287. ' reset the decl scope, adding decl to the block decl list.
  2288. ' this improves scope visibilty - for decls such as embedded functions
  2289. If TConstDecl(decl) Or TGlobalDecl(decl) Then
  2290. If mdecl Then
  2291. mdecl.InsertDecl decl
  2292. End If
  2293. If Not (attrs & DECL_EXTERN) Then
  2294. decl.scope = Null
  2295. _block.InsertDecl(decl)
  2296. End If
  2297. If TGlobalDecl(decl) Then
  2298. If initOnly Then
  2299. decl.attrs :| DECL_INITONLY
  2300. TGlobalDecl(decl).mscope = _module
  2301. Else
  2302. TGlobalDecl(decl).funcGlobal = True
  2303. End If
  2304. End If
  2305. End If
  2306. Until Not CParse(",")
  2307. End Method
  2308. Method ParseLoopLabelDecl:TLoopLabelDecl()
  2309. NextToke
  2310. Local id:String = ParseIdent()
  2311. Return New TLoopLabelDecl.Create(id, 0)
  2312. End Method
  2313. 'handle end-of-line "dot dot return"-line connector
  2314. '-> skips EOL tokens
  2315. Method HandleDotsLineConnector(eatToke:Int = False)
  2316. Local tok:TToker = New TToker.Copy(_toker)
  2317. Local t:String = tok.NextToke()
  2318. Local count:Int = tok.SkipSpace()
  2319. For Local i:Int = 0 Until count
  2320. NextToke
  2321. Next
  2322. t = tok._toke
  2323. If t = "~r" Then
  2324. t = tok.NextToke()
  2325. If t = "~n" Then
  2326. NextToke
  2327. NextToke
  2328. Else
  2329. NextToke
  2330. End If
  2331. Else
  2332. If t = "~n" Then
  2333. NextToke
  2334. End If
  2335. End If
  2336. If eatToke And Not count Then
  2337. NextToke
  2338. End If
  2339. End Method
  2340. 'should return a specific "metadata object" ?
  2341. ' metadata is in the form : {key key=value key="value"}
  2342. Method ParseMetaData:TMetadata()
  2343. If Not CParse( "{" ) Then
  2344. Return Null
  2345. End If
  2346. Local meta:TMetadata = New TMetadata
  2347. SkipEols
  2348. Repeat
  2349. 'reached end of meta data declaration
  2350. If _toke="}" Then Exit
  2351. If meta.metadataString Then
  2352. meta.metadataString :+ " "
  2353. End If
  2354. Select _tokeType
  2355. Case TOKE_INTLIT
  2356. Err "Expecting '}' but encountered integer literal"
  2357. Case TOKE_FLOATLIT
  2358. Err "Expecting '}' but encountered floating point literal"
  2359. Case TOKE_STRINGLIT
  2360. Err "Expecting '}' but encountered string literal"
  2361. Case TOKE_SYMBOL
  2362. Err "Expecting '}' but encountered " + _toke
  2363. End Select
  2364. 'append current token to metaDataString
  2365. Local key:String = _toke
  2366. meta.metadataString :+ key
  2367. 'read next token
  2368. NextToke()
  2369. Local value:String
  2370. ' got a value
  2371. If CParse("=") Then
  2372. If _tokeType = TOKE_IDENT Then
  2373. Err "Meta data must be literal constant"
  2374. End If
  2375. value = _toke
  2376. meta.metadataString :+ "=" + value
  2377. 'read next token
  2378. NextToke()
  2379. Else
  2380. value = "1"
  2381. meta.metadataString :+ "=1"
  2382. End If
  2383. meta.InsertMeta(key.ToLower(), value)
  2384. Forever
  2385. 'continue to next token
  2386. NextToke()
  2387. 'parse this into something
  2388. Return meta
  2389. End Method
  2390. Method ParseFuncDecl:TFuncDecl( toke$, attrs:Int, parent:TScopeDecl = Null )
  2391. SetErr
  2392. If toke Parse toke
  2393. Local id$
  2394. Local ty:TType
  2395. Local meth:Int = attrs & FUNC_METHOD
  2396. Local meta:TMetadata
  2397. Local noMangle:Int
  2398. Local exported:Int
  2399. Local inInterface:Int = attrs & DECL_ABSTRACT
  2400. Local classDecl:TClassDecl = TClassDecl(parent)
  2401. If attrs & FUNC_METHOD
  2402. If _toke="new"
  2403. If attrs & DECL_EXTERN
  2404. Err "Extern classes cannot have constructors"
  2405. EndIf
  2406. id="New"
  2407. NextToke
  2408. attrs:|FUNC_CTOR
  2409. attrs:&~FUNC_METHOD
  2410. ty=ParseDeclType()
  2411. Else If _toke="operator" Then
  2412. attrs:|FUNC_OPERATOR
  2413. NextToke
  2414. Local t:String = _toke.ToLower()
  2415. NextToke
  2416. Select t
  2417. Case "*","/","+","-","&","|","~~","^"
  2418. id = t
  2419. Case ":*",":/",":+",":-",":&",":|",":~~",":^"
  2420. id = t
  2421. Case "<",">"',"="',"<=",">=","=","<>"
  2422. If CParse("=") Then
  2423. t :+ "="
  2424. Else If t = "<" And CParse(">") Then
  2425. t :+ ">"
  2426. End If
  2427. id = t
  2428. Case "="
  2429. id = t
  2430. Case "mod", "shl", "shr"
  2431. id = t
  2432. Case ":mod", ":shl", ":shr"
  2433. id = t
  2434. Case "[]"
  2435. If CParse("=") Then t :+ "="
  2436. id = t
  2437. Default
  2438. DoErr "Operator must be one of: * / + - & | ~~ :* :/ :+ :- :& :| :~~ < > <= >= = <> mod shl shr :mod :shl :shr [] []="
  2439. End Select
  2440. ty=ParseDeclType()
  2441. Else
  2442. id=ParseIdent()
  2443. ty=ParseDeclType(attrs & DECL_API_STDCALL)
  2444. If ty._flags & (TType.T_CHAR_PTR | TType.T_SHORT_PTR) Then
  2445. DoErr "Illegal function return type"
  2446. End If
  2447. ' Delete() return type should always be Void
  2448. If id.ToLower() = "delete" Then
  2449. attrs:|FUNC_DTOR
  2450. If TIntType(ty) Then
  2451. ty = New TVoidType
  2452. End If
  2453. End If
  2454. ' TODO: make sure Delete cannot be declared with parameters?
  2455. EndIf
  2456. Else
  2457. 'If Not (attrs & FUNC_PTR) Then
  2458. id=ParseIdent()
  2459. ty=ParseDeclType(attrs & DECL_API_STDCALL)
  2460. ' can only return "$z" and "$w" from an extern function.
  2461. If ty._flags & (TType.T_CHAR_PTR | TType.T_SHORT_PTR) And Not (attrs & DECL_EXTERN) Then
  2462. DoErr "Illegal function return type"
  2463. End If
  2464. 'End If
  2465. EndIf
  2466. ' every branch in that nested If block up there contains the line "ty=ParseDeclType()";
  2467. ' this already consumed all sets of parentheses and brackets belonging to this function declaration
  2468. ' so we will now extract our actual return type and args from the result
  2469. Local args:TArgDecl[]
  2470. If Not TFunctionPtrType(ty) Then
  2471. DoErr "Expecting function type"
  2472. Else
  2473. Local fdecl:TFuncDecl = TFunctionPtrType(ty).func
  2474. ty = fdecl.retTypeExpr
  2475. args = fdecl.argDecls
  2476. attrs :| (fdecl.attrs & DECL_API_FLAGS)
  2477. End If
  2478. Local declaredAttrs:Int
  2479. While True
  2480. If CParse( "nodebug" ) Then
  2481. If declaredAttrs & DECL_NODEBUG Then Err "Duplicate modifier 'NoDebug'"
  2482. declaredAttrs :| DECL_NODEBUG
  2483. Continue
  2484. End If
  2485. If CParse( "final" )
  2486. If Not classDecl Then
  2487. Err "Final cannot be used with global functions"
  2488. End If
  2489. If inInterface Then
  2490. If attrs & FUNC_METHOD Then
  2491. Err "Final methods cannot appear in interfaces"
  2492. Else
  2493. Err "Final functions cannot appear in interfaces"
  2494. End If
  2495. End If
  2496. If declaredAttrs & DECL_FINAL Then Err "Duplicate modifier 'Final'"
  2497. declaredAttrs :| DECL_FINAL
  2498. Continue
  2499. End If
  2500. If CParse( "abstract" )
  2501. If Not classDecl Then
  2502. Err "Abstract cannot be used with global functions"
  2503. End If
  2504. If classDecl And classDecl.attrs & DECL_FINAL Then
  2505. Err "Abstract methods cannot appear in final types"
  2506. End If
  2507. If inInterface Then
  2508. If attrs & FUNC_METHOD Then
  2509. Err "Abstract cannot be used in interfaces (interface methods are automatically abstract)"
  2510. Else
  2511. Err "Abstract cannot be used in interfaces (interface functions are automatically abstract)"
  2512. End If
  2513. End If
  2514. If declaredAttrs & DECL_ABSTRACT Then Err "Duplicate modifier 'Abstract'"
  2515. declaredAttrs :| DECL_ABSTRACT
  2516. Continue
  2517. End If
  2518. If CParse("override") Then
  2519. If Not classDecl Then
  2520. Err "Override cannot be used with global functions"
  2521. End If
  2522. If declaredAttrs & DECL_OVERRIDE Then Err "Duplicate modifier 'Override'"
  2523. declaredAttrs :| DECL_OVERRIDE
  2524. Continue
  2525. End If
  2526. If CParse("inline") And Not opt_debug Then
  2527. If classDecl Then
  2528. Err "Inline can only be used with global functions"
  2529. End If
  2530. If declaredAttrs & DECL_INLINE Then Err "Duplicate modifier 'Inline'"
  2531. declaredAttrs :| DECL_INLINE
  2532. Continue
  2533. End If
  2534. Exit
  2535. Wend
  2536. attrs :| declaredAttrs
  2537. 'meta data for functions/methods
  2538. meta = ParseMetaData()
  2539. If meta And meta.HasMeta("nomangle") Then
  2540. If attrs & FUNC_METHOD Then
  2541. Err "Only functions can specify NoMangle"
  2542. Else
  2543. noMangle = True
  2544. End If
  2545. End If
  2546. If CParse("export") Then
  2547. attrs :| DECL_EXPORT
  2548. If attrs & FUNC_METHOD Then
  2549. Err "Only functions can specify Export"
  2550. Else
  2551. exported = True
  2552. End If
  2553. End If
  2554. attrs :| ParseCallConvention(attrs & DECL_API_STDCALL)
  2555. If CParse( "nodebug" ) Then
  2556. attrs :| DECL_NODEBUG
  2557. End If
  2558. Local funcDecl:TFuncDecl
  2559. If attrs & FUNC_CTOR Then
  2560. funcDecl=New TNewDecl.CreateF( id,ty,args,attrs )
  2561. TNewDecl(funcDecl).cdecl = classdecl
  2562. Else
  2563. 'If fdecl Then
  2564. ' funcDecl = fdecl
  2565. ' funcDecl.ident = id
  2566. 'Else
  2567. funcDecl=New TFuncDecl.CreateF( id,ty,args,attrs )
  2568. 'End If
  2569. funcDecl.noMangle = noMangle
  2570. funcDecl.exported = exported
  2571. End If
  2572. If meta Then
  2573. funcDecl.metadata = meta
  2574. End If
  2575. If funcDecl.IsExtern() Or (attrs & FUNC_PTR)
  2576. funcDecl.munged=funcDecl.ident
  2577. ' a normal function pointer definition *probably* can't be defined with a munged name?
  2578. ' If there is an equals here, one can assume it is for an initialisation...
  2579. 'If (Not (attrs & FUNC_PTR)) Or (attrs & FUNC_PTR And Not (attrs & DECL_ARG)) Then
  2580. Local cdets:TCastDets
  2581. If Not (attrs & FUNC_PTR) Then
  2582. If CParse( "=" )
  2583. Local munged:String = ParseStringLit()
  2584. If munged.Find("(") > 0 Then
  2585. cdets = ParseExternCast(munged, True)
  2586. If cdets Then
  2587. funcDecl.munged = cdets.name
  2588. End If
  2589. Else
  2590. funcDecl.munged = munged
  2591. End If
  2592. End If
  2593. 'Array $resize hack!
  2594. 'If funcDecl.munged="$resize"
  2595. ' funcDecl.retTypeExpr=TType.emptyArrayType
  2596. 'EndIf
  2597. EndIf
  2598. If funcDecl.munged Then
  2599. ' look up extern cast list
  2600. If Not cdets Then
  2601. cdets = TCastDets(_externCasts.ValueForKey(funcDecl.munged))
  2602. End If
  2603. If cdets Then
  2604. funcDecl.castTo = cdets.retType
  2605. If cdets.noGen Then
  2606. funcDecl.noCastGen = True
  2607. End If
  2608. For Local i:Int = 0 Until cdets.args.length
  2609. If i < funcDecl.argDecls.length Then
  2610. funcDecl.argDecls[i].castTo = cdets.args[i]
  2611. End If
  2612. Next
  2613. End If
  2614. End If
  2615. Return funcDecl
  2616. EndIf
  2617. If funcDecl.IsAbstract() Return funcDecl
  2618. 'Ok, only first statement of a constructor can call super constructor - not pretty, should be in semant.
  2619. If attrs & FUNC_CTOR
  2620. SkipEols
  2621. If CParse( "super" )
  2622. Parse "."
  2623. If _toke="new"
  2624. Local id$="New"
  2625. NextToke
  2626. 'funcDecl.superCtor=New TInvokeSuperExpr.Create( id,ParseArgs( True ) )
  2627. 'funcDecl.AddStmt New TExprStmt.Create( funcDecl.superCtor )
  2628. funcDecl.AddStmt New TExprStmt.Create( New TNewExpr.Create(ParseArgs(True), True))
  2629. Else
  2630. Local id$=ParseIdent()
  2631. funcDecl.AddStmt New TExprStmt.Create( New TInvokeSuperExpr.Create( id,ParseArgs( True ) ) )
  2632. EndIf
  2633. Else
  2634. 'Invoke super default ctor
  2635. 'funcDecl.superCtor=New InvokeSuperExpr( "new",[] )
  2636. 'funcDecl.AddStmt New TExprStmt( funcDecl.superCtor )
  2637. EndIf
  2638. EndIf
  2639. PushBlock funcDecl
  2640. While (Not meth And _toke.ToLower()<>"endfunction") Or (meth And _toke.ToLower()<>"endmethod")
  2641. If CParse( "end" )
  2642. If (Not meth And CParse("function")) Or (meth And CParse("method"))
  2643. Exit
  2644. End If
  2645. ' handle "end" statement
  2646. ParseEndStmt(False)
  2647. EndIf
  2648. ParseStmt
  2649. Wend
  2650. PopBlock
  2651. NextToke
  2652. 'If toke CParse toke
  2653. Return funcDecl
  2654. End Method
  2655. Method ParseCallConvention:Int(callConvention:Int = DECL_API_DEFAULT)
  2656. If _tokeType <> TOKE_STRINGLIT Then
  2657. Return callConvention
  2658. End If
  2659. Local api:String = ParseStringLit().ToLower()
  2660. If api = "os" Then
  2661. Select opt_platform
  2662. Case "macos", "osx", "ios"
  2663. api = "macos"
  2664. Case "linux", "android", "raspberrypi"
  2665. api = "linux"
  2666. Case "win32"
  2667. api = "win32"
  2668. Case "nx"
  2669. api = "nx"
  2670. End Select
  2671. End If
  2672. Select api
  2673. Case "c", "blitz", "macos", "linux", "nx"
  2674. Return DECL_API_CDECL
  2675. Case "win32"
  2676. ' only if we are compiling for win32
  2677. If opt_platform = "win32"
  2678. Return DECL_API_STDCALL
  2679. Else
  2680. Return DECL_API_CDECL
  2681. End If
  2682. End Select
  2683. Err "Unrecognized calling convention '" + api+ "'"
  2684. End Method
  2685. Method ParseFuncParamDecl:TArgDecl[]()
  2686. Local args:TArgDecl[]
  2687. Parse "("
  2688. SkipEols
  2689. If _toke<>")"
  2690. Local nargs:Int
  2691. Repeat
  2692. Local attrs:Int
  2693. If CParse("staticarray") Then
  2694. attrs :| DECL_STATIC
  2695. End If
  2696. Local argId$=ParseIdent()
  2697. Local ty:TType=ParseDeclType(attrs)
  2698. Local init:TExpr
  2699. ' var argument?
  2700. If CParse("var") Then
  2701. If attrs & DECL_STATIC Then
  2702. Err "Unexpected 'Var' for static array argument"
  2703. End If
  2704. ty = TType.MapToVarType(ty)
  2705. Else If CParse( "=" )
  2706. init=ParseExpr()
  2707. End If
  2708. Local arg:TArgDecl=New TArgDecl.Create( argId,ty,init,attrs )
  2709. If args.Length=nargs args=args + New TArgDecl[10]
  2710. args[nargs]=arg
  2711. nargs:+1
  2712. If _toke=")" Exit
  2713. Parse ","
  2714. Forever
  2715. args=args[..nargs]
  2716. EndIf
  2717. Parse ")"
  2718. Return args
  2719. End Method
  2720. Method ParseEnumDecl:TEnumDecl( toke:String )
  2721. SetErr
  2722. If toke Parse toke
  2723. Local id:String = ParseIdent()
  2724. Local ty:TType = ParseConstNumberType()
  2725. If Not ty Then
  2726. ty = New TIntType
  2727. End If
  2728. Local isFlags:Int = 0
  2729. Local values:TEnumValueDecl[0]
  2730. If CParse("flags")
  2731. isFlags = True
  2732. End If
  2733. Local decl:TEnumDecl = New TEnumDecl.Create(id, ty, isFlags, values)
  2734. Local nValues:Int
  2735. Repeat
  2736. SkipEols
  2737. If CParse("end") Then
  2738. Parse("enum")
  2739. Exit
  2740. End If
  2741. If CParse("endenum") Then
  2742. Exit
  2743. End If
  2744. Local valId:String = ParseIdent()
  2745. Local value:TExpr
  2746. If CParse( "=" ) Then
  2747. value = ParseExpr()
  2748. End If
  2749. Local v:TEnumValueDecl = New TEnumValueDecl.Create(valId, nValues, value)
  2750. If decl.values.Length = nValues Then
  2751. decl.values = decl.values + New TEnumValueDecl[10]
  2752. End If
  2753. decl.values[nValues] = v
  2754. nValues :+ 1
  2755. CParse(",")
  2756. Forever
  2757. decl.values = decl.values[..nValues]
  2758. Return decl
  2759. End Method
  2760. Method ParseClassDecl:TClassDecl( toke$,attrs:Int, templateDets:TTemplateDets = Null )
  2761. SetErr
  2762. Local calculatedStartLine:Int = _toker.Line()
  2763. Local startLine:Int = _toker._line
  2764. If toke Parse toke
  2765. Local id$=ParseIdent()
  2766. Local args:TList = New TList
  2767. Local superTy:TIdentType
  2768. Local imps:TIdentType[]
  2769. Local meta:TMetadata
  2770. 'If (attrs & CLASS_INTERFACE) And (attrs & DECL_EXTERN)
  2771. ' Err "Interfaces cannot be extern."
  2772. 'EndIf
  2773. If CParse( "<" )
  2774. If attrs & DECL_EXTERN
  2775. Err "Extern classes cannot be generic."
  2776. EndIf
  2777. 'If attrs & CLASS_INTERFACE
  2778. ' Err "Interfaces cannot be generic."
  2779. 'EndIf
  2780. 'If attrs & CLASS_TEMPLATEARG
  2781. ' Err "Class parameters cannot be generic."
  2782. 'EndIf
  2783. Local nargs:Int
  2784. Repeat
  2785. 'Local decl:TClassDecl=ParseClassDecl( "",CLASS_TEMPLATEARG )
  2786. 'If args.Length=nargs args=args + New TClassDecl[10]
  2787. 'args[nargs]=decl
  2788. 'nargs:+1
  2789. Local arg:TTemplateArg = New TTemplateArg
  2790. arg.ident = ParseIdent()
  2791. ' If CParse("extends") Then
  2792. ' arg.superTy = ParseIdentType()
  2793. ' End If
  2794. args.AddLast arg
  2795. Until Not CParse(",")
  2796. 'args=args[..nargs]
  2797. Parse ">"
  2798. If CParse( "where" ) Then
  2799. 'DebugStop
  2800. Repeat
  2801. Local argIdent:String = ParseIdent()
  2802. Parse("extends")
  2803. Local found:Int
  2804. For Local arg:TTemplateArg = EachIn args
  2805. If arg.ident = argIdent Then
  2806. Repeat
  2807. arg.ExtendsType(ParseIdentType())
  2808. Until Not CParse("and")
  2809. found = True
  2810. Exit
  2811. EndIf
  2812. Next
  2813. If Not found Then
  2814. Err "Use of undeclared type '" + argIdent + "'."
  2815. End If
  2816. Until Not CParse(",")
  2817. End If
  2818. EndIf
  2819. If CParse( "extends" )
  2820. 'If attrs & CLASS_TEMPLATEARG
  2821. ' Err "Extends cannot be used with class parameters."
  2822. 'EndIf
  2823. ' If CParse( "null" )
  2824. '
  2825. If attrs & CLASS_STRUCT
  2826. Err "Structs cannot be extended"
  2827. EndIf
  2828. '
  2829. ' If Not (attrs & DECL_EXTERN)
  2830. ' Err "Only extern objects can extend null."
  2831. ' EndIf
  2832. '
  2833. ' superTy=Null
  2834. '
  2835. ' Else
  2836. If attrs & CLASS_INTERFACE And Not (attrs & DECL_EXTERN)
  2837. Local nimps:Int
  2838. Repeat
  2839. If imps.Length=nimps imps=imps + New TIdentType[10]
  2840. imps[nimps]=ParseIdentType()
  2841. nimps:+1
  2842. Until Not CParse(",")
  2843. imps=imps[..nimps]
  2844. superTy=New TIdentType.Create( "brl.classes.object" )
  2845. Else
  2846. superTy=ParseIdentType()
  2847. EndIf
  2848. Else
  2849. If Not (attrs & DECL_EXTERN) And Not (attrs & CLASS_STRUCT) Then
  2850. superTy=New TIdentType.Create( "brl.classes.object" )
  2851. End If
  2852. EndIf
  2853. If CParse( "implements" )
  2854. If attrs & CLASS_STRUCT
  2855. Err "Implements cannot be used with Structs"
  2856. EndIf
  2857. 'If attrs & DECL_EXTERN
  2858. ' Err "Implements cannot be used with external classes."
  2859. 'EndIf
  2860. If attrs & CLASS_INTERFACE
  2861. Err "Implements cannot be used with interfaces."
  2862. EndIf
  2863. 'If attrs & CLASS_TEMPLATEARG
  2864. ' Err "Implements cannot be used with class parameters."
  2865. 'EndIf
  2866. Local nimps:Int
  2867. Repeat
  2868. If imps.Length=nimps imps=imps + New TIdentType[10]
  2869. imps[nimps]=ParseIdentType()
  2870. nimps:+1
  2871. Until Not CParse(",")
  2872. imps=imps[..nimps]
  2873. EndIf
  2874. Repeat
  2875. If CParse( "final" )
  2876. If attrs & CLASS_INTERFACE
  2877. Err "Final cannot be used with interfaces."
  2878. End If
  2879. If attrs & CLASS_STRUCT
  2880. Err "Final cannot be used with structs."
  2881. End If
  2882. If attrs & DECL_FINAL
  2883. Err "Duplicate modifier 'Final'."
  2884. End If
  2885. If attrs & DECL_ABSTRACT
  2886. Err "Classes cannot be both final and abstract."
  2887. End If
  2888. attrs:|DECL_FINAL
  2889. Else If CParse( "abstract" )
  2890. If attrs & CLASS_INTERFACE
  2891. Err "Abstract cannot be used with interfaces."
  2892. EndIf
  2893. If attrs & CLASS_STRUCT
  2894. Err "Abstract cannot be used with structs."
  2895. EndIf
  2896. If attrs & DECL_ABSTRACT
  2897. Err "Duplicate modifier 'Abstract'."
  2898. End If
  2899. If attrs & DECL_FINAL
  2900. Err "Types cannot be both final and abstract."
  2901. End If
  2902. attrs:|DECL_ABSTRACT
  2903. Else
  2904. Exit
  2905. EndIf
  2906. Forever
  2907. 'check for metadata
  2908. meta = ParseMetaData()
  2909. Local sargs:TTemplateArg[] = New TTemplateArg[args.Count()]
  2910. Local i:Int = 0
  2911. For Local arg:TTemplateArg = EachIn args
  2912. sargs[i] = arg
  2913. i :+ 1
  2914. Next
  2915. Local classDecl:TClassDecl=New TClassDecl.Create( id,sargs,superTy,imps,attrs )
  2916. If meta Then
  2917. If attrs & CLASS_STRUCT
  2918. Err "Structs cannot store metadata."
  2919. EndIf
  2920. classDecl.metadata = meta
  2921. End If
  2922. If classDecl.IsExtern()
  2923. classDecl.munged=classDecl.ident
  2924. If CParse( "=" ) classDecl.munged=ParseStringLit()
  2925. EndIf
  2926. 'If classDecl.IsTemplateArg() Return classDecl
  2927. Local decl_attrs:Int=(attrs & DECL_EXTERN) | (attrs & DECL_NODEBUG) | (attrs & DECL_API_STDCALL)
  2928. Repeat
  2929. Local method_attrs:Int=decl_attrs|FUNC_METHOD | (attrs & DECL_NODEBUG)
  2930. Local abst_attrs:Int = 0
  2931. If attrs & CLASS_INTERFACE abst_attrs:|DECL_ABSTRACT
  2932. SkipEols
  2933. Select _toke
  2934. Case "end"
  2935. NextToke
  2936. Exit
  2937. Case "endtype"
  2938. If attrs & CLASS_INTERFACE Then
  2939. Err "Syntax error - expecting End Interface, not 'EndType'"
  2940. End If
  2941. If attrs & CLASS_STRUCT Then
  2942. Err "Syntax error - expecting End Struct, not 'EndType'"
  2943. End If
  2944. toke = Null
  2945. NextToke
  2946. Exit
  2947. Case "endstruct"
  2948. If attrs & CLASS_INTERFACE Then
  2949. Err "Syntax error - expecting End Interface, not 'EndStruct'"
  2950. End If
  2951. If Not (attrs & CLASS_STRUCT) Then
  2952. Err "Syntax error - expecting End Type, not 'EndStruct'"
  2953. End If
  2954. toke = Null
  2955. NextToke
  2956. Exit
  2957. Case "endinterface"
  2958. If Not (attrs & CLASS_INTERFACE) And Not (attrs & CLASS_STRUCT) Then
  2959. Err "Syntax error - expecting End Type, not 'EndInterface'"
  2960. End If
  2961. If Not (attrs & CLASS_INTERFACE) And (attrs & CLASS_STRUCT) Then
  2962. Err "Syntax error - expecting End Struct, not 'EndInterface'"
  2963. End If
  2964. toke = Null
  2965. NextToke
  2966. Exit
  2967. Case "private"
  2968. If attrs & CLASS_INTERFACE Then
  2969. Err "Private cannot be used with interfaces."
  2970. End If
  2971. NextToke
  2972. decl_attrs=decl_attrs | DECL_PRIVATE
  2973. decl_attrs:& ~DECL_PROTECTED
  2974. Case "protected"
  2975. If attrs & CLASS_INTERFACE Then
  2976. Err "Protected cannot be used with interfaces."
  2977. End If
  2978. NextToke
  2979. decl_attrs=decl_attrs | DECL_PROTECTED
  2980. decl_attrs:& ~DECL_PRIVATE
  2981. Case "public"
  2982. NextToke
  2983. decl_attrs:& ~DECL_PRIVATE
  2984. decl_attrs:& ~DECL_PROTECTED
  2985. Case "const","global","field"
  2986. If attrs & DECL_EXTERN Then
  2987. If (attrs & CLASS_INTERFACE) Then
  2988. Err "Extern Interfaces can only contain methods."
  2989. End If
  2990. If Not (attrs & CLASS_STRUCT) Then
  2991. Err "Extern Types can only contain methods."
  2992. End If
  2993. End If
  2994. If (attrs & CLASS_INTERFACE) And _toke<>"const"
  2995. Err "Interfaces can only contain constants and methods."
  2996. EndIf
  2997. If (attrs & CLASS_STRUCT) And _toke<>"field" And _toke<>"global"
  2998. Err "Structs can only contain fields."
  2999. EndIf
  3000. classDecl.InsertDecls ParseDecls( _toke,decl_attrs, _toke = "field")
  3001. Case "method"
  3002. If (attrs & CLASS_STRUCT) And (attrs & DECL_EXTERN) Then
  3003. Err "Structs can only contain fields."
  3004. EndIf
  3005. Local decl:TFuncDecl=ParseFuncDecl( _toke,method_attrs | abst_attrs,classDecl )
  3006. classDecl.InsertDecl decl
  3007. Case "function"
  3008. 'If (attrs & CLASS_INTERFACE)
  3009. ' Err "Interfaces can only contain constants and methods."
  3010. 'EndIf
  3011. If attrs & CLASS_STRUCT Then
  3012. If (attrs & DECL_EXTERN) Then
  3013. Err "Structs can only contain fields."
  3014. End If
  3015. EndIf
  3016. If attrs & DECL_EXTERN Then
  3017. Err "Extern Types can only contain methods."
  3018. End If
  3019. Local decl:TFuncDecl=ParseFuncDecl( _toke,decl_attrs | abst_attrs,classDecl )
  3020. classDecl.InsertDecl decl
  3021. Case "type"
  3022. If templateDets Then
  3023. Local cdecl:TClassDecl = ParseClassDecl( _toke,DECL_NESTED, templateDets)
  3024. cdecl = cdecl.GenClassInstance(templateDets.instArgs, False, Null, templateDets)
  3025. classDecl.InsertDecl cdecl, True
  3026. Else
  3027. classDecl.InsertDecl ParseClassDecl( _toke,DECL_NESTED)
  3028. End If
  3029. Default
  3030. Err "Syntax error - expecting class member declaration, not '" + _toke + "'"
  3031. End Select
  3032. Forever
  3033. If Not args.IsEmpty() Then
  3034. Local endline:Int = _toker._line
  3035. classDecl.templateSource = New TTemplateRecord.Create(calculatedStartLine - 1, _toker._path, _toker.Join(startLine, endLine, "~n"))
  3036. End If
  3037. If toke Parse toke
  3038. Return classDecl
  3039. End Method
  3040. Method ParseNativeStmt()
  3041. If Not _toke.StartsWith("'!") Then
  3042. Err "Syntax error - expecting '!"
  3043. End If
  3044. Local raw:String = _toke[2..]
  3045. _block.AddStmt New TNativeStmt.Create( raw )
  3046. NextToke
  3047. End Method
  3048. Method ParseModuleDecl:String( toke$,attrs:Int )
  3049. NextToke
  3050. ' namespace . module
  3051. Return ParseModPath().ToLower()
  3052. End Method
  3053. Method ParseModPath$()
  3054. Local path$=ParseIdent()
  3055. While CParse( "." )
  3056. path:+"."+ParseIdent()
  3057. Wend
  3058. Return path
  3059. End Method
  3060. Method ExtractModIdent$( modpath$ )
  3061. Local i:Int=modpath.FindLast( "." )
  3062. If i<>-1 Return modpath[i+1..]
  3063. Return modpath
  3064. End Method
  3065. Method ImportFile( filepath$ )
  3066. If filepath.Endswith(".bmx") Then
  3067. filepath = ActualPath(filepath)
  3068. Local origPath:String = RealPath(filepath)
  3069. Local path:String = OutputFilePath(origPath, FileMung(), "i")
  3070. If FileType( origPath )<>FILETYPE_FILE
  3071. Err "File '"+ origPath +"' not found."
  3072. EndIf
  3073. If FileType( path )<>FILETYPE_FILE
  3074. Err "File '"+ path +"' not found."
  3075. EndIf
  3076. If _module.imported.Contains( path ) Return
  3077. Local modpath:String
  3078. If opt_buildtype = BUILDTYPE_MODULE Then
  3079. Local dir:String = ExtractDir(origPath).ToLower()
  3080. dir = dir[dir.findLast("/") + 1..]
  3081. If dir.EndsWith(".mod") Then
  3082. dir = ""
  3083. Else
  3084. dir :+ "_"
  3085. End If
  3086. Local file:String = StripDir(origPath).ToLower()
  3087. modpath = opt_modulename + "_" + dir + StripExt(file)
  3088. Else
  3089. modpath = StripExt(filepath)
  3090. End If
  3091. 'sanitize the path, remove non-allowed chars
  3092. modpath = TStringHelper.Sanitize(modpath.ToLower())
  3093. ' try to import interface
  3094. Local par:TIParser = New TIParser
  3095. If par.ParseModuleImport(_module, modpath, origPath, path, , , filepath, True) Return
  3096. Else If filepath.startswith("-") Then
  3097. If Not _app.fileimports.Contains(filepath) Then
  3098. _app.fileimports.AddLast filepath
  3099. End If
  3100. Else
  3101. If filepath.EndsWith(".h") Or filepath.EndsWith(".hpp") Or filepath.EndsWith(".hxx") Then
  3102. If filepath.Find("*") = -1 Then
  3103. _app.headers.AddLast filepath
  3104. End If
  3105. Else
  3106. Local path:String = ActualPath(RealPath(filepath))
  3107. If FileType( path )<>FILETYPE_FILE
  3108. Err "File '"+ path +"' not found."
  3109. End If
  3110. End If
  3111. End If
  3112. End Method
  3113. Method ImportAllModules(attrs:Int)
  3114. ' get all brl and pub modules
  3115. Local mods:TList = EnumModules("brl")
  3116. mods = EnumModules("pub", mods)
  3117. For Local m:String = EachIn mods
  3118. ImportModule(m, attrs)
  3119. Next
  3120. End Method
  3121. Method ImportModule( modpath$,attrs:Int )
  3122. SetErr
  3123. modpath = modpath.ToLower()
  3124. Local basepath:String = ModulePath(modpath.ToLower())
  3125. If _module.imported.Contains( basepath ) Return
  3126. ' try to import interface
  3127. Local par:TIParser = New TIParser
  3128. If par.ParseModuleImport(_module, modpath, basepath, , , attrs) Return
  3129. 'DebugStop
  3130. 'Local mdecl:TDecl=_app.imported.ValueForKey( basepath )
  3131. 'If Not mdecl
  3132. ' mdecl=ParseModule( filepath,_app )
  3133. 'EndIf
  3134. '_module.imported.Insert mdecl.filepath,mdecl
  3135. 'If Not (attrs & DECL_PRIVATE) _module.pubImported.Insert mdecl.filepath,mdecl
  3136. '_module.InsertDecl New AliasDecl( mdecl.ident,mdecl,attrs )
  3137. 'End Rem
  3138. End Method
  3139. Method ValidateModIdent( id$ )
  3140. If id.Length
  3141. If IsAlpha( id[0] ) Or id[0]="_"[0]
  3142. Local err:Int
  3143. For Local i:Int=1 Until id.Length
  3144. If IsAlpha( id[i] ) Or IsDigit( id[i] ) Or id[i]="_"[0] Continue
  3145. err=1
  3146. Exit
  3147. Next
  3148. If Not err Return
  3149. EndIf
  3150. EndIf
  3151. Err "Invalid module identifier '"+id+"'."
  3152. End Method
  3153. Method MungAppDecl(app:TAppDecl)
  3154. If opt_buildtype = BUILDTYPE_MODULE And opt_ismain Then
  3155. app.munged = MungModuleName(opt_modulename)
  3156. Else If opt_buildtype = BUILDTYPE_MODULE Then
  3157. Local dir:String = ExtractDir(opt_filepath).ToLower()
  3158. dir = dir[dir.findLast("/") + 1..]
  3159. If dir.EndsWith(".mod") Then
  3160. dir = ""
  3161. Else
  3162. dir :+ "_"
  3163. End If
  3164. app.munged = "_bb_" + opt_modulename + "_" + dir + StripExt(StripDir(opt_filepath).ToLower())
  3165. Else
  3166. ' main application file?
  3167. If opt_apptype Then
  3168. app.munged = "_bb_main"
  3169. Else
  3170. Local dir:String = ExtractDir(opt_filepath).ToLower()
  3171. dir = dir[dir.findLast("/") + 1..]
  3172. If dir.EndsWith(".mod") Then
  3173. dir = dir.Replace(".mod", "")
  3174. End If
  3175. Local file:String = StripDir(opt_filepath).ToLower()
  3176. app.munged = "_bb_" + dir + "_" + StripExt(file)
  3177. End If
  3178. End If
  3179. 'sanitize, remove non-allowed chars
  3180. app.munged = TStringHelper.Sanitize(app.munged)
  3181. End Method
  3182. ' load external cast defs
  3183. Method LoadExternCasts(path:String)
  3184. For Local externs:Int = 0 Until 3
  3185. Local ePath:String
  3186. ' we will iterate through all possibilities as there may be different sets
  3187. ' of explicit casts/no gen funcs for each.
  3188. Select externs
  3189. Case 0
  3190. ' eg. file.win32.x86.x
  3191. ePath = StripExt(path) + "." + opt_platform + "." + opt_arch + ".x"
  3192. Case 1
  3193. ' eg. file.win32.x
  3194. ePath = StripExt(path) + "." + opt_platform + ".x"
  3195. Case 2
  3196. ' eg. file.x
  3197. ePath = StripExt(path) + ".x"
  3198. End Select
  3199. If FileType(ePath) = FILETYPE_FILE Then
  3200. Print "Warning: .x cast definition files are deprecated. You should now place the details in the extern function's alias string. (" + path + ")"
  3201. ParseExternCast(LoadText( ePath ), False, ePath)
  3202. End If
  3203. Next
  3204. End Method
  3205. Method ParseExternCast:TCastDets(txt:String, single:Int = False, path:String = "")
  3206. Local toker:TToker = New TToker.Create(path, txt)
  3207. toker.NextToke
  3208. Local dets:TCastDets
  3209. While True
  3210. SkipEolsToker(toker)
  3211. If toker._tokeType = TOKE_EOF Exit
  3212. dets = New TCastDets
  3213. Local rt$=toker._toke
  3214. If CParseToker(toker, "const") Then
  3215. rt :+ " " + toker._toke
  3216. End If
  3217. If CParseToker(toker, "unsigned") Then
  3218. rt :+ " " + toker._toke
  3219. End If
  3220. NextTokeToker(toker)
  3221. If CParseToker(toker,"*") Then
  3222. rt:+ "*"
  3223. If CParseToker(toker,"*") Then
  3224. rt:+ "*"
  3225. End If
  3226. End If
  3227. If CParseToker(toker, "__stdcall") Then
  3228. dets.api = "__stdcall"
  3229. End If
  3230. ' fname
  3231. Local fn$=toker._toke
  3232. NextTokeToker(toker)
  3233. dets.name = fn
  3234. dets.retType = rt
  3235. ' add to global map (may be referenced by function ptr defs)
  3236. _externCasts.Insert(fn, dets)
  3237. ' args
  3238. ParseToker(toker, "(")
  3239. If CParseToker(toker, ")") Then
  3240. ' don't generate header extern
  3241. If CParseToker(toker, "!") Then
  3242. dets.noGen = True
  3243. End If
  3244. Continue
  3245. End If
  3246. Local i:Int = 0
  3247. Repeat
  3248. Local at$=toker._toke
  3249. If CParseToker(toker, "const") Then
  3250. at :+ " " + toker._toke
  3251. End If
  3252. If CParseToker(toker, "unsigned") Then
  3253. at :+ " " + toker._toke
  3254. End If
  3255. If CParseToker(toker, "struct") Then
  3256. at :+ " " + toker._toke
  3257. End If
  3258. NextTokeToker(toker)
  3259. If CParseToker(toker, "*") Then
  3260. at:+ "*"
  3261. If CParseToker(toker, "const") Then
  3262. at :+ " const"
  3263. End If
  3264. If CParseToker(toker, "*") Then
  3265. at:+ "*"
  3266. End If
  3267. End If
  3268. ' function pointer
  3269. If CParseToker(toker, "(") Then
  3270. ParseToker(toker, "*")
  3271. ParseToker(toker, ")")
  3272. at :+ "(*)"
  3273. ParseToker(toker, "(")
  3274. at :+ "("
  3275. While Not CParseToker(toker, ")")
  3276. NextTokeToker(toker)
  3277. at :+ toker._toke
  3278. Wend
  3279. at :+ ")"
  3280. End If
  3281. dets.args :+ [at]
  3282. If toker._toke=")" Exit
  3283. ParseToker(toker, ",")
  3284. i:+ 1
  3285. Forever
  3286. NextTokeToker(toker)
  3287. ' don't generate header extern
  3288. If CParseToker(toker, "!") Then
  3289. dets.noGen = True
  3290. End If
  3291. If single Then
  3292. Exit
  3293. End If
  3294. Wend
  3295. Return dets
  3296. End Method
  3297. Method ParseCurrentFile:Int(path:String, attrs:Int)
  3298. LoadExternCasts(path)
  3299. While _toke
  3300. SetErr
  3301. Select _toke.toLower()
  3302. Case "~n"
  3303. NextToke
  3304. Case "public"
  3305. NextToke
  3306. attrs=attrs & ~DECL_PRIVATE
  3307. Case "private"
  3308. NextToke
  3309. attrs=attrs | DECL_PRIVATE
  3310. Case "extern"
  3311. ParseExternBlock(_module, attrs)
  3312. Case "const"
  3313. _module.InsertDecls ParseDecls( _toke,attrs )
  3314. Case "global"
  3315. ParseDeclStmts(True, attrs, _module)
  3316. Case "struct"
  3317. _module.InsertDecl ParseClassDecl( _toke,attrs | CLASS_STRUCT )
  3318. Case "type"
  3319. _module.InsertDecl ParseClassDecl( _toke,attrs)
  3320. Case "interface"
  3321. _module.InsertDecl ParseClassDecl( _toke,attrs|CLASS_INTERFACE|DECL_ABSTRACT )
  3322. Case "enum"
  3323. _module.InsertDecl ParseEnumDecl( _toke )
  3324. Case "function"
  3325. _module.InsertDecl ParseFuncDecl( _toke,attrs )
  3326. Case "incbin"
  3327. NextToke
  3328. Local s:String = ParseStringLit()
  3329. _app.mapStringConsts(s)
  3330. Local ib:TIncBin = New TIncbin.Create(s, path)
  3331. If Not ib Then
  3332. DoErr "Incbin file '"+ s +"' not found."
  3333. End If
  3334. _app.incbins.AddLast(ib)
  3335. Case "include"
  3336. 'include command is NOT just a pattern to replace with
  3337. 'content. BlitzMax parses each included file before the
  3338. 'content gets appended to the source (right before
  3339. 'semanting or analyzing content)
  3340. NextToke
  3341. Local includeFile:String = ParseStringLit()
  3342. 'convert the URI of the to include file as it might be
  3343. 'a relative one
  3344. includeFile = RealPath(includeFile)
  3345. 'instead of merging the data of multiple parsers, the
  3346. 'same parser is used for all included files - but each
  3347. 'of them uses an individual toker
  3348. If FileType( includeFile )<>FILETYPE_FILE
  3349. DoErr "File '"+ includeFile +"' not found."
  3350. EndIf
  3351. 'instead of "LoadText" "PreProcess" is used to include
  3352. 'handling of conditionals and comments
  3353. Try
  3354. Local includeSource:String = PreProcess(includeFile)
  3355. Local includeToker:TToker = New TToker.Create(includeFile, includeSource)
  3356. 'backup old vars
  3357. Local oldToker:TToker = Self._toker
  3358. 'assign temporary vars
  3359. Self._toker = includeToker
  3360. 'parse the include file
  3361. parseCurrentFile(includeFile, attrs)
  3362. 'restore backup vars
  3363. Self._toker = oldToker
  3364. Catch e:TStreamException
  3365. DoErr "Failed to include file '" + includeFile + "' : '" + e.ToString() + "'"
  3366. End Try
  3367. 'move on to next toke (after include "xyz.bmx")
  3368. NextToke
  3369. Default
  3370. ParseStmt
  3371. 'Err "Syntax error - expecting declaration."
  3372. End Select
  3373. Wend
  3374. Return attrs
  3375. End Method
  3376. Method ParseGeneric:Object(templateSource:TTemplateRecord, templateDets:TTemplateDets)
  3377. Local toker:TToker = New TToker.Create(templateSource.file, templateSource.source, False, templateSource.start)
  3378. Local parser:TParser = New TParser.Create( toker, _appInstance )
  3379. Local m:TModuleDecl = New TModuleDecl
  3380. parser._module = m
  3381. Local cdecl:TClassDecl = Null
  3382. Select parser._toke
  3383. Case "type"
  3384. cdecl = parser.ParseClassDecl(parser._toke,0, templateDets )
  3385. Case "interface"
  3386. cdecl = parser.ParseClassDecl(parser._toke, CLASS_INTERFACE|DECL_ABSTRACT, templateDets )
  3387. End Select
  3388. Return cdecl
  3389. End Method
  3390. Method ParseMain()
  3391. SkipEols
  3392. Local mattrs:Int
  3393. 'If CParse( "strict" ) mattrs:|MODULE_STRICT
  3394. 'If CParse( "superstrict" ) mattrs:|MODULE_SUPERSTRICT
  3395. Local path$=_toker.Path()
  3396. Local ident$=StripAll( path )
  3397. Local munged$ '="bb_"+ident+"_"
  3398. If opt_buildtype = BUILDTYPE_MODULE And opt_ismain
  3399. ValidateModIdent ident
  3400. Else If opt_buildtype = BUILDTYPE_MODULE Then
  3401. Local dir:String = ExtractDir(opt_filepath).ToLower()
  3402. dir = dir[dir.findLast("/") + 1..]
  3403. If dir.EndsWith(".mod") Then
  3404. dir = ""
  3405. Else
  3406. dir :+ "_"
  3407. End If
  3408. munged = opt_modulename + "_" + dir + ident
  3409. 'sanitize, remove non-allowed chars
  3410. munged = TStringHelper.Sanitize(munged.ToLower())
  3411. End If
  3412. If opt_ismain Then 'And opt_modulename <> "brl.blitz" Then
  3413. ident = opt_modulename
  3414. End If
  3415. If opt_buildtype = BUILDTYPE_APP Then
  3416. ident = "m_" + ident
  3417. End If
  3418. _module=New TModuleDecl.Create( ident,munged,path,mattrs )
  3419. _module.AddImport path,_module
  3420. _app.InsertModule _module
  3421. ' mung the app decl
  3422. MungAppDecl(_app)
  3423. If opt_buildtype = BUILDTYPE_MODULE And opt_modulename = "brl.blitz" Then
  3424. ' import Object and String definitions
  3425. Local par:TIParser = New TIParser
  3426. par.ParseModuleImport(_module, "brl.classes", modulepath("brl.blitz"), modulepath("brl.blitz") + "/blitz_classes.i")
  3427. ' set up built-in keywords
  3428. par = New TIParser
  3429. par.ParseModuleImport(_module, "brl.blitzkeywords", "", "", MakeKeywords())
  3430. End If
  3431. ' don't import ourself
  3432. If opt_modulename <> "brl.blitz" Then
  3433. Local par:TIParser = New TIParser
  3434. par.ParseModuleImport(_module, "brl.blitz", modulepath("brl.blitz"), , , MODULE_ACTUALMOD)
  3435. End If
  3436. Local mainFunc:TFuncDecl = New TFuncDecl.CreateF("__LocalMain", New TIntType,Null,0)
  3437. '_app.InsertDecl mainFunc
  3438. _module.insertDecl(mainFunc)
  3439. 'Local mainBlock:TBlockDecl = New TBlockDecl.Create( _block )
  3440. ' import all brl and pub modules if we haven't specified one
  3441. If opt_buildtype <> BUILDTYPE_MODULE And Not opt_framework Then
  3442. ImportAllModules MODULE_ACTUALMOD
  3443. Else
  3444. If opt_framework Then
  3445. Local par:TIParser = New TIParser
  3446. par.ParseModuleImport(_module, opt_framework, modulepath(opt_framework), , , MODULE_ACTUALMOD)
  3447. End If
  3448. End If
  3449. Local attrs:Int
  3450. While _toke
  3451. SetErr
  3452. Select _toke.ToLower()
  3453. Case "~n"
  3454. NextToke
  3455. Case "strict"
  3456. If _module.attrs & (MODULE_STRICT | MODULE_SUPERSTRICT) Then
  3457. Err "Strict or SuperStrict already specified"
  3458. End If
  3459. _module.attrs :| MODULE_STRICT
  3460. nextToke
  3461. Case "superstrict"
  3462. If _module.attrs & (MODULE_STRICT | MODULE_SUPERSTRICT) Then
  3463. Err "Strict or SuperStrict already specified"
  3464. End If
  3465. _module.attrs :| MODULE_SUPERSTRICT
  3466. opt_issuperstrict = True
  3467. NextToke
  3468. Default
  3469. Exit
  3470. End Select
  3471. Wend
  3472. If opt_need_strict And Not (_module.attrs & (MODULE_STRICT | MODULE_SUPERSTRICT)) Then
  3473. Err "Strict or SuperStrict must be declared at the start of the file."
  3474. End If
  3475. 'Parse header - imports etc.
  3476. While _toke
  3477. SetErr
  3478. Select _toke.ToLower()
  3479. Case "~n"
  3480. NextToke
  3481. Case "public"
  3482. NextToke
  3483. attrs=attrs & ~DECL_PRIVATE
  3484. Case "private"
  3485. NextToke
  3486. attrs=attrs | DECL_PRIVATE
  3487. Case "import"
  3488. NextToke
  3489. If _tokeType=TOKE_STRINGLIT
  3490. ' TODO
  3491. 'ImportFile ReplaceEnvTags( ParseStringLit() )
  3492. ImportFile ParseStringLit()
  3493. Else
  3494. ImportModule ParseModPath(),attrs | MODULE_ACTUALMOD
  3495. EndIf
  3496. Case "framework"
  3497. NextToke
  3498. ImportModule ParseModPath(),attrs
  3499. Case "alias"
  3500. NextToke
  3501. Repeat
  3502. Local ident$=ParseIdent()
  3503. Parse "="
  3504. Local decl:Object
  3505. Local scope:TScopeDecl=_module
  3506. _env=_module 'naughty! Shouldn't be doing GetDecl in parser...
  3507. Repeat
  3508. Local id$=ParseIdent()
  3509. decl=scope.FindDecl( id )
  3510. If Not decl Err "Identifier '"+id+"' not found."
  3511. If Not CParse( "." ) Exit
  3512. scope=TScopeDecl( decl )
  3513. If Not scope Or TFuncDecl( scope ) Err "Invalid scope '"+id+"'."
  3514. Forever
  3515. _env=Null '/naughty
  3516. _module.InsertDecl New TAliasDecl.Create( ident,decl,attrs )
  3517. Until Not CParse(",")
  3518. Case "module"
  3519. Local m:String = ParseModuleDecl(_toke, attrs)
  3520. If m.ToLower() <> opt_modulename Then
  3521. Err "Module does not match commandline module"
  3522. End If
  3523. 'sanitize, remove non-allowed chars
  3524. _module.munged = TStringHelper.Sanitize(m)
  3525. Case "nodebug"
  3526. mainFunc.attrs :| DECL_NODEBUG
  3527. attrs :| DECL_NODEBUG
  3528. NextToke
  3529. Case "moduleinfo"
  3530. NextToke
  3531. Local info:String = ParseStringLit()
  3532. _module.modInfo.AddLast(info)
  3533. Default
  3534. Exit
  3535. End Select
  3536. Wend
  3537. ' app code
  3538. PushBlock(mainFunc)
  3539. 'Parse main app
  3540. attrs = ParseCurrentFile(path, attrs)
  3541. PopBlock
  3542. End Method
  3543. Method ParseModule()
  3544. End Method
  3545. Method Create:TParser( toker:TToker,app:TAppDecl, unknownIdentsEvalFalse:Int = False )
  3546. _toke="~n"
  3547. _toker=toker
  3548. _app=app
  3549. SetErr
  3550. NextToke
  3551. Self.unknownIdentsEvalFalse = unknownIdentsEvalFalse
  3552. Return Self
  3553. End Method
  3554. End Type
  3555. Function Eval$( toker:TToker,_type:TType )
  3556. Local src$
  3557. While toker.Toke() And toker.Toke()<>"'" And toker.Toke()<>"~n" And toker.Toke()<>"~r"
  3558. src:+toker.Toke()
  3559. toker.NextToke()
  3560. Wend
  3561. Local t:String=EvalS( src,_type )
  3562. Return t
  3563. End Function
  3564. Function PreProcessNextToke$(toker:TToker)
  3565. Repeat
  3566. toker.NextToke()
  3567. Until toker.tokeType()<>TOKE_SPACE Or toker.Toke().Endswith("~n")
  3568. Return toker._toke
  3569. End Function
  3570. Function PreProcess$( path$ )
  3571. Local ifnest:Int,con:Int=1,line:Int,source:TStringList=New TStringList
  3572. Local toker:TToker=New TToker.Create( path,LoadText( path ), True )
  3573. PreProcessNextToke(toker)
  3574. Repeat
  3575. If line
  3576. source.AddLast "~n"
  3577. While toker.Toke() And Not toker.Toke().Endswith("~n") And toker.TokeType()<>TOKE_LINECOMMENT
  3578. PreProcessNextToke(toker)
  3579. Wend
  3580. If Not toker.Toke() Exit
  3581. PreProcessNextToke(toker)
  3582. EndIf
  3583. line :+ 1
  3584. ' catch up with any skipped lines
  3585. While line < toker._line - 1
  3586. line:+1
  3587. source.AddLast "~n"
  3588. Wend
  3589. If toker.TokeType()=TOKE_SPACE And Not toker.Toke().Endswith("~n") PreProcessNextToke(toker)
  3590. If toker.Toke()<>"?"
  3591. If con
  3592. Local textline$
  3593. While toker.Toke() And toker.Toke()<>"~n" And toker.TokeType()<>TOKE_LINECOMMENT
  3594. Local toke$=toker.Toke()
  3595. textline:+toke
  3596. toker.NextToke()
  3597. Wend
  3598. If textline Then
  3599. source.AddLast textline
  3600. EndIf
  3601. EndIf
  3602. Continue
  3603. EndIf
  3604. Local stm$= PreProcessNextToke(toker).ToLower()
  3605. 'toker.NextToke()
  3606. Local isNot:Int = False
  3607. If stm = "not" Then
  3608. If toker.TokeType()=TOKE_SPACE PreProcessNextToke(toker)
  3609. stm = toker.Toke().ToLower()
  3610. isNot = True
  3611. End If
  3612. 'If stm="end" Or stm="else"
  3613. ' If toker.TokeType()=TOKE_SPACE toker.NextToke()
  3614. ' If toker.Toke().ToLower()="if"
  3615. ' toker.NextToke()
  3616. ' stm:+"if"
  3617. ' EndIf
  3618. 'EndIf
  3619. Rem
  3620. Debug True if program is being compiled in debug mode.
  3621. Threaded True if program is being compiled in threaded mode.
  3622. Win32 True if program is being compiled for the Windows operating system.
  3623. MacOS True if program is being compiled for the MacOS operating system.
  3624. Linux True if program is being compiled for the Linux operating system.
  3625. X86 True if program is being compiled for the Intel CPU.
  3626. PPC True if program is being compiled for the PowerPC CPU.
  3627. MacOSX86 True if program is being compiled for an Intel Mac.
  3628. MacOSPPC True if program is being compiled for a PowerPC Mac.
  3629. BigEndian True if program is being compiled for a big endian CPU.
  3630. LittleEndian
  3631. End Rem
  3632. Select stm
  3633. Case "~r", "~n"
  3634. 'ifnest = 0
  3635. con = 1
  3636. Default
  3637. ' test for EOF
  3638. If Not toker.Toke() Exit
  3639. con = 0
  3640. Try
  3641. If Eval( toker,New TIntType ) = "1" con = 1
  3642. Catch Error:String
  3643. con = 0
  3644. End Try
  3645. Rem
  3646. Case "macos", "macosx86", "x86", "littleendian", "bigendian"
  3647. con = 1
  3648. ' If con=ifnest
  3649. ' If Eval( toker,TType.intType ) con:+1
  3650. ' EndIf
  3651. '
  3652. ifnest = 1
  3653. ' Case "rem"
  3654. '
  3655. ' ifnest:+1
  3656. Case "threaded", "win32", "linux", "ppc", "win32x86", "linuxx86", "macosppc"
  3657. If isNot Then
  3658. con = 1
  3659. Else
  3660. con = 0
  3661. End If
  3662. ifnest = 1
  3663. Case "else","elseif"
  3664. If Not ifnest Err "#Else without #If"
  3665. If con=ifnest
  3666. con=-con
  3667. Else If con=ifnest-1
  3668. If stm="elseif"
  3669. If Eval( toker,TType.intType ) con:+1
  3670. Else
  3671. con:+1
  3672. EndIf
  3673. EndIf
  3674. Case "end","endif"
  3675. If Not ifnest Err "#End without #If"
  3676. ifnest:-1
  3677. If con<0 con=-con
  3678. If ifnest<con con=ifnest
  3679. ' Case "print"
  3680. ' If con=ifnest
  3681. ' TODO
  3682. 'Print ReplaceEnvTags( Eval( toker,TType.stringType ) )
  3683. ' EndIf
  3684. ' Case "error"
  3685. ' If con=ifnest
  3686. ' TODO
  3687. 'Err ReplaceEnvTags( Eval( toker,TType.stringType ) )
  3688. ' EndIf
  3689. Default
  3690. Err "Unrecognized preprocessor directive '"+stm+"'."
  3691. End Rem
  3692. End Select
  3693. Forever
  3694. Return source.Join( "" )
  3695. End Function
  3696. Function ParseModule:TModuleDecl( path$,app:TAppDecl )
  3697. 'Local source$=PreProcess( path )
  3698. Local source:String = LoadText(path)
  3699. Local toker:TToker=New TToker.Create( path,source )
  3700. Local parser:TParser=New TParser.Create( toker,app )
  3701. parser.ParseMain
  3702. Return parser._module
  3703. End Function
  3704. Function AppendLibInit:String(source:String)
  3705. Local sb:TStringBuffer = TStringBuffer.Create(source)
  3706. sb.Append("~n")
  3707. sb.Append("Extern~n")
  3708. sb.Append("Function bbLibInit()~n")
  3709. sb.Append("End Extern~n")
  3710. sb.Append("Function InitBRL() Export~n")
  3711. sb.Append("bbLibInit()~n")
  3712. sb.Append("End Function~n")
  3713. Return sb.ToString()
  3714. End Function
  3715. '***** PUBLIC API ******
  3716. Function ParseApp:TAppDecl( path$ )
  3717. Local app:TAppDecl=New TAppDecl
  3718. _appInstance = app
  3719. Local source$=PreProcess( path )
  3720. 'Local source:String = LoadString(path)
  3721. If opt_makelib And opt_apptype Then
  3722. source = AppendLibInit(source)
  3723. End If
  3724. Local toker:TToker=New TToker.Create( path,source )
  3725. Local parser:TParser=New TParser.Create( toker,app )
  3726. parser.ParseMain
  3727. Return app
  3728. End Function
  3729. Function MungModuleName:String(ident:Object)
  3730. Local mung:String
  3731. If String(ident) Then
  3732. Local id:String = String(ident)
  3733. mung = "__bb_" + id + "_" + id[id.Find(".") + 1..]
  3734. Else
  3735. Local mdecl:TModuleDecl = TModuleDecl(ident)
  3736. If mdecl Then
  3737. Local id:String = mdecl.ident
  3738. Local dir:String = ExtractDir(mdecl.filepath).ToLower()
  3739. dir = dir[dir.findLast("/") + 1..]
  3740. If dir.EndsWith(".mod") Then
  3741. dir = ""
  3742. Else
  3743. dir :+ "_"
  3744. End If
  3745. mung = "__bb_" + id + "_" + dir + id[id.Find(".") + 1..]
  3746. End If
  3747. End If
  3748. 'return sanitized, remove non-allowed chars
  3749. Return TStringHelper.Sanitize(mung)
  3750. End Function
  3751. Function EvalS$( source$,ty:TType )
  3752. Local env:TScopeDecl=New TScopeDecl
  3753. Rem
  3754. Debug True if program is being compiled in debug mode.
  3755. Threaded True if program is being compiled in threaded mode.
  3756. Win32 True if program is being compiled for the Windows operating system.
  3757. MacOS True if program is being compiled for the MacOS operating system.
  3758. Linux True if program is being compiled for the Linux operating system.
  3759. X86 True if program is being compiled for the Intel CPU.
  3760. PPC True if program is being compiled for the PowerPC CPU.
  3761. MacOSX86 True if program is being compiled for an Intel Mac.
  3762. MacOSPPC True if program is being compiled for a PowerPC Mac.
  3763. BigEndian True if program is being compiled for a big endian CPU.
  3764. LittleEndian
  3765. End Rem
  3766. ' debug/release
  3767. env.InsertDecl New TConstDecl.Create( "debug",New TIntType,New TConstExpr.Create( New TIntType,opt_debug ),0 )
  3768. 'env.InsertDecl New TConstDecl.Create( "release",TType.intType,New TConstExpr.Create( TType.intType,opt_release ),0 )
  3769. ' threaded
  3770. env.InsertDecl New TConstDecl.Create( "threaded",New TIntType,New TConstExpr.Create( New TIntType,opt_threaded ),0 )
  3771. ' macos
  3772. env.InsertDecl New TConstDecl.Create( "macos",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="macos" Or opt_platform="osx" Or opt_platform="ios"),0 )
  3773. env.InsertDecl New TConstDecl.Create( "macosx86",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="macos" Or opt_platform="osx" Or opt_platform="ios") And opt_arch="x86"),0 )
  3774. env.InsertDecl New TConstDecl.Create( "macosppc",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="macos" Or opt_platform="osx") And opt_arch="ppc"),0 )
  3775. env.InsertDecl New TConstDecl.Create( "macosx64",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="macos" Or opt_platform="osx" Or opt_platform="ios") And opt_arch="x64"),0 )
  3776. ' osx
  3777. env.InsertDecl New TConstDecl.Create( "osx",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="macos" Or opt_platform="osx" ),0 )
  3778. env.InsertDecl New TConstDecl.Create( "osxx86",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="macos" Or opt_platform="osx") And opt_arch="x86"),0 )
  3779. env.InsertDecl New TConstDecl.Create( "osxppc",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="macos" Or opt_platform="osx") And opt_arch="ppc"),0 )
  3780. env.InsertDecl New TConstDecl.Create( "osxx64",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="macos" Or opt_platform="osx") And opt_arch="x64"),0 )
  3781. ' ios
  3782. env.InsertDecl New TConstDecl.Create( "ios",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="ios" ),0 )
  3783. env.InsertDecl New TConstDecl.Create( "iosx86",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="ios" And opt_arch="x86"),0 )
  3784. env.InsertDecl New TConstDecl.Create( "iosx64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="ios" And opt_arch="x64"),0 )
  3785. env.InsertDecl New TConstDecl.Create( "iosarmv7",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="ios" And opt_arch="armv7"),0 )
  3786. env.InsertDecl New TConstDecl.Create( "iosarm64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="ios" And opt_arch="arm64"),0 )
  3787. ' windows
  3788. env.InsertDecl New TConstDecl.Create( "win32",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="win32" ),0 )
  3789. env.InsertDecl New TConstDecl.Create( "win32x86",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="win32" And opt_arch="x86"),0 )
  3790. env.InsertDecl New TConstDecl.Create( "win32x64",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="win64" And opt_arch="x64") Or (opt_platform="win32" And opt_arch="x64")),0 )
  3791. env.InsertDecl New TConstDecl.Create( "win64",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="win64" And opt_arch="x64") Or (opt_platform="win32" And opt_arch="x64")),0 )
  3792. ' linux
  3793. env.InsertDecl New TConstDecl.Create( "linux",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="linux" Or opt_platform="android" Or opt_platform="raspberrypi")),0 )
  3794. env.InsertDecl New TConstDecl.Create( "linuxx86",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="linux" Or opt_platform="android") And opt_arch="x86"),0 )
  3795. env.InsertDecl New TConstDecl.Create( "linuxx64",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="linux" Or opt_platform="android") And opt_arch="x64"),0 )
  3796. env.InsertDecl New TConstDecl.Create( "linuxarm",New TIntType,New TConstExpr.Create( New TIntType, ((opt_platform="android" Or opt_platform="linux") And (opt_arch="arm" Or opt_arch="armeabi" Or opt_arch="armeabiv7a" Or opt_arch="arm64v8a")) Or (opt_platform="raspberrypi" And opt_arch="arm")),0 )
  3797. env.InsertDecl New TConstDecl.Create( "linuxarm64",New TIntType,New TConstExpr.Create( New TIntType, (opt_platform="android" And opt_arch="arm64v8a") Or ((opt_platform="linux" Or opt_platform="raspberrypi") And opt_arch="arm64")),0 )
  3798. ' android
  3799. env.InsertDecl New TConstDecl.Create( "android",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" ),0 )
  3800. env.InsertDecl New TConstDecl.Create( "androidx86",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And opt_arch="x86"),0 )
  3801. env.InsertDecl New TConstDecl.Create( "androidx64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And opt_arch="x64"),0 )
  3802. env.InsertDecl New TConstDecl.Create( "androidarm",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And (opt_arch="arm" Or opt_arch="armeabi" Or opt_arch="armeabiv7a" Or opt_arch="arm64v8a") ),0 )
  3803. env.InsertDecl New TConstDecl.Create( "androidarmeabi",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And opt_arch="armeabi"),0 )
  3804. env.InsertDecl New TConstDecl.Create( "androidarmeabiv7a",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And opt_arch="armeabiv7a"),0 )
  3805. env.InsertDecl New TConstDecl.Create( "androidarm64v8a",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And opt_arch="arm64v8a"),0 )
  3806. ' raspberrypi - ARM only
  3807. env.InsertDecl New TConstDecl.Create( "raspberrypi",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="raspberrypi" And (opt_arch="arm" Or opt_arch="arm64")),0 )
  3808. env.InsertDecl New TConstDecl.Create( "raspberrypiARM",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="raspberrypi" And opt_arch="arm"),0 )
  3809. env.InsertDecl New TConstDecl.Create( "raspberrypiARM64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="raspberrypi" And opt_arch="arm64"),0 )
  3810. ' emscripten
  3811. env.InsertDecl New TConstDecl.Create( "emscripten",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="emscripten" ),0 )
  3812. env.InsertDecl New TConstDecl.Create( "emscriptenjs",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="emscripten" And opt_arch="js"),0 )
  3813. ' arch
  3814. env.InsertDecl New TConstDecl.Create( "ppc",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="ppc" ),0 )
  3815. env.InsertDecl New TConstDecl.Create( "x86",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="x86" ),0 )
  3816. env.InsertDecl New TConstDecl.Create( "x64",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="x64" ),0 )
  3817. env.InsertDecl New TConstDecl.Create( "arm",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="arm" Or opt_arch="armeabi" Or opt_arch="armeabiv7a" Or opt_arch="arm64v8a" ),0 )
  3818. env.InsertDecl New TConstDecl.Create( "armeabi",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="armeabi" ),0 )
  3819. env.InsertDecl New TConstDecl.Create( "armeabiv7a",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="armeabiv7a" ),0 )
  3820. env.InsertDecl New TConstDecl.Create( "arm64v8a",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="arm64v8a" ),0 )
  3821. env.InsertDecl New TConstDecl.Create( "js",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="js" ),0 )
  3822. env.InsertDecl New TConstDecl.Create( "armv7",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="armv7" ),0 )
  3823. env.InsertDecl New TConstDecl.Create( "arm64",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="arm64" ),0 )
  3824. env.InsertDecl New TConstDecl.Create( "ptr32",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="x86" Or opt_arch="ppc" Or opt_arch="armv7" Or opt_arch="arm" Or opt_arch="armeabi" Or opt_arch="armeabiv7a" ),0 )
  3825. env.InsertDecl New TConstDecl.Create( "ptr64",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="x64" Or opt_arch="arm64" Or opt_arch="arm64v8a" ),0 )
  3826. ' endian
  3827. env.InsertDecl New TConstDecl.Create( "bigendian",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="ppc" ),0 )
  3828. env.InsertDecl New TConstDecl.Create( "littleendian",New TIntType,New TConstExpr.Create( New TIntType,opt_arch<>"ppc" ),0 )
  3829. ' opengles target platform
  3830. env.InsertDecl New TConstDecl.Create( "opengles",New TIntType,New TConstExpr.Create( New TIntType, opt_platform="android" Or opt_platform="raspberrypi" Or opt_platform="emscripten" Or opt_platform="ios" Or (opt_platform="linux" And (opt_arch="arm" Or opt_arch="arm64"))),0 )
  3831. ' musl - linux only
  3832. env.InsertDecl New TConstDecl.Create( "musl",New TIntType,New TConstExpr.Create( New TIntType,(opt_musl And (opt_platform="linux" Or opt_platform="android" Or opt_platform="raspberrypi"))),0 )
  3833. ' nx / switch
  3834. env.InsertDecl New TConstDecl.Create( "nx",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="nx" ),0 )
  3835. env.InsertDecl New TConstDecl.Create( "nxarm64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="nx" And opt_arch="arm64"),0 )
  3836. ' new compiler
  3837. env.InsertDecl New TConstDecl.Create( "bmxng",New TIntType,New TConstExpr.Create( New TIntType, True ),0 )
  3838. ' user defines
  3839. If opt_userdefs Then
  3840. Local defs:String[] = opt_userdefs.ToLower().Split(",")
  3841. For Local def:String = EachIn defs
  3842. def = def.Trim()
  3843. If def Then
  3844. Local name:String = def
  3845. Local value:Int = 1
  3846. Local dp:String[] = def.Split("=")
  3847. If dp.length = 2 Then
  3848. name = dp[0].Trim()
  3849. value = Int(dp[1])
  3850. End If
  3851. env.InsertDecl New TConstDecl.Create( name,New TIntType,New TConstExpr.Create( New TIntType, value ),0 )
  3852. End If
  3853. Next
  3854. End If
  3855. ' env.InsertDecl New TConstDecl.Create( "LANG",TType.stringType,New TConstExpr.Create( TType.stringType,ENV_LANG ),0 )
  3856. ' env.InsertDecl New TConstDecl.Create( "TARGET",TType.stringType,New TConstExpr.Create( TType.stringType,ENV_TARGET ),0 )
  3857. ' env.InsertDecl New TConstDecl.Create( "CONFIG",TType.stringType,New TConstExpr.Create( TType.stringType,ENV_CONFIG ),0 )
  3858. PushEnv env
  3859. Local toker:TToker=New TToker.Create( "",source )
  3860. Local parser:TParser=New TParser.Create( toker,Null,True )
  3861. Local val:String
  3862. Try
  3863. Local expr:TExpr=parser.ParseExpr()
  3864. expr=expr.Semant()
  3865. If ty expr=expr.Cast( ty )
  3866. val=expr.Eval()
  3867. Catch error:String
  3868. val = "0"
  3869. End Try
  3870. PopEnv
  3871. Return val
  3872. End Function
  3873. Type TCastDets
  3874. Field name:String
  3875. Field retType:String
  3876. Field noGen:Int
  3877. Field args:String[0]
  3878. Field api:String
  3879. End Type