parser.bmx 131 KB

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