parser.bmx 109 KB

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