parser.bmx 128 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834
  1. ' Copyright (c) 2013-2024 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.cdets = cdets
  2286. TFunctionPtrType(ty).func.castTo = cdets.retType
  2287. If cdets.noGen Then
  2288. TFunctionPtrType(ty).func.noCastGen = True
  2289. End If
  2290. For Local i:Int = 0 Until cdets.args.length
  2291. If i < TFunctionPtrType(ty).func.argDecls.length Then
  2292. TFunctionPtrType(ty).func.argDecls[i].castTo = cdets.args[i]
  2293. End If
  2294. Next
  2295. End If
  2296. End If
  2297. EndIf
  2298. ' apply any function ptr metadata to decl
  2299. If TFunctionPtrType(ty) Then
  2300. If TFunctionPtrType(ty).func And TFunctionPtrType(ty).func.metadata Then
  2301. decl.metadata = TFunctionPtrType(ty).func.metadata
  2302. End If
  2303. End If
  2304. 'meta data for variables
  2305. Local meta:TMetaData = ParseMetaData()
  2306. If meta Then
  2307. decl.metadata = meta
  2308. End If
  2309. Return decl
  2310. End Method
  2311. Method ParseDecls:TList( toke$,attrs:Long, isField:Int = False )
  2312. If toke Parse toke
  2313. If isField Then
  2314. Repeat
  2315. If CParse("readonly") Then
  2316. If attrs & DECL_READ_ONLY
  2317. Err "Duplicate modifier 'ReadOnly'."
  2318. End If
  2319. attrs :| DECL_READ_ONLY
  2320. Else If CParse("staticarray") Then
  2321. If attrs & DECL_STATIC
  2322. Err "Duplicate modifier 'Static'."
  2323. End If
  2324. attrs :| DECL_STATIC
  2325. Else
  2326. Exit
  2327. End If
  2328. Forever
  2329. End If
  2330. Local decls:TList=New TList'<Decl>
  2331. Repeat
  2332. Local decl:TDecl=ParseDecl( toke,attrs )
  2333. decls.AddLast decl
  2334. If Not CParse(",") Return decls
  2335. Forever
  2336. End Method
  2337. Method ParseDeclStmts(initOnly:Int = False, attrs:Long = 0, mdecl:TModuleDecl = Null)
  2338. Local toke$=_toke
  2339. NextToke
  2340. Repeat
  2341. Local decl:TDecl=ParseDecl( toke,attrs )
  2342. If Not (attrs & DECL_EXTERN) Then
  2343. _block.AddStmt New TDeclStmt.Create( decl )
  2344. End If
  2345. ' reset the decl scope, adding decl to the block decl list.
  2346. ' this improves scope visibilty - for decls such as embedded functions
  2347. If TConstDecl(decl) Or TGlobalDecl(decl) Then
  2348. If mdecl Then
  2349. mdecl.InsertDecl decl
  2350. End If
  2351. If Not (attrs & DECL_EXTERN) Then
  2352. decl.scope = Null
  2353. _block.InsertDecl(decl)
  2354. End If
  2355. If TGlobalDecl(decl) Then
  2356. If initOnly Then
  2357. decl.attrs :| DECL_INITONLY
  2358. TGlobalDecl(decl).mscope = _module
  2359. Else
  2360. TGlobalDecl(decl).funcGlobal = True
  2361. End If
  2362. End If
  2363. End If
  2364. Until Not CParse(",")
  2365. End Method
  2366. Method ParseLoopLabelDecl:TLoopLabelDecl()
  2367. NextToke
  2368. Local id:String = ParseIdent()
  2369. Return New TLoopLabelDecl.Create(id, 0)
  2370. End Method
  2371. 'handle end-of-line "dot dot return"-line connector
  2372. '-> skips EOL tokens
  2373. Method HandleDotsLineConnector(eatToke:Int = False)
  2374. Local tok:TToker = New TToker.Copy(_toker)
  2375. Local t:String = tok.NextToke()
  2376. Local count:Int = tok.SkipSpace()
  2377. For Local i:Int = 0 Until count
  2378. NextToke
  2379. Next
  2380. t = tok._toke
  2381. If t = "~r" Then
  2382. t = tok.NextToke()
  2383. If t = "~n" Then
  2384. NextToke
  2385. NextToke
  2386. Else
  2387. NextToke
  2388. End If
  2389. Else
  2390. If t = "~n" Then
  2391. NextToke
  2392. End If
  2393. End If
  2394. If eatToke And Not count Then
  2395. NextToke
  2396. End If
  2397. End Method
  2398. 'should return a specific "metadata object" ?
  2399. ' metadata is in the form : {key key=value key="value"}
  2400. Method ParseMetaData:TMetadata()
  2401. If Not CParse( "{" ) Then
  2402. Return Null
  2403. End If
  2404. Local meta:TMetadata = New TMetadata
  2405. SkipEols
  2406. Repeat
  2407. 'reached end of meta data declaration
  2408. If _toke="}" Then Exit
  2409. If meta.metadataString Then
  2410. meta.metadataString :+ " "
  2411. End If
  2412. Select _tokeType
  2413. Case TOKE_INTLIT
  2414. Err "Expecting '}' but encountered integer literal"
  2415. Case TOKE_FLOATLIT
  2416. Err "Expecting '}' but encountered floating point literal"
  2417. Case TOKE_STRINGLIT
  2418. Err "Expecting '}' but encountered string literal"
  2419. Case TOKE_SYMBOL
  2420. Err "Expecting '}' but encountered " + _toke
  2421. End Select
  2422. 'append current token to metaDataString
  2423. Local key:String = _toke
  2424. meta.metadataString :+ key
  2425. 'read next token
  2426. NextToke()
  2427. Local value:String
  2428. ' got a value
  2429. If CParse("=") Then
  2430. If _tokeType = TOKE_IDENT Then
  2431. Err "Meta data must be literal constant"
  2432. End If
  2433. value = _toke
  2434. meta.metadataString :+ "=" + value
  2435. 'read next token
  2436. NextToke()
  2437. Else
  2438. value = "1"
  2439. meta.metadataString :+ "=1"
  2440. End If
  2441. meta.InsertMeta(key.ToLower(), value)
  2442. Forever
  2443. 'continue to next token
  2444. NextToke()
  2445. 'parse this into something
  2446. Return meta
  2447. End Method
  2448. Method ParseFuncDecl:TFuncDecl( toke$, attrs:Long, parent:TScopeDecl = Null )
  2449. SetErr
  2450. If toke Parse toke
  2451. Local id$
  2452. Local ty:TType
  2453. Local meth:Int = attrs & FUNC_METHOD
  2454. Local meta:TMetadata
  2455. Local noMangle:Int
  2456. Local exported:Int
  2457. Local inInterface:Int = attrs & DECL_ABSTRACT
  2458. Local classDecl:TClassDecl = TClassDecl(parent)
  2459. If attrs & FUNC_METHOD
  2460. If _toke="new"
  2461. If attrs & DECL_EXTERN
  2462. Err "Extern classes cannot have constructors"
  2463. EndIf
  2464. id="New"
  2465. NextToke
  2466. attrs:|FUNC_CTOR
  2467. attrs:&~FUNC_METHOD
  2468. ty=ParseDeclType()
  2469. Else If _toke="operator" Then
  2470. attrs:|FUNC_OPERATOR
  2471. NextToke
  2472. Local t:String = _toke.ToLower()
  2473. NextToke
  2474. Select t
  2475. Case "*","/","+","-","&","|","~~","^"
  2476. id = t
  2477. Case ":*",":/",":+",":-",":&",":|",":~~",":^"
  2478. id = t
  2479. Case "<",">"',"="',"<=",">=","=","<>"
  2480. If CParse("=") Then
  2481. t :+ "="
  2482. Else If t = "<" And CParse(">") Then
  2483. t :+ ">"
  2484. End If
  2485. id = t
  2486. Case "="
  2487. id = t
  2488. Case "mod", "shl", "shr"
  2489. id = t
  2490. Case ":mod", ":shl", ":shr"
  2491. id = t
  2492. Case "[]"
  2493. If CParse("=") Then t :+ "="
  2494. id = t
  2495. Default
  2496. DoErr "Operator must be one of: * / + - & | ~~ :* :/ :+ :- :& :| :~~ < > <= >= = <> mod shl shr :mod :shl :shr [] []="
  2497. End Select
  2498. ty=ParseDeclType()
  2499. Else
  2500. id=ParseIdent()
  2501. ty=ParseDeclType(attrs & DECL_API_STDCALL)
  2502. If ty._flags & (TType.T_CHAR_PTR | TType.T_SHORT_PTR) Then
  2503. DoErr "Illegal function return type"
  2504. End If
  2505. ' Delete() return type should always be Void
  2506. If id.ToLower() = "delete" Then
  2507. attrs:|FUNC_DTOR
  2508. If TIntType(ty) Then
  2509. ty = New TVoidType
  2510. End If
  2511. End If
  2512. ' TODO: make sure Delete cannot be declared with parameters?
  2513. EndIf
  2514. Else
  2515. 'If Not (attrs & FUNC_PTR) Then
  2516. id=ParseIdent()
  2517. ty=ParseDeclType(attrs & DECL_API_STDCALL)
  2518. ' can only return "$z" and "$w" from an extern function.
  2519. If ty._flags & (TType.T_CHAR_PTR | TType.T_SHORT_PTR) And Not (attrs & DECL_EXTERN) Then
  2520. DoErr "Illegal function return type"
  2521. End If
  2522. 'End If
  2523. EndIf
  2524. ' every branch in that nested If block up there contains the line "ty=ParseDeclType()";
  2525. ' this already consumed all sets of parentheses and brackets belonging to this function declaration
  2526. ' so we will now extract our actual return type and args from the result
  2527. Local args:TArgDecl[]
  2528. If Not TFunctionPtrType(ty) Then
  2529. DoErr "Expecting function type"
  2530. Else
  2531. Local fdecl:TFuncDecl = TFunctionPtrType(ty).func
  2532. ty = fdecl.retTypeExpr
  2533. args = fdecl.argDecls
  2534. attrs :| (fdecl.attrs & DECL_API_FLAGS)
  2535. End If
  2536. Local declaredAttrs:Long
  2537. While True
  2538. If CParse( "nodebug" ) Then
  2539. If declaredAttrs & DECL_NODEBUG Then Err "Duplicate modifier 'NoDebug'"
  2540. declaredAttrs :| DECL_NODEBUG
  2541. Continue
  2542. End If
  2543. If CParse( "final" )
  2544. If Not classDecl Then
  2545. Err "Final cannot be used with global functions"
  2546. End If
  2547. If inInterface Then
  2548. If attrs & FUNC_METHOD Then
  2549. Err "Final methods cannot appear in interfaces"
  2550. Else
  2551. Err "Final functions cannot appear in interfaces"
  2552. End If
  2553. End If
  2554. If declaredAttrs & DECL_FINAL Then Err "Duplicate modifier 'Final'"
  2555. declaredAttrs :| DECL_FINAL
  2556. Continue
  2557. End If
  2558. If CParse( "abstract" )
  2559. If Not classDecl Then
  2560. Err "Abstract cannot be used with global functions"
  2561. End If
  2562. If classDecl And classDecl.attrs & DECL_FINAL Then
  2563. Err "Abstract methods cannot appear in final types"
  2564. End If
  2565. If inInterface Then
  2566. If attrs & FUNC_METHOD Then
  2567. Err "Abstract cannot be used in interfaces (interface methods are automatically abstract)"
  2568. Else
  2569. Err "Abstract cannot be used in interfaces (interface functions are automatically abstract)"
  2570. End If
  2571. End If
  2572. If declaredAttrs & DECL_ABSTRACT Then Err "Duplicate modifier 'Abstract'"
  2573. declaredAttrs :| DECL_ABSTRACT
  2574. Continue
  2575. End If
  2576. If CParse("override") Then
  2577. If Not classDecl Then
  2578. Err "Override cannot be used with global functions"
  2579. End If
  2580. If declaredAttrs & DECL_OVERRIDE Then Err "Duplicate modifier 'Override'"
  2581. declaredAttrs :| DECL_OVERRIDE
  2582. Continue
  2583. End If
  2584. If CParse("inline") And Not opt_debug Then
  2585. If classDecl Then
  2586. Err "Inline can only be used with global functions"
  2587. End If
  2588. If declaredAttrs & DECL_INLINE Then Err "Duplicate modifier 'Inline'"
  2589. declaredAttrs :| DECL_INLINE
  2590. Continue
  2591. End If
  2592. Exit
  2593. Wend
  2594. attrs :| declaredAttrs
  2595. 'meta data for functions/methods
  2596. meta = ParseMetaData()
  2597. If meta And meta.HasMeta("nomangle") Then
  2598. If attrs & FUNC_METHOD Then
  2599. Err "Only functions can specify NoMangle"
  2600. Else
  2601. noMangle = True
  2602. End If
  2603. End If
  2604. If CParse("export") Then
  2605. attrs :| DECL_EXPORT
  2606. If attrs & FUNC_METHOD Then
  2607. Err "Only functions can specify Export"
  2608. Else
  2609. exported = True
  2610. End If
  2611. End If
  2612. attrs :| ParseCallConvention(attrs & DECL_API_STDCALL)
  2613. If CParse( "nodebug" ) Then
  2614. attrs :| DECL_NODEBUG
  2615. End If
  2616. Local funcDecl:TFuncDecl
  2617. If attrs & FUNC_CTOR Then
  2618. funcDecl=New TNewDecl.CreateF( id,ty,args,attrs )
  2619. TNewDecl(funcDecl).cdecl = classdecl
  2620. Else
  2621. 'If fdecl Then
  2622. ' funcDecl = fdecl
  2623. ' funcDecl.ident = id
  2624. 'Else
  2625. funcDecl=New TFuncDecl.CreateF( id,ty,args,attrs )
  2626. 'End If
  2627. funcDecl.noMangle = noMangle
  2628. funcDecl.exported = exported
  2629. End If
  2630. If meta Then
  2631. funcDecl.metadata = meta
  2632. End If
  2633. If funcDecl.IsExtern() Or (attrs & FUNC_PTR)
  2634. funcDecl.munged=funcDecl.ident
  2635. ' a normal function pointer definition *probably* can't be defined with a munged name?
  2636. ' If there is an equals here, one can assume it is for an initialisation...
  2637. 'If (Not (attrs & FUNC_PTR)) Or (attrs & FUNC_PTR And Not (attrs & DECL_ARG)) Then
  2638. Local cdets:TCastDets
  2639. If Not (attrs & FUNC_PTR) Then
  2640. If CParse( "=" )
  2641. Local munged:String = ParseStringLit()
  2642. If munged.Find("(") > 0 Then
  2643. cdets = ParseExternCast(munged, True)
  2644. If cdets Then
  2645. funcDecl.munged = cdets.name
  2646. End If
  2647. Else
  2648. funcDecl.munged = munged
  2649. End If
  2650. End If
  2651. 'Array $resize hack!
  2652. 'If funcDecl.munged="$resize"
  2653. ' funcDecl.retTypeExpr=TType.emptyArrayType
  2654. 'EndIf
  2655. EndIf
  2656. If funcDecl.munged Then
  2657. ' look up extern cast list
  2658. If Not cdets Then
  2659. cdets = TCastDets(_externCasts.ValueForKey(funcDecl.munged))
  2660. End If
  2661. If cdets Then
  2662. funcDecl.castTo = cdets.retType
  2663. If cdets.noGen Then
  2664. funcDecl.noCastGen = True
  2665. End If
  2666. For Local i:Int = 0 Until cdets.args.length
  2667. If i < funcDecl.argDecls.length Then
  2668. funcDecl.argDecls[i].castTo = cdets.args[i]
  2669. End If
  2670. Next
  2671. End If
  2672. End If
  2673. Return funcDecl
  2674. EndIf
  2675. If funcDecl.IsAbstract() Return funcDecl
  2676. 'Ok, only first statement of a constructor can call super constructor - not pretty, should be in semant.
  2677. If attrs & FUNC_CTOR
  2678. SkipEols
  2679. If CParse( "super" )
  2680. Parse "."
  2681. If _toke="new"
  2682. Local id$="New"
  2683. NextToke
  2684. 'funcDecl.superCtor=New TInvokeSuperExpr.Create( id,ParseArgs( True ) )
  2685. 'funcDecl.AddStmt New TExprStmt.Create( funcDecl.superCtor )
  2686. funcDecl.AddStmt New TExprStmt.Create( New TNewExpr.Create(ParseArgs(True), True))
  2687. Else
  2688. Local id$=ParseIdent()
  2689. funcDecl.AddStmt New TExprStmt.Create( New TInvokeSuperExpr.Create( id,ParseArgs( True ) ) )
  2690. EndIf
  2691. Else
  2692. 'Invoke super default ctor
  2693. 'funcDecl.superCtor=New InvokeSuperExpr( "new",[] )
  2694. 'funcDecl.AddStmt New TExprStmt( funcDecl.superCtor )
  2695. EndIf
  2696. EndIf
  2697. PushBlock funcDecl
  2698. While (Not meth And _toke.ToLower()<>"endfunction") Or (meth And _toke.ToLower()<>"endmethod")
  2699. If CParse( "end" )
  2700. If (Not meth And CParse("function")) Or (meth And CParse("method"))
  2701. Exit
  2702. End If
  2703. ' handle "end" statement
  2704. ParseEndStmt(False)
  2705. EndIf
  2706. ParseStmt
  2707. Wend
  2708. PopBlock
  2709. NextToke
  2710. 'If toke CParse toke
  2711. Return funcDecl
  2712. End Method
  2713. Method ParseCallConvention:Long(callConvention:Long = DECL_API_DEFAULT)
  2714. If _tokeType <> TOKE_STRINGLIT Then
  2715. Return callConvention
  2716. End If
  2717. Local api:String = ParseStringLit().ToLower()
  2718. If api = "os" Then
  2719. Select opt_platform
  2720. Case "macos", "osx", "ios"
  2721. api = "macos"
  2722. Case "linux", "android", "raspberrypi", "haiku"
  2723. api = "linux"
  2724. Case "win32"
  2725. api = "win32"
  2726. Case "nx"
  2727. api = "nx"
  2728. End Select
  2729. End If
  2730. Select api
  2731. Case "c", "blitz", "macos", "linux", "nx"
  2732. Return DECL_API_CDECL
  2733. Case "win32"
  2734. ' only if we are compiling for win32
  2735. If opt_platform = "win32"
  2736. Return DECL_API_STDCALL
  2737. Else
  2738. Return DECL_API_CDECL
  2739. End If
  2740. End Select
  2741. Err "Unrecognized calling convention '" + api+ "'"
  2742. End Method
  2743. Method ParseFuncParamDecl:TArgDecl[]()
  2744. Local args:TArgDecl[]
  2745. Parse "("
  2746. SkipEols
  2747. If _toke<>")"
  2748. Local nargs:Int
  2749. Repeat
  2750. Local attrs:Long
  2751. If CParse("staticarray") Then
  2752. attrs :| DECL_STATIC
  2753. End If
  2754. Local argId$=ParseIdent()
  2755. Local ty:TType=ParseDeclType(attrs)
  2756. Local init:TExpr
  2757. ' var argument?
  2758. If CParse("var") Then
  2759. If attrs & DECL_STATIC Then
  2760. Err "Unexpected 'Var' for static array argument"
  2761. End If
  2762. ty = TType.MapToVarType(ty)
  2763. Else If CParse( "=" )
  2764. init=ParseExpr()
  2765. Else
  2766. If CParse( "[" ) And (attrs & DECL_STATIC) Then
  2767. init = ParseExpr()
  2768. Parse "]"
  2769. ty=New TArrayType.Create( ty,1,, attrs & DECL_STATIC > 0 )
  2770. End If
  2771. End If
  2772. Local arg:TArgDecl=New TArgDecl.Create( argId,ty,init,attrs )
  2773. If args.Length=nargs args=args + New TArgDecl[10]
  2774. args[nargs]=arg
  2775. nargs:+1
  2776. If _toke=")" Exit
  2777. Parse ","
  2778. Forever
  2779. args=args[..nargs]
  2780. EndIf
  2781. Parse ")"
  2782. Return args
  2783. End Method
  2784. Method ParseEnumDecl:TEnumDecl( toke:String )
  2785. SetErr
  2786. If toke Parse toke
  2787. Local id:String = ParseIdent()
  2788. Local ty:TType = ParseConstNumberType()
  2789. If Not ty Then
  2790. ty = New TIntType
  2791. End If
  2792. Local isFlags:Int = 0
  2793. Local values:TEnumValueDecl[0]
  2794. If CParse("flags")
  2795. isFlags = True
  2796. End If
  2797. Local decl:TEnumDecl = New TEnumDecl.Create(id, ty, isFlags, values)
  2798. Local nValues:Int
  2799. Repeat
  2800. SkipEols
  2801. If CParse("end") Then
  2802. Parse("enum")
  2803. Exit
  2804. End If
  2805. If CParse("endenum") Then
  2806. Exit
  2807. End If
  2808. Local valId:String = ParseIdent()
  2809. Local value:TExpr
  2810. If CParse( "=" ) Then
  2811. value = ParseExpr()
  2812. End If
  2813. Local v:TEnumValueDecl = New TEnumValueDecl.Create(valId, nValues, value)
  2814. If decl.values.Length = nValues Then
  2815. decl.values = decl.values + New TEnumValueDecl[10]
  2816. End If
  2817. decl.values[nValues] = v
  2818. nValues :+ 1
  2819. CParse(",")
  2820. Forever
  2821. decl.values = decl.values[..nValues]
  2822. Return decl
  2823. End Method
  2824. Method ParseClassDecl:TClassDecl( toke$,attrs:Long, templateDets:TTemplateDets = Null )
  2825. SetErr
  2826. Local calculatedStartLine:Int = _toker.Line()
  2827. Local startLine:Int = _toker._line
  2828. If toke Parse toke
  2829. Local id$=ParseIdent()
  2830. Local args:TList = New TList
  2831. Local superTy:TIdentType
  2832. Local imps:TIdentType[]
  2833. Local meta:TMetadata
  2834. 'If (attrs & CLASS_INTERFACE) And (attrs & DECL_EXTERN)
  2835. ' Err "Interfaces cannot be extern."
  2836. 'EndIf
  2837. If CParse( "<" )
  2838. If attrs & DECL_EXTERN
  2839. Err "Extern classes cannot be generic."
  2840. EndIf
  2841. 'If attrs & CLASS_INTERFACE
  2842. ' Err "Interfaces cannot be generic."
  2843. 'EndIf
  2844. 'If attrs & CLASS_TEMPLATEARG
  2845. ' Err "Class parameters cannot be generic."
  2846. 'EndIf
  2847. Local nargs:Int
  2848. Repeat
  2849. 'Local decl:TClassDecl=ParseClassDecl( "",CLASS_TEMPLATEARG )
  2850. 'If args.Length=nargs args=args + New TClassDecl[10]
  2851. 'args[nargs]=decl
  2852. 'nargs:+1
  2853. Local arg:TTemplateArg = New TTemplateArg
  2854. arg.ident = ParseIdent()
  2855. ' If CParse("extends") Then
  2856. ' arg.superTy = ParseIdentType()
  2857. ' End If
  2858. args.AddLast arg
  2859. Until Not CParse(",")
  2860. 'args=args[..nargs]
  2861. Parse ">"
  2862. If CParse( "where" ) Then
  2863. 'DebugStop
  2864. Repeat
  2865. Local argIdent:String = ParseIdent()
  2866. Parse("extends")
  2867. Local found:Int
  2868. For Local arg:TTemplateArg = EachIn args
  2869. If arg.ident = argIdent Then
  2870. Repeat
  2871. arg.ExtendsType(ParseIdentType())
  2872. Until Not CParse("and")
  2873. found = True
  2874. Exit
  2875. EndIf
  2876. Next
  2877. If Not found Then
  2878. Err "Use of undeclared type '" + argIdent + "'."
  2879. End If
  2880. Until Not CParse(",")
  2881. End If
  2882. EndIf
  2883. If CParse( "extends" )
  2884. 'If attrs & CLASS_TEMPLATEARG
  2885. ' Err "Extends cannot be used with class parameters."
  2886. 'EndIf
  2887. ' If CParse( "null" )
  2888. '
  2889. If attrs & CLASS_STRUCT
  2890. Err "Structs cannot be extended"
  2891. EndIf
  2892. '
  2893. ' If Not (attrs & DECL_EXTERN)
  2894. ' Err "Only extern objects can extend null."
  2895. ' EndIf
  2896. '
  2897. ' superTy=Null
  2898. '
  2899. ' Else
  2900. If attrs & CLASS_INTERFACE And Not (attrs & DECL_EXTERN)
  2901. Local nimps:Int
  2902. Repeat
  2903. If imps.Length=nimps imps=imps + New TIdentType[10]
  2904. imps[nimps]=ParseIdentType()
  2905. nimps:+1
  2906. Until Not CParse(",")
  2907. imps=imps[..nimps]
  2908. superTy=New TIdentType.Create( "brl.classes.object" )
  2909. Else
  2910. superTy=ParseIdentType()
  2911. EndIf
  2912. Else
  2913. If Not (attrs & DECL_EXTERN) And Not (attrs & CLASS_STRUCT) Then
  2914. superTy=New TIdentType.Create( "brl.classes.object" )
  2915. End If
  2916. EndIf
  2917. If CParse( "implements" )
  2918. If attrs & CLASS_STRUCT
  2919. Err "Implements cannot be used with Structs"
  2920. EndIf
  2921. 'If attrs & DECL_EXTERN
  2922. ' Err "Implements cannot be used with external classes."
  2923. 'EndIf
  2924. If attrs & CLASS_INTERFACE
  2925. Err "Implements cannot be used with interfaces."
  2926. EndIf
  2927. 'If attrs & CLASS_TEMPLATEARG
  2928. ' Err "Implements cannot be used with class parameters."
  2929. 'EndIf
  2930. Local nimps:Int
  2931. Repeat
  2932. If imps.Length=nimps imps=imps + New TIdentType[10]
  2933. imps[nimps]=ParseIdentType()
  2934. nimps:+1
  2935. Until Not CParse(",")
  2936. imps=imps[..nimps]
  2937. EndIf
  2938. Repeat
  2939. If CParse( "final" )
  2940. If attrs & CLASS_INTERFACE
  2941. Err "Final cannot be used with interfaces."
  2942. End If
  2943. If attrs & CLASS_STRUCT
  2944. Err "Final cannot be used with structs."
  2945. End If
  2946. If attrs & DECL_FINAL
  2947. Err "Duplicate modifier 'Final'."
  2948. End If
  2949. If attrs & DECL_ABSTRACT
  2950. Err "Classes cannot be both final and abstract."
  2951. End If
  2952. attrs:|DECL_FINAL
  2953. Else If CParse( "abstract" )
  2954. If attrs & CLASS_INTERFACE
  2955. Err "Abstract cannot be used with interfaces."
  2956. EndIf
  2957. If attrs & CLASS_STRUCT
  2958. Err "Abstract cannot be used with structs."
  2959. EndIf
  2960. If attrs & DECL_ABSTRACT
  2961. Err "Duplicate modifier 'Abstract'."
  2962. End If
  2963. If attrs & DECL_FINAL
  2964. Err "Types cannot be both final and abstract."
  2965. End If
  2966. attrs:|DECL_ABSTRACT
  2967. Else
  2968. Exit
  2969. EndIf
  2970. Forever
  2971. 'check for metadata
  2972. meta = ParseMetaData()
  2973. Local sargs:TTemplateArg[] = New TTemplateArg[args.Count()]
  2974. Local i:Int = 0
  2975. For Local arg:TTemplateArg = EachIn args
  2976. sargs[i] = arg
  2977. i :+ 1
  2978. Next
  2979. Local classDecl:TClassDecl=New TClassDecl.Create( id,sargs,superTy,imps,attrs )
  2980. If meta Then
  2981. If attrs & CLASS_STRUCT
  2982. Err "Structs cannot store metadata."
  2983. EndIf
  2984. classDecl.metadata = meta
  2985. End If
  2986. If classDecl.IsExtern()
  2987. classDecl.munged=classDecl.ident
  2988. If CParse( "=" ) classDecl.munged=ParseStringLit()
  2989. EndIf
  2990. 'If classDecl.IsTemplateArg() Return classDecl
  2991. Local decl_attrs:Long=(attrs & DECL_EXTERN) | (attrs & DECL_NODEBUG) | (attrs & DECL_API_STDCALL)
  2992. Repeat
  2993. Local method_attrs:Long=decl_attrs|FUNC_METHOD | (attrs & DECL_NODEBUG)
  2994. Local abst_attrs:Long = 0
  2995. If attrs & CLASS_INTERFACE abst_attrs:|DECL_ABSTRACT
  2996. SkipEols
  2997. Select _toke
  2998. Case "end"
  2999. NextToke
  3000. Exit
  3001. Case "endtype"
  3002. If attrs & CLASS_INTERFACE Then
  3003. Err "Syntax error - expecting End Interface, not 'EndType'"
  3004. End If
  3005. If attrs & CLASS_STRUCT Then
  3006. Err "Syntax error - expecting End Struct, not 'EndType'"
  3007. End If
  3008. toke = Null
  3009. NextToke
  3010. Exit
  3011. Case "endstruct"
  3012. If attrs & CLASS_INTERFACE Then
  3013. Err "Syntax error - expecting End Interface, not 'EndStruct'"
  3014. End If
  3015. If Not (attrs & CLASS_STRUCT) Then
  3016. Err "Syntax error - expecting End Type, not 'EndStruct'"
  3017. End If
  3018. toke = Null
  3019. NextToke
  3020. Exit
  3021. Case "endinterface"
  3022. If Not (attrs & CLASS_INTERFACE) And Not (attrs & CLASS_STRUCT) Then
  3023. Err "Syntax error - expecting End Type, not 'EndInterface'"
  3024. End If
  3025. If Not (attrs & CLASS_INTERFACE) And (attrs & CLASS_STRUCT) Then
  3026. Err "Syntax error - expecting End Struct, not 'EndInterface'"
  3027. End If
  3028. toke = Null
  3029. NextToke
  3030. Exit
  3031. Case "private"
  3032. If attrs & CLASS_INTERFACE Then
  3033. Err "Private cannot be used with interfaces."
  3034. End If
  3035. NextToke
  3036. decl_attrs=decl_attrs | DECL_PRIVATE
  3037. decl_attrs:& ~DECL_PROTECTED
  3038. Case "protected"
  3039. If attrs & CLASS_INTERFACE Then
  3040. Err "Protected cannot be used with interfaces."
  3041. End If
  3042. NextToke
  3043. decl_attrs=decl_attrs | DECL_PROTECTED
  3044. decl_attrs:& ~DECL_PRIVATE
  3045. Case "public"
  3046. NextToke
  3047. decl_attrs:& ~DECL_PRIVATE
  3048. decl_attrs:& ~DECL_PROTECTED
  3049. Case "const","global","field","threadedglobal"
  3050. Local extra_attrs:Long
  3051. If _toke = "threadedglobal" Then
  3052. extra_attrs = DECL_THREADED
  3053. End If
  3054. If attrs & DECL_EXTERN Then
  3055. If (attrs & CLASS_INTERFACE) Then
  3056. Err "Extern Interfaces can only contain methods."
  3057. End If
  3058. If Not (attrs & CLASS_STRUCT) Then
  3059. Err "Extern Types can only contain methods."
  3060. End If
  3061. End If
  3062. If (attrs & CLASS_INTERFACE) And _toke<>"const"
  3063. Err "Interfaces can only contain constants and methods."
  3064. EndIf
  3065. If (attrs & CLASS_STRUCT) And _toke<>"field" And _toke<>"global" And _toke<>"threadedglobal"
  3066. Err "Structs can only contain fields."
  3067. EndIf
  3068. classDecl.InsertDecls ParseDecls( _toke,decl_attrs | extra_attrs, _toke = "field")
  3069. Case "method"
  3070. If (attrs & CLASS_STRUCT) And (attrs & DECL_EXTERN) Then
  3071. Err "Structs can only contain fields."
  3072. EndIf
  3073. Local decl:TFuncDecl=ParseFuncDecl( _toke,method_attrs | abst_attrs,classDecl )
  3074. classDecl.InsertDecl decl
  3075. Case "function"
  3076. 'If (attrs & CLASS_INTERFACE)
  3077. ' Err "Interfaces can only contain constants and methods."
  3078. 'EndIf
  3079. If attrs & CLASS_STRUCT Then
  3080. If (attrs & DECL_EXTERN) Then
  3081. Err "Structs can only contain fields."
  3082. End If
  3083. EndIf
  3084. If attrs & DECL_EXTERN Then
  3085. Err "Extern Types can only contain methods."
  3086. End If
  3087. Local decl:TFuncDecl=ParseFuncDecl( _toke,decl_attrs | abst_attrs,classDecl )
  3088. classDecl.InsertDecl decl
  3089. Case "type"
  3090. If templateDets Then
  3091. Local cdecl:TClassDecl = ParseClassDecl( _toke,DECL_NESTED, templateDets)
  3092. cdecl = cdecl.GenClassInstance(templateDets.instArgs, False, Null, templateDets)
  3093. classDecl.InsertDecl cdecl, True
  3094. Else
  3095. classDecl.InsertDecl ParseClassDecl( _toke,DECL_NESTED)
  3096. End If
  3097. Default
  3098. Err "Syntax error - expecting class member declaration, not '" + _toke + "'"
  3099. End Select
  3100. Forever
  3101. If Not args.IsEmpty() Then
  3102. Local endline:Int = _toker._line
  3103. classDecl.templateSource = New TTemplateRecord.Create(calculatedStartLine - 1, _toker._path, _toker.Join(startLine, endLine, "~n"))
  3104. End If
  3105. If toke Parse toke
  3106. Return classDecl
  3107. End Method
  3108. Method ParseNativeStmt()
  3109. If Not _toke.StartsWith("'!") Then
  3110. Err "Syntax error - expecting '!"
  3111. End If
  3112. Local raw:String = _toke[2..]
  3113. _block.AddStmt New TNativeStmt.Create( raw )
  3114. NextToke
  3115. End Method
  3116. Method ParsePragmaStmt()
  3117. Local pragma:String = _toke
  3118. If pragma.StartsWith("'") Then
  3119. pragma = pragma[1..].Trim()
  3120. If Not pragma.StartsWith("@bmk") Then
  3121. Err "Syntax error - expecting @bmk pragma"
  3122. End If
  3123. pragma = pragma[4..].Trim()
  3124. _module.pragmas.AddLast(pragma)
  3125. End If
  3126. NextToke
  3127. End Method
  3128. Method ParseModuleDecl:String( toke$,attrs:Long )
  3129. NextToke
  3130. ' namespace . module
  3131. Return ParseModPath().ToLower()
  3132. End Method
  3133. Method ParseModPath$()
  3134. Local path$=ParseIdent()
  3135. While CParse( "." )
  3136. path:+"."+ParseIdent()
  3137. Wend
  3138. Return path
  3139. End Method
  3140. Method ExtractModIdent$( modpath$ )
  3141. Local i:Int=modpath.FindLast( "." )
  3142. If i<>-1 Return modpath[i+1..]
  3143. Return modpath
  3144. End Method
  3145. Method ImportFile( filepath$ )
  3146. If filepath.Endswith(".bmx") Then
  3147. filepath = ActualPath(filepath)
  3148. Local origPath:String = RealPath(filepath)
  3149. Local path:String = OutputFilePath(origPath, FileMung(), "i")
  3150. If FileType( origPath )<>FILETYPE_FILE
  3151. Err "File '"+ origPath +"' not found."
  3152. EndIf
  3153. If FileType( path )<>FILETYPE_FILE
  3154. Err "File '"+ path +"' not found."
  3155. EndIf
  3156. If _module.imported.Contains( path ) Return
  3157. Local modpath:String
  3158. If opt_buildtype = BUILDTYPE_MODULE Then
  3159. Local dir:String = ExtractDir(origPath).ToLower()
  3160. dir = dir[dir.findLast("/") + 1..]
  3161. If dir.EndsWith(".mod") Then
  3162. dir = ""
  3163. Else
  3164. dir :+ "_"
  3165. End If
  3166. Local file:String = StripDir(origPath).ToLower()
  3167. modpath = opt_modulename + "_" + dir + StripExt(file)
  3168. Else
  3169. modpath = StripExt(filepath)
  3170. End If
  3171. 'sanitize the path, remove non-allowed chars
  3172. modpath = TStringHelper.Sanitize(modpath.ToLower())
  3173. ' try to import interface
  3174. Local par:TIParser = New TIParser
  3175. If par.ParseModuleImport(_module, modpath, origPath, path, , , filepath, True) Return
  3176. Else If filepath.startswith("-") Then
  3177. If Not _app.fileimports.Contains(filepath) Then
  3178. _app.fileimports.AddLast filepath
  3179. End If
  3180. Else
  3181. If filepath.EndsWith(".h") Or filepath.EndsWith(".hpp") Or filepath.EndsWith(".hxx") Then
  3182. If filepath.Find("*") = -1 Then
  3183. _app.headers.AddLast filepath
  3184. End If
  3185. Else
  3186. Local path:String = ActualPath(RealPath(filepath))
  3187. If FileType( path )<>FILETYPE_FILE
  3188. Err "File '"+ path +"' not found."
  3189. End If
  3190. End If
  3191. End If
  3192. End Method
  3193. Method ImportAllModules(attrs:Long)
  3194. ' get all brl and pub modules
  3195. Local mods:TList = EnumModules("brl")
  3196. mods = EnumModules("pub", mods)
  3197. For Local m:String = EachIn mods
  3198. ImportModule(m, attrs)
  3199. Next
  3200. End Method
  3201. Method ImportModule( modpath$,attrs:Long )
  3202. ' SetErr
  3203. modpath = modpath.ToLower()
  3204. Local basepath:String = ModulePath(modpath)
  3205. If _module.imported.Contains( basepath ) Return
  3206. ' try to import interface
  3207. Local par:TIParser = New TIParser
  3208. If par.ParseModuleImport(_module, modpath, basepath, , , attrs) Return
  3209. 'DebugStop
  3210. 'Local mdecl:TDecl=_app.imported.ValueForKey( basepath )
  3211. 'If Not mdecl
  3212. ' mdecl=ParseModule( filepath,_app )
  3213. 'EndIf
  3214. '_module.imported.Insert mdecl.filepath,mdecl
  3215. 'If Not (attrs & DECL_PRIVATE) _module.pubImported.Insert mdecl.filepath,mdecl
  3216. '_module.InsertDecl New AliasDecl( mdecl.ident,mdecl,attrs )
  3217. 'End Rem
  3218. End Method
  3219. Method ValidateModIdent( id$ )
  3220. If id.Length
  3221. If IsAlpha( id[0] ) Or id[0]="_"[0]
  3222. Local err:Int
  3223. For Local i:Int=1 Until id.Length
  3224. If IsAlpha( id[i] ) Or IsDigit( id[i] ) Or id[i]="_"[0] Continue
  3225. err=1
  3226. Exit
  3227. Next
  3228. If Not err Return
  3229. EndIf
  3230. EndIf
  3231. Err "Invalid module identifier '"+id+"'."
  3232. End Method
  3233. Method MungAppDecl(app:TAppDecl)
  3234. If opt_buildtype = BUILDTYPE_MODULE And opt_ismain Then
  3235. app.munged = MungModuleName(opt_modulename)
  3236. Else If opt_buildtype = BUILDTYPE_MODULE Then
  3237. Local dir:String = ExtractDir(opt_filepath).ToLower()
  3238. dir = dir[dir.findLast("/") + 1..]
  3239. If dir.EndsWith(".mod") Then
  3240. dir = ""
  3241. Else
  3242. dir :+ "_"
  3243. End If
  3244. app.munged = "_bb_" + opt_modulename + "_" + dir + StripExt(StripDir(opt_filepath).ToLower())
  3245. Else
  3246. ' main application file?
  3247. If opt_apptype Then
  3248. app.munged = "_bb_main"
  3249. Else
  3250. Local dir:String = ExtractDir(opt_filepath).ToLower()
  3251. dir = dir[dir.findLast("/") + 1..]
  3252. If dir.EndsWith(".mod") Then
  3253. dir = dir.Replace(".mod", "")
  3254. End If
  3255. Local file:String = StripDir(opt_filepath).ToLower()
  3256. app.munged = "_bb_" + dir + "_" + StripExt(file)
  3257. End If
  3258. End If
  3259. 'sanitize, remove non-allowed chars
  3260. app.munged = TStringHelper.Sanitize(app.munged)
  3261. End Method
  3262. ' load external cast defs
  3263. Method LoadExternCasts(path:String)
  3264. For Local externs:Int = 0 Until 3
  3265. Local ePath:String
  3266. ' we will iterate through all possibilities as there may be different sets
  3267. ' of explicit casts/no gen funcs for each.
  3268. Select externs
  3269. Case 0
  3270. ' eg. file.win32.x86.x
  3271. ePath = StripExt(path) + "." + opt_platform + "." + opt_arch + ".x"
  3272. Case 1
  3273. ' eg. file.win32.x
  3274. ePath = StripExt(path) + "." + opt_platform + ".x"
  3275. Case 2
  3276. ' eg. file.x
  3277. ePath = StripExt(path) + ".x"
  3278. End Select
  3279. If FileType(ePath) = FILETYPE_FILE Then
  3280. Print "Warning: .x cast definition files are deprecated. You should now place the details in the extern function's alias string. (" + path + ")"
  3281. ParseExternCast(LoadText( ePath ), False, ePath)
  3282. End If
  3283. Next
  3284. End Method
  3285. Method ParseExternCast:TCastDets(txt:String, single:Int = False, path:String = "")
  3286. Local toker:TToker = New TToker.Create(path, txt)
  3287. toker.NextToke
  3288. Local dets:TCastDets
  3289. While True
  3290. SkipEolsToker(toker)
  3291. If toker._tokeType = TOKE_EOF Exit
  3292. dets = New TCastDets
  3293. Local rt$=toker._toke
  3294. If CParseToker(toker, "const") Then
  3295. rt :+ " " + toker._toke
  3296. End If
  3297. If CParseToker(toker, "unsigned") Then
  3298. rt :+ " " + toker._toke
  3299. End If
  3300. NextTokeToker(toker)
  3301. If CParseToker(toker,"*") Then
  3302. rt:+ "*"
  3303. If CParseToker(toker,"*") Then
  3304. rt:+ "*"
  3305. End If
  3306. End If
  3307. If CParseToker(toker, "__stdcall") Then
  3308. dets.api = "__stdcall"
  3309. End If
  3310. ' fname
  3311. Local fn$=toker._toke
  3312. NextTokeToker(toker)
  3313. dets.name = fn
  3314. dets.retType = rt
  3315. ' add to global map (may be referenced by function ptr defs)
  3316. _externCasts.Insert(fn, dets)
  3317. ' args
  3318. ParseToker(toker, "(")
  3319. If CParseToker(toker, ")") Then
  3320. ' don't generate header extern
  3321. If CParseToker(toker, "!") Then
  3322. dets.noGen = True
  3323. End If
  3324. Continue
  3325. End If
  3326. Local i:Int = 0
  3327. Repeat
  3328. Local at$=toker._toke
  3329. If CParseToker(toker, "const") Then
  3330. at :+ " " + toker._toke
  3331. End If
  3332. If CParseToker(toker, "unsigned") Then
  3333. at :+ " " + toker._toke
  3334. End If
  3335. If CParseToker(toker, "struct") Then
  3336. at :+ " " + toker._toke
  3337. End If
  3338. NextTokeToker(toker)
  3339. If CParseToker(toker, "*") Then
  3340. at:+ "*"
  3341. If CParseToker(toker, "const") Then
  3342. at :+ " const"
  3343. End If
  3344. If CParseToker(toker, "*") Then
  3345. at:+ "*"
  3346. End If
  3347. End If
  3348. ' function pointer
  3349. If CParseToker(toker, "(") Then
  3350. ParseToker(toker, "*")
  3351. ParseToker(toker, ")")
  3352. at :+ "(*)"
  3353. ParseToker(toker, "(")
  3354. at :+ "("
  3355. While Not CParseToker(toker, ")")
  3356. NextTokeToker(toker)
  3357. at :+ toker._toke
  3358. Wend
  3359. at :+ ")"
  3360. End If
  3361. dets.args :+ [at]
  3362. If toker._toke=")" Exit
  3363. ParseToker(toker, ",")
  3364. i:+ 1
  3365. Forever
  3366. NextTokeToker(toker)
  3367. ' don't generate header extern
  3368. If CParseToker(toker, "!") Then
  3369. dets.noGen = True
  3370. End If
  3371. If single Then
  3372. Exit
  3373. End If
  3374. Wend
  3375. Return dets
  3376. End Method
  3377. Method ParseCurrentFile:Long(path:String, attrs:Long)
  3378. LoadExternCasts(path)
  3379. While _toke
  3380. SetErr
  3381. Select _toke.toLower()
  3382. Case "~n"
  3383. NextToke
  3384. Case "public"
  3385. NextToke
  3386. attrs=attrs & ~DECL_PRIVATE
  3387. Case "private"
  3388. NextToke
  3389. attrs=attrs | DECL_PRIVATE
  3390. Case "extern"
  3391. ParseExternBlock(_module, attrs)
  3392. Case "const"
  3393. _module.InsertDecls ParseDecls( _toke,attrs )
  3394. Case "global"
  3395. ParseDeclStmts(True, attrs, _module)
  3396. Case "threadedglobal"
  3397. ParseDeclStmts(True, attrs | DECL_THREADED, _module)
  3398. Case "struct"
  3399. _module.InsertDecl ParseClassDecl( _toke,attrs | CLASS_STRUCT )
  3400. Case "type"
  3401. _module.InsertDecl ParseClassDecl( _toke,attrs)
  3402. Case "interface"
  3403. _module.InsertDecl ParseClassDecl( _toke,attrs|CLASS_INTERFACE|DECL_ABSTRACT )
  3404. Case "enum"
  3405. _module.InsertDecl ParseEnumDecl( _toke )
  3406. Case "function"
  3407. _module.InsertDecl ParseFuncDecl( _toke,attrs )
  3408. Case "incbin"
  3409. SetErr
  3410. NextToke
  3411. Local s:String = ParseStringLit()
  3412. _app.mapStringConsts(s)
  3413. Local ib:TIncBin = New TIncbin.Create(s, path)
  3414. If Not ib Then
  3415. Err "Incbin file '"+ s +"' not found."
  3416. End If
  3417. _app.incbins.AddLast(ib)
  3418. Case "include"
  3419. SetErr
  3420. 'include command is NOT just a pattern to replace with
  3421. 'content. BlitzMax parses each included file before the
  3422. 'content gets appended to the source (right before
  3423. 'semanting or analyzing content)
  3424. NextToke
  3425. Local includeFile:String = ParseStringLit()
  3426. 'convert the URI of the to include file as it might be
  3427. 'a relative one
  3428. includeFile = RealPath(includeFile)
  3429. 'instead of merging the data of multiple parsers, the
  3430. 'same parser is used for all included files - but each
  3431. 'of them uses an individual toker
  3432. If FileType( includeFile )<>FILETYPE_FILE
  3433. Err "File '"+ includeFile +"' not found."
  3434. EndIf
  3435. 'instead of "LoadText" "PreProcess" is used to include
  3436. 'handling of conditionals and comments
  3437. Try
  3438. Local includeSource:String = PreProcess(includeFile)
  3439. Local includeToker:TToker = New TToker.Create(includeFile, includeSource)
  3440. 'backup old vars
  3441. Local oldToker:TToker = Self._toker
  3442. 'assign temporary vars
  3443. Self._toker = includeToker
  3444. 'parse the include file
  3445. parseCurrentFile(includeFile, attrs)
  3446. 'restore backup vars
  3447. Self._toker = oldToker
  3448. Catch e:TStreamException
  3449. DoErr "Failed to include file '" + includeFile + "' : '" + e.ToString() + "'"
  3450. End Try
  3451. 'move on to next toke (after include "xyz.bmx")
  3452. NextToke
  3453. Default
  3454. ParseStmt
  3455. 'Err "Syntax error - expecting declaration."
  3456. End Select
  3457. Wend
  3458. Return attrs
  3459. End Method
  3460. Method ParseGeneric:Object(templateSource:TTemplateRecord, templateDets:TTemplateDets)
  3461. Local toker:TToker = New TToker.Create(templateSource.file, templateSource.source, False, templateSource.start)
  3462. Local parser:TParser = New TParser.Create( toker, _appInstance )
  3463. Local m:TModuleDecl = New TModuleDecl
  3464. parser._module = m
  3465. Local cdecl:TClassDecl = Null
  3466. Select parser._toke
  3467. Case "type"
  3468. cdecl = parser.ParseClassDecl(parser._toke,0, templateDets )
  3469. Case "interface"
  3470. cdecl = parser.ParseClassDecl(parser._toke, CLASS_INTERFACE|DECL_ABSTRACT, templateDets )
  3471. End Select
  3472. Return cdecl
  3473. End Method
  3474. Method ParseMain()
  3475. SkipEols
  3476. Local mattrs:Long
  3477. 'If CParse( "strict" ) mattrs:|MODULE_STRICT
  3478. 'If CParse( "superstrict" ) mattrs:|MODULE_SUPERSTRICT
  3479. Local path$=_toker.Path()
  3480. Local ident$=StripAll( path )
  3481. Local munged$ '="bb_"+ident+"_"
  3482. If opt_buildtype = BUILDTYPE_MODULE And opt_ismain
  3483. ValidateModIdent ident
  3484. Else If opt_buildtype = BUILDTYPE_MODULE Then
  3485. Local dir:String = ExtractDir(opt_filepath).ToLower()
  3486. dir = dir[dir.findLast("/") + 1..]
  3487. If dir.EndsWith(".mod") Then
  3488. dir = ""
  3489. Else
  3490. dir :+ "_"
  3491. End If
  3492. munged = opt_modulename + "_" + dir + ident
  3493. 'sanitize, remove non-allowed chars
  3494. munged = TStringHelper.Sanitize(munged.ToLower())
  3495. End If
  3496. If opt_ismain Then 'And opt_modulename <> "brl.blitz" Then
  3497. ident = opt_modulename
  3498. End If
  3499. If opt_buildtype = BUILDTYPE_APP Then
  3500. ident = "m_" + ident
  3501. End If
  3502. _module=New TModuleDecl.Create( ident,munged,path,mattrs )
  3503. If Not _env Then
  3504. _env = _module
  3505. End If
  3506. _module.AddImport path,_module
  3507. _app.InsertModule _module
  3508. ' mung the app decl
  3509. MungAppDecl(_app)
  3510. If opt_buildtype = BUILDTYPE_MODULE And opt_modulename = "brl.blitz" Then
  3511. ' import Object and String definitions
  3512. Local par:TIParser = New TIParser
  3513. par.ParseModuleImport(_module, "brl.classes", modulepath("brl.blitz"), modulepath("brl.blitz") + "/blitz_classes.i")
  3514. ' set up built-in keywords
  3515. par = New TIParser
  3516. par.ParseModuleImport(_module, "brl.blitzkeywords", "", "", MakeKeywords())
  3517. End If
  3518. ' don't import ourself
  3519. If opt_modulename <> "brl.blitz" Then
  3520. Local par:TIParser = New TIParser
  3521. par.ParseModuleImport(_module, "brl.blitz", modulepath("brl.blitz"), , , MODULE_ACTUALMOD)
  3522. End If
  3523. Local mainFunc:TFuncDecl = New TFuncDecl.CreateF("__LocalMain", New TIntType,Null,0)
  3524. '_app.InsertDecl mainFunc
  3525. _module.insertDecl(mainFunc)
  3526. 'Local mainBlock:TBlockDecl = New TBlockDecl.Create( _block )
  3527. ' import all brl and pub modules if we haven't specified one
  3528. If opt_buildtype <> BUILDTYPE_MODULE And Not opt_framework Then
  3529. ImportAllModules MODULE_ACTUALMOD
  3530. Else
  3531. If opt_framework Then
  3532. Local par:TIParser = New TIParser
  3533. par.ParseModuleImport(_module, opt_framework, modulepath(opt_framework), , , MODULE_ACTUALMOD)
  3534. End If
  3535. End If
  3536. Local attrs:Long
  3537. While _toke
  3538. SetErr
  3539. Select _toke.ToLower()
  3540. Case "~n"
  3541. NextToke
  3542. Case "strict"
  3543. If _module.attrs & (MODULE_STRICT | MODULE_SUPERSTRICT) Then
  3544. Err "Strict or SuperStrict already specified"
  3545. End If
  3546. _module.attrs :| MODULE_STRICT
  3547. nextToke
  3548. Case "superstrict"
  3549. If _module.attrs & (MODULE_STRICT | MODULE_SUPERSTRICT) Then
  3550. Err "Strict or SuperStrict already specified"
  3551. End If
  3552. _module.attrs :| MODULE_SUPERSTRICT
  3553. opt_issuperstrict = True
  3554. NextToke
  3555. Default
  3556. Exit
  3557. End Select
  3558. Wend
  3559. ' auto enable superstrict mode?
  3560. If Not (_module.attrs & (MODULE_STRICT | MODULE_SUPERSTRICT)) Then
  3561. If opt_no_auto_superstrict Then
  3562. If opt_need_strict And Not (_module.attrs & (MODULE_STRICT | MODULE_SUPERSTRICT)) Then
  3563. Err "Strict or SuperStrict must be declared at the start of the file."
  3564. End If
  3565. Else
  3566. _module.attrs :| MODULE_SUPERSTRICT
  3567. End If
  3568. End If
  3569. 'Parse header - imports etc.
  3570. While _toke
  3571. SetErr
  3572. Select _toke.ToLower()
  3573. Case "~n"
  3574. NextToke
  3575. Case "public"
  3576. NextToke
  3577. attrs=attrs & ~DECL_PRIVATE
  3578. Case "private"
  3579. NextToke
  3580. attrs=attrs | DECL_PRIVATE
  3581. Case "import"
  3582. NextToke
  3583. If _tokeType=TOKE_STRINGLIT
  3584. ' TODO
  3585. 'ImportFile ReplaceEnvTags( ParseStringLit() )
  3586. ImportFile ParseStringLit()
  3587. Else
  3588. ImportModule ParseModPath(),attrs | MODULE_ACTUALMOD
  3589. EndIf
  3590. Case "framework"
  3591. If _module.attrs & MODULE_FRAMEWORK Then
  3592. Err "Framework already specified"
  3593. End If
  3594. If _module.attrs & MODULE_MODULE Then
  3595. Err "Module already specified"
  3596. End If
  3597. NextToke
  3598. ImportModule ParseModPath(),attrs
  3599. _module.attrs :| MODULE_FRAMEWORK
  3600. Case "alias"
  3601. NextToke
  3602. Repeat
  3603. Local ident$=ParseIdent()
  3604. Parse "="
  3605. Local decl:Object
  3606. Local scope:TScopeDecl=_module
  3607. _env=_module 'naughty! Shouldn't be doing GetDecl in parser...
  3608. Repeat
  3609. Local id$=ParseIdent()
  3610. decl=scope.FindDecl( id )
  3611. If Not decl Err "Identifier '"+id+"' not found."
  3612. If Not CParse( "." ) Exit
  3613. scope=TScopeDecl( decl )
  3614. If Not scope Or TFuncDecl( scope ) Err "Invalid scope '"+id+"'."
  3615. Forever
  3616. _env=Null '/naughty
  3617. _module.InsertDecl New TAliasDecl.Create( ident,decl,attrs )
  3618. Until Not CParse(",")
  3619. Case "module"
  3620. If _module.attrs & MODULE_FRAMEWORK Then
  3621. Err "Framework already specified"
  3622. End If
  3623. If _module.attrs & MODULE_MODULE Then
  3624. Err "Module already specified"
  3625. End If
  3626. Local m:String = ParseModuleDecl(_toke, attrs)
  3627. If m.ToLower() <> opt_modulename Then
  3628. Err "Module does not match commandline module"
  3629. End If
  3630. 'sanitize, remove non-allowed chars
  3631. _module.munged = TStringHelper.Sanitize(m)
  3632. _module.attrs :| MODULE_MODULE
  3633. Case "nodebug"
  3634. mainFunc.attrs :| DECL_NODEBUG
  3635. attrs :| DECL_NODEBUG
  3636. NextToke
  3637. Case "moduleinfo"
  3638. NextToke
  3639. Local info:String = ParseStringLit()
  3640. _module.modInfo.AddLast(info)
  3641. Default
  3642. Exit
  3643. End Select
  3644. If _tokeType = TOKE_PRAGMA Then
  3645. ParsePragmaStmt()
  3646. NextToke
  3647. End If
  3648. Wend
  3649. ' app code
  3650. PushBlock(mainFunc)
  3651. 'Parse main app
  3652. attrs = ParseCurrentFile(path, attrs)
  3653. PopBlock
  3654. End Method
  3655. Method ParseModule()
  3656. End Method
  3657. Method Create:TParser( toker:TToker,app:TAppDecl, unknownIdentsEvalFalse:Int = False )
  3658. _toke="~n"
  3659. _toker=toker
  3660. _app=app
  3661. SetErr
  3662. NextToke
  3663. Self.unknownIdentsEvalFalse = unknownIdentsEvalFalse
  3664. Return Self
  3665. End Method
  3666. End Type
  3667. Function Eval$( toker:TToker,_type:TType )
  3668. Local src$
  3669. While toker.Toke() And toker.Toke()<>"'" And toker.Toke()<>"~n" And toker.Toke()<>"~r"
  3670. src:+toker.Toke()
  3671. toker.NextToke()
  3672. Wend
  3673. Local t:String=EvalS( src,_type )
  3674. Return t
  3675. End Function
  3676. Function PreProcessNextToke$(toker:TToker)
  3677. Repeat
  3678. toker.NextToke()
  3679. Until toker.tokeType()<>TOKE_SPACE Or toker.Toke().Endswith("~n")
  3680. Return toker._toke
  3681. End Function
  3682. Function PreProcess$( path$ )
  3683. Local ifnest:Int,con:Int=1,line:Int,source:TStringList=New TStringList
  3684. Local toker:TToker=New TToker.Create( path,LoadText( path ), True )
  3685. PreProcessNextToke(toker)
  3686. Repeat
  3687. If line
  3688. source.AddLast "~n"
  3689. While toker.Toke() And Not toker.Toke().Endswith("~n") And toker.TokeType()<>TOKE_LINECOMMENT
  3690. PreProcessNextToke(toker)
  3691. Wend
  3692. If Not toker.Toke() Exit
  3693. PreProcessNextToke(toker)
  3694. EndIf
  3695. line :+ 1
  3696. ' catch up with any skipped lines
  3697. While line < toker._line - 1
  3698. line:+1
  3699. source.AddLast "~n"
  3700. Wend
  3701. If toker.TokeType()=TOKE_SPACE And Not toker.Toke().Endswith("~n") PreProcessNextToke(toker)
  3702. If toker.Toke()<>"?"
  3703. If con
  3704. Local textline$
  3705. While toker.Toke() And toker.Toke()<>"~n" And toker.TokeType()<>TOKE_LINECOMMENT
  3706. Local toke$=toker.Toke()
  3707. textline:+toke
  3708. toker.NextToke()
  3709. Wend
  3710. If textline Then
  3711. source.AddLast textline
  3712. EndIf
  3713. EndIf
  3714. Continue
  3715. EndIf
  3716. Local stm$= PreProcessNextToke(toker).ToLower()
  3717. 'toker.NextToke()
  3718. Local isNot:Int = False
  3719. If stm = "not" Then
  3720. If toker.TokeType()=TOKE_SPACE PreProcessNextToke(toker)
  3721. stm = toker.Toke().ToLower()
  3722. isNot = True
  3723. End If
  3724. 'If stm="end" Or stm="else"
  3725. ' If toker.TokeType()=TOKE_SPACE toker.NextToke()
  3726. ' If toker.Toke().ToLower()="if"
  3727. ' toker.NextToke()
  3728. ' stm:+"if"
  3729. ' EndIf
  3730. 'EndIf
  3731. Rem
  3732. Debug True if program is being compiled in debug mode.
  3733. Threaded True if program is being compiled in threaded mode.
  3734. Win32 True if program is being compiled for the Windows operating system.
  3735. MacOS True if program is being compiled for the MacOS operating system.
  3736. Linux True if program is being compiled for the Linux operating system.
  3737. X86 True if program is being compiled for the Intel CPU.
  3738. PPC True if program is being compiled for the PowerPC CPU.
  3739. MacOSX86 True if program is being compiled for an Intel Mac.
  3740. MacOSPPC True if program is being compiled for a PowerPC Mac.
  3741. BigEndian True if program is being compiled for a big endian CPU.
  3742. LittleEndian
  3743. End Rem
  3744. Select stm
  3745. Case "~r", "~n"
  3746. 'ifnest = 0
  3747. con = 1
  3748. Default
  3749. ' test for EOF
  3750. If Not toker.Toke() Exit
  3751. con = 0
  3752. Try
  3753. If Eval( toker,New TIntType ) = "1" con = 1
  3754. Catch Error:String
  3755. con = 0
  3756. End Try
  3757. Rem
  3758. Case "macos", "macosx86", "x86", "littleendian", "bigendian"
  3759. con = 1
  3760. ' If con=ifnest
  3761. ' If Eval( toker,TType.intType ) con:+1
  3762. ' EndIf
  3763. '
  3764. ifnest = 1
  3765. ' Case "rem"
  3766. '
  3767. ' ifnest:+1
  3768. Case "threaded", "win32", "linux", "ppc", "win32x86", "linuxx86", "macosppc"
  3769. If isNot Then
  3770. con = 1
  3771. Else
  3772. con = 0
  3773. End If
  3774. ifnest = 1
  3775. Case "else","elseif"
  3776. If Not ifnest Err "#Else without #If"
  3777. If con=ifnest
  3778. con=-con
  3779. Else If con=ifnest-1
  3780. If stm="elseif"
  3781. If Eval( toker,TType.intType ) con:+1
  3782. Else
  3783. con:+1
  3784. EndIf
  3785. EndIf
  3786. Case "end","endif"
  3787. If Not ifnest Err "#End without #If"
  3788. ifnest:-1
  3789. If con<0 con=-con
  3790. If ifnest<con con=ifnest
  3791. ' Case "print"
  3792. ' If con=ifnest
  3793. ' TODO
  3794. 'Print ReplaceEnvTags( Eval( toker,TType.stringType ) )
  3795. ' EndIf
  3796. ' Case "error"
  3797. ' If con=ifnest
  3798. ' TODO
  3799. 'Err ReplaceEnvTags( Eval( toker,TType.stringType ) )
  3800. ' EndIf
  3801. Default
  3802. Err "Unrecognized preprocessor directive '"+stm+"'."
  3803. End Rem
  3804. End Select
  3805. Forever
  3806. Return source.Join( "" )
  3807. End Function
  3808. Function ParseModule:TModuleDecl( path$,app:TAppDecl )
  3809. 'Local source$=PreProcess( path )
  3810. Local source:String = LoadText(path)
  3811. Local toker:TToker=New TToker.Create( path,source )
  3812. Local parser:TParser=New TParser.Create( toker,app )
  3813. parser.ParseMain
  3814. Return parser._module
  3815. End Function
  3816. Function AppendLibInit:String(source:String)
  3817. Local sb:TStringBuffer = TStringBuffer.Create(source)
  3818. sb.Append("~n")
  3819. sb.Append("Extern~n")
  3820. sb.Append("Function bbLibInit()~n")
  3821. sb.Append("End Extern~n")
  3822. sb.Append("Function InitBRL() Export~n")
  3823. sb.Append("bbLibInit()~n")
  3824. sb.Append("End Function~n")
  3825. Return sb.ToString()
  3826. End Function
  3827. '***** PUBLIC API ******
  3828. Function ParseApp:TAppDecl( path$ )
  3829. Local app:TAppDecl=New TAppDecl
  3830. _appInstance = app
  3831. Local source$=PreProcess( path )
  3832. 'Local source:String = LoadString(path)
  3833. If opt_makelib And opt_apptype Then
  3834. source = AppendLibInit(source)
  3835. End If
  3836. Local toker:TToker=New TToker.Create( path,source )
  3837. Local parser:TParser=New TParser.Create( toker,app )
  3838. parser.ParseMain
  3839. Return app
  3840. End Function
  3841. Function MungModuleName:String(ident:Object)
  3842. Local mung:String
  3843. If String(ident) Then
  3844. Local id:String = String(ident)
  3845. mung = "__bb_" + id + "_" + id[id.Find(".") + 1..]
  3846. Else
  3847. Local mdecl:TModuleDecl = TModuleDecl(ident)
  3848. If mdecl Then
  3849. Local id:String = mdecl.ident
  3850. Local dir:String = ExtractDir(mdecl.filepath).ToLower()
  3851. dir = dir[dir.findLast("/") + 1..]
  3852. If dir.EndsWith(".mod") Then
  3853. dir = ""
  3854. Else
  3855. dir :+ "_"
  3856. End If
  3857. mung = "__bb_" + id + "_" + dir + id[id.Find(".") + 1..]
  3858. End If
  3859. End If
  3860. 'return sanitized, remove non-allowed chars
  3861. Return TStringHelper.Sanitize(mung)
  3862. End Function
  3863. Function EvalS$( source$,ty:TType )
  3864. Local env:TScopeDecl=New TScopeDecl
  3865. ' debug/release
  3866. env.InsertDecl New TConstDecl.Create( "debug",New TIntType,New TConstExpr.Create( New TIntType,opt_debug ),0 )
  3867. env.InsertDecl New TConstDecl.Create( "gdbdebug",New TIntType,New TConstExpr.Create( New TIntType,opt_gdbdebug ),0 )
  3868. ' threaded
  3869. env.InsertDecl New TConstDecl.Create( "threaded",New TIntType,New TConstExpr.Create( New TIntType,opt_threaded ),0 )
  3870. ' macos
  3871. 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 )
  3872. 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 )
  3873. 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 )
  3874. 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 )
  3875. 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 )
  3876. ' osx
  3877. env.InsertDecl New TConstDecl.Create( "osx",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="macos" Or opt_platform="osx" ),0 )
  3878. 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 )
  3879. 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 )
  3880. 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 )
  3881. 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 )
  3882. ' ios
  3883. env.InsertDecl New TConstDecl.Create( "ios",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="ios" ),0 )
  3884. env.InsertDecl New TConstDecl.Create( "iosx86",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="ios" And opt_arch="x86"),0 )
  3885. env.InsertDecl New TConstDecl.Create( "iosx64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="ios" And opt_arch="x64"),0 )
  3886. env.InsertDecl New TConstDecl.Create( "iosarmv7",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="ios" And opt_arch="armv7"),0 )
  3887. env.InsertDecl New TConstDecl.Create( "iosarm64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="ios" And opt_arch="arm64"),0 )
  3888. ' windows
  3889. env.InsertDecl New TConstDecl.Create( "win32",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="win32" ),0 )
  3890. env.InsertDecl New TConstDecl.Create( "win32x86",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="win32" And opt_arch="x86"),0 )
  3891. 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 )
  3892. 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 )
  3893. env.InsertDecl New TConstDecl.Create( "win32armv7",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="win32" And opt_arch="armv7"),0 )
  3894. env.InsertDecl New TConstDecl.Create( "win32arm64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="win32" And opt_arch="arm64"),0 )
  3895. ' linux
  3896. 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 )
  3897. 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 )
  3898. 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 )
  3899. 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 )
  3900. 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 )
  3901. env.InsertDecl New TConstDecl.Create( "linuxriscv32",New TIntType,New TConstExpr.Create( New TIntType, (opt_platform="linux" And opt_arch="riscv32")),0 )
  3902. env.InsertDecl New TConstDecl.Create( "linuxriscv64",New TIntType,New TConstExpr.Create( New TIntType, (opt_platform="linux" And opt_arch="riscv64")),0 )
  3903. ' android
  3904. env.InsertDecl New TConstDecl.Create( "android",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" ),0 )
  3905. env.InsertDecl New TConstDecl.Create( "androidx86",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And opt_arch="x86"),0 )
  3906. env.InsertDecl New TConstDecl.Create( "androidx64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And opt_arch="x64"),0 )
  3907. 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 )
  3908. env.InsertDecl New TConstDecl.Create( "androidarmeabi",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And opt_arch="armeabi"),0 )
  3909. env.InsertDecl New TConstDecl.Create( "androidarmeabiv7a",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And opt_arch="armeabiv7a"),0 )
  3910. env.InsertDecl New TConstDecl.Create( "androidarm64v8a",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And opt_arch="arm64v8a"),0 )
  3911. ' raspberrypi - ARM only
  3912. 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 )
  3913. env.InsertDecl New TConstDecl.Create( "raspberrypiarm",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="raspberrypi" And opt_arch="arm"),0 )
  3914. env.InsertDecl New TConstDecl.Create( "raspberrypiarm64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="raspberrypi" And opt_arch="arm64"),0 )
  3915. ' haiku
  3916. 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 )
  3917. env.InsertDecl New TConstDecl.Create( "haikux86",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="haiku" And opt_arch="x86"),0 )
  3918. env.InsertDecl New TConstDecl.Create( "haikux64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="haiku" And opt_arch="x64"),0 )
  3919. ' emscripten
  3920. env.InsertDecl New TConstDecl.Create( "emscripten",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="emscripten" ),0 )
  3921. env.InsertDecl New TConstDecl.Create( "emscriptenjs",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="emscripten" And opt_arch="js"),0 )
  3922. ' arch
  3923. env.InsertDecl New TConstDecl.Create( "ppc",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="ppc" ),0 )
  3924. env.InsertDecl New TConstDecl.Create( "x86",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="x86" ),0 )
  3925. env.InsertDecl New TConstDecl.Create( "x64",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="x64" ),0 )
  3926. 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 )
  3927. env.InsertDecl New TConstDecl.Create( "armeabi",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="armeabi" ),0 )
  3928. env.InsertDecl New TConstDecl.Create( "armeabiv7a",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="armeabiv7a" ),0 )
  3929. env.InsertDecl New TConstDecl.Create( "arm64v8a",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="arm64v8a" ),0 )
  3930. env.InsertDecl New TConstDecl.Create( "js",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="js" ),0 )
  3931. env.InsertDecl New TConstDecl.Create( "armv7",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="armv7" ),0 )
  3932. env.InsertDecl New TConstDecl.Create( "arm64",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="arm64" ),0 )
  3933. env.InsertDecl New TConstDecl.Create( "riscv32",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="riscv32" ),0 )
  3934. env.InsertDecl New TConstDecl.Create( "riscv64",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="riscv64" ),0 )
  3935. 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 )
  3936. 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 )
  3937. ' endian
  3938. env.InsertDecl New TConstDecl.Create( "bigendian",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="ppc" ),0 )
  3939. env.InsertDecl New TConstDecl.Create( "littleendian",New TIntType,New TConstExpr.Create( New TIntType,opt_arch<>"ppc" ),0 )
  3940. ' opengles target platform
  3941. 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 )
  3942. ' musl - linux only
  3943. 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 )
  3944. ' nx / switch
  3945. env.InsertDecl New TConstDecl.Create( "nx",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="nx" ),0 )
  3946. env.InsertDecl New TConstDecl.Create( "nxarm64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="nx" And opt_arch="arm64"),0 )
  3947. ' new compiler
  3948. env.InsertDecl New TConstDecl.Create( "bmxng",New TIntType,New TConstExpr.Create( New TIntType, True ),0 )
  3949. ' coverage
  3950. env.InsertDecl New TConstDecl.Create( "coverage",New TIntType,New TConstExpr.Create( New TIntType, opt_coverage ),0 )
  3951. ' console or gui build?
  3952. env.InsertDecl New TConstDecl.Create( "console",New TIntType,New TConstExpr.Create( New TIntType, opt_apptype = APPTYPE_CONSOLE ),0 )
  3953. env.InsertDecl New TConstDecl.Create( "gui",New TIntType,New TConstExpr.Create( New TIntType, opt_apptype = APPTYPE_GUI ),0 )
  3954. ' user defines
  3955. If opt_userdefs Then
  3956. Local defs:String[] = opt_userdefs.ToLower().Split(",")
  3957. For Local def:String = EachIn defs
  3958. def = def.Trim()
  3959. If def Then
  3960. Local name:String = def
  3961. Local value:Int = 1
  3962. Local dp:String[] = def.Split("=")
  3963. If dp.length = 2 Then
  3964. name = dp[0].Trim()
  3965. value = Int(dp[1])
  3966. End If
  3967. env.InsertDecl New TConstDecl.Create( name,New TIntType,New TConstExpr.Create( New TIntType, value ),0 )
  3968. End If
  3969. Next
  3970. End If
  3971. PushEnv env
  3972. Local toker:TToker=New TToker.Create( "",source )
  3973. Local parser:TParser=New TParser.Create( toker,Null,True )
  3974. Local val:String
  3975. Try
  3976. Local expr:TExpr=parser.ParseExpr()
  3977. expr=expr.Semant()
  3978. If ty expr=expr.Cast( ty )
  3979. val=expr.Eval()
  3980. Catch error:String
  3981. val = "0"
  3982. End Try
  3983. PopEnv
  3984. Return val
  3985. End Function