parser.bmx 128 KB

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