jsparser.pp 120 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369
  1. { *********************************************************************
  2. This file is part of the Free Component Library (FCL)
  3. Copyright (c) 2016 Michael Van Canneyt.
  4. Javascript parser
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit jsparser;
  12. { $define debugparser}
  13. {$mode objfpc}{$H+}
  14. {$inline on}
  15. interface
  16. uses
  17. Classes, SysUtils, jsscanner, jstree, jstoken, jsbase;
  18. Const
  19. SEmptyLabel = '';
  20. MinAsyncVersion = ecma2021;
  21. MinAwaitVersion = ecma2021;
  22. MinYieldVersion = ecma2021;
  23. minLetVersion = ecma2021;
  24. MinDebuggerVersion = ecma2021;
  25. MinImportVersion = ecma2021;
  26. MinExportVersion = ecma2021;
  27. MinClassVersion = ecma2021;
  28. MinGeneratorVersion = ecma2021;
  29. Type
  30. TECMAVersion = jsScanner.TECMAVersion;
  31. TScopeType = (stFunction,stClass,stModule,stNamespace);
  32. TListType = (ltUnknown,ltTuple,ltTemplate);
  33. TFunctionFlag = (ffAmbient,ffConstructor,ffGenerator);
  34. TFunctionFlags = Set of TFunctionFlag;
  35. EJSParser = Class(Exception)
  36. ErrorRow : Integer;
  37. ErrorCol : integer;
  38. FileName : String;
  39. end;
  40. TParseTypeOption = (ptoAllowLiteral,ptoRefOnly,ptoUnion,ptoIntersection,ptoFunctionCall);
  41. TParseTypeOptions = set of TParseTypeOption;
  42. { TJSParser }
  43. TJSParser = Class(TObject)
  44. Private
  45. FFunctionDepth: Integer;
  46. FInput : TStream;
  47. FIsLHS: Boolean;
  48. FNoIn: Boolean;
  49. FScanner : TJSScanner;
  50. FPrevious,
  51. FCurrent : TJSToken;
  52. FCurrentString : JSBase.TJSString;
  53. FFreeScanner : Boolean;
  54. FCurrentVars : TJSElementNodes;
  55. FPeekToken: TJSToken;
  56. FPeekTokenString: JSBase.TJSString;
  57. FLabelSets,
  58. FCurrentLabelSet:TJSLabelSet;
  59. FLabels : TJSLabel;
  60. // these check that current token is identifier with specific value:
  61. // as, from, get, of, set, target
  62. function AddToElements(aSource: TJSSourceElements; aElement: TJSElement; aIsAmbient: Boolean=False; aIsExport: Boolean=False): Boolean;
  63. procedure ClassDefToMembers(aClass: TJSClassDeclaration; aClassDef: TJSObjectTypeDef);
  64. function CurrentTokenIsValidIdentifier: Boolean;
  65. function GetIsTypeScript: Boolean;
  66. function IdentifierIsLiteral(const aValue : jsbase.TJSString) : Boolean;
  67. Procedure CheckIdentifierLiteral(const aValue : jsbase.TJSString);
  68. function ConsumeIdentifierLiteral(const aValue: jsbase.TJSString): TJSToken;
  69. function CheckSemiColonInsert(aToken: TJSToken; Consume: Boolean): Boolean;
  70. function EnterLabel(const ALabelName: jsBase.TJSString): TJSLabel;
  71. // Check that current token is aToken
  72. procedure Expect(aToken: TJSToken);
  73. // Check that current token is aToken and goto next token.
  74. procedure Consume(aToken: TJSToken; AllowSemicolonInsert : Boolean = False);
  75. procedure FreeCurrentLabelSet;
  76. function GetVersion: TECMAVersion;
  77. procedure LeaveLabel;
  78. function LookupLabel(const ALabelName: jsBase.TJSString; Kind: TJSToken): TJSLabel;
  79. function ParseAdditiveExpression: TJSElement;
  80. procedure ParseAliasElements(aElements: TJSAliasElements);
  81. procedure ParseAmbientClassBody(aObj: TJSObjectTypeDef);
  82. function ParseArguments: TJSarguments;
  83. function ParseArrayLiteral: TJSElement;
  84. procedure ParseArrowFunctionTypeDef(aDef: TJSArrowFunctionTypeDef; aFirstParam: TJSTypedParam); overload;
  85. function ParseArrowFunctionTypeDef(const aArgName: jsBase.TJSString; aArgIsSpread: Boolean): TJSArrowFunctionTypeDef; overload;
  86. function ParseArrowFunctionTypeDef(aFirst: TJSObjectTypeDef; aArgIsSpread: Boolean): TJSArrowFunctionTypeDef; overload;
  87. function ParseAssignmentExpression: TJSElement;
  88. function ParseBitwiseAndExpression: TJSElement;
  89. function ParseBitwiseORExpression: TJSElement;
  90. function ParseBitwiseXORExpression: TJSElement;
  91. function ParseBlock: TJSElement;
  92. function ParseBreakStatement: TJSElement;
  93. function ParseClassBody(isAmbient : Boolean = False): TJSSourceElements; inline;
  94. function ParseClassDeclaration(isAmbient : Boolean = False; IsAbstract : Boolean = False) : TJSClassDeclaration;
  95. function ParseClassStatement(isAmbient : Boolean = False; IsAbstract : Boolean = False) : TJSClassStatement;
  96. function ParseClassExpression: TJSClassDeclaration;
  97. function ParseConditionalExpression: TJSElement;
  98. function ParseContinueStatement: TJSElement;
  99. function ParseDebuggerStatement: TJSElement;
  100. function ParseDestructuredParam(aParams: TJSTypedParams) : TJSTypedParam;
  101. function ParseEmptyStatement: TJSElement;
  102. function ParseEnumDeclaration: TJSEnumDeclaration;
  103. function ParseEnumDeclarationStatement: TJSElement;
  104. function ParseEqualityExpression: TJSElement;
  105. function ParseExportStatement(IsAssign : Boolean): TJSElement;
  106. function ParseExpression: TJSElement;
  107. function ParseExpressionStatement: TJSElement;
  108. procedure ParseFormalParameterList(aParams : TJSTypedParams);
  109. function ParseFunctionDeclaration(aFlags : TFunctionFlags): TJSFunctionDeclarationStatement;
  110. function ParseFunctionExpression(aFlags : TFunctionFlags): TJSFunctionDeclarationStatement;
  111. function ParseFunctionStatement: TJSElement;
  112. function ParseFunctionBody: TJSFunctionBody;
  113. procedure ParseGenericParamList(aList: TJSElementNodes);
  114. function ParseIdentifier(AcceptAsIdentifier: TJSTokens=[]): JSBase.TJSString;
  115. function ParseIfStatement: TJSElement;
  116. function ParseImportStatement: TJSElement;
  117. function ParseIndexSignature: TJSObjectTypeElementDef;
  118. function ParseIndexSignatureStatement: TJSIndexSignatureStatement;
  119. function ParseInterfaceDeclaration: TJSInterfaceDeclaration;
  120. function ParseInterfaceDeclarationStatement: TJSInterfaceStatement;
  121. function ParseIterationStatement: TJSElement;
  122. function ParseLabeledStatement: TJSElement;
  123. function ParseLeftHandSideExpression: TJSElement;
  124. function ParseLiteral: TJSElement;
  125. function ParseLogicalAndExpression: TJSElement;
  126. function ParseLogicalORExpression: TJSElement;
  127. function ParseMemberExpression: TJSElement;
  128. function ParseModuleDeclarationStatement : TJSModuleStatement;
  129. function ParseModuleDeclaration : TJSModuleDeclaration;
  130. function ParseModuleBody: TJSSourceElements;
  131. function ParseMultiplicativeExpression: TJSElement;
  132. function ParseNamespaceDeclarationStatement : TJSNamespaceStatement;
  133. function ParseNamespaceDeclaration(IsAmbient: Boolean = False): TJSNamespaceDeclaration;
  134. function ParseNamespaceBody(IsAmbient: Boolean = False): TJSSourceElements;
  135. function ParseNumericLiteral: TJSElement;
  136. procedure ParseObjectBody(aObj: TJSObjectTypeDef);
  137. function ParseObjectLiteral: TJSElement;
  138. function ParsePostFixExpression: TJSElement;
  139. function ParsePrimaryExpression: TJSElement;
  140. function ParseRegularExpressionLiteral: TJSElement;
  141. function ParseRelationalExpression: TJSElement;
  142. function ParseReturnStatement: TJSElement;
  143. function ParseShiftExpression: TJSElement;
  144. function ParseStatement(IsAmbient : Boolean = False;IsExport : Boolean = False): TJSElement;
  145. function ParseStatementList: TJSElement;
  146. function ParseStringLiteral: TJSElement;
  147. function ParseSwitchStatement: TJSElement;
  148. function ParseThrowStatement: TJSElement;
  149. function ParseTryStatement: TJSElement;
  150. // Type parsing
  151. function ParseTypeSimple(aOptions: TParseTypeOptions): TJSTypeDef;
  152. function ParseTypeDeclaration: TJSTypeDeclaration;
  153. function ParseTypeDeclarationStatement : TJSElement;
  154. function ParseTypeDef(aOptions: TParseTypeOptions = []; StopTokens : TJSTokens = []): TJSTypeDef;
  155. procedure ParseTypeGuard(aType: TJSTypedef; aOptions: TParseTypeOptions; StopTokens: TJSTokens=[]);
  156. function ParseTypeArrayDef(aOptions: TParseTypeOptions; aSub: TJSTypeDef): TJSArrayTypeDef;
  157. function ParseTypeObjectDef: TJSObjectTypeDef;
  158. function ParseGenericType(aType: TJSTypeDef): TJSTypeDef;
  159. function ParseTypeTuple(aOptions: TParseTypeOptions): TJSTupleTypeDef;
  160. function ParseTypeParenthesised(aOptions : TParseTypeOptions): TJSTypeDef;
  161. procedure ParseTypeList(aList: TJSElementNodes; aTerminator: TJSToken; ListType : TListType = ltUnknown);
  162. function ParseTypeStatement(Elements: TJSSourceElements; ScopeType: TScopeType; aIsAmbient: Boolean): TJSElement;
  163. function ParseUnaryExpression: TJSElement;
  164. procedure ParseTypeUnionIntercept(aType: TJSUnionOrTupleTypeDef; aOptions: TParseTypeOptions; aSeparator: TJSToken);
  165. function ParseVariableDeclaration(aVarType: TJSVarType=vtVar; IsAmbient: Boolean=False; IsExport: Boolean=False): TJSElement;
  166. function ParseVariableDeclarationList(aVarType : TJSVarType = vtVar; IsAmbient: Boolean = False; IsExport: Boolean = False): TJSElement;
  167. function ParseVariableStatement(aVarType : TJSVarType = vtVar;IsAmbient : Boolean = False; IsExport : Boolean = False): TJSElement;
  168. function ParseWithStatement: TJSElement;
  169. Protected
  170. Procedure CheckParser;
  171. Function CurrentLabelSet : TJSLabelSet;
  172. function CurSource: String;
  173. Function CurLine : Integer;
  174. Function CurPos : Integer;
  175. Function CreateElement(AElementClass : TJSElementClass) : TJSElement; virtual;
  176. Procedure FreeElement(aElement : TJSElement); virtual;
  177. Procedure FreeElement(aElements : TJSElementNodes); virtual;
  178. Procedure Error(const Msg : String);
  179. Procedure Error(const Fmt : String; Args : Array of const);
  180. // Parse functions
  181. Function IsIdentifier(const aIdentifier : jsBase.TJSString) : Boolean; inline;
  182. function ParseSourceElements(ScopeType : TScopeType = stFunction; ParentisAmbient : Boolean = False): TJSSourceElements;
  183. Property FunctionDepth : Integer Read FFunctionDepth Write FFunctionDepth;
  184. Property NoIn : Boolean Read FNoIn Write FNoIn;
  185. Property IsLHS : Boolean Read FIsLHS Write FIsLHS;
  186. Public
  187. Constructor Create(AInput: TStream; aVersion : TECMAVersion = ecma5; aIsTypeScript : Boolean = false; const aFileName : String = '');
  188. // Scanner has version
  189. Constructor Create(AScanner : TJSScanner);
  190. Destructor Destroy; override;
  191. Function Parse : TJSElement;
  192. Function ParseProgram : TJSFunctionDeclarationStatement;
  193. Function CurrentToken : TJSToken;
  194. Function CurrentTokenString : jsBase.TJSString;
  195. Function GetNextToken : TJSToken;
  196. Function PeekNextToken : TJSToken;
  197. Function IsEndOfLine : Boolean;
  198. Property ECMAVersion : TECMAVersion Read GetVersion;
  199. Property IsTypeScript : Boolean Read GetIsTypeScript;
  200. Property Scanner : TJSScanner Read FScanner;
  201. end;
  202. implementation
  203. uses typinfo;
  204. Resourcestring
  205. SErrUnmatchedCurlyBrace = 'Unmatched }';
  206. SErrUnmatchedSquareBrace = 'Unmatched ]';
  207. SErrUnmatchedBrace = 'Unmatched )';
  208. SErrUnexpectedToken = 'Unexpected token: ''%s''';
  209. SErrTokenMismatch = 'Unexpected token: ''%s'', expected: ''%s''';
  210. SErrSemicolonOrInExpected = 'Unexpected token: ''%s'', expected ; or ''in''';
  211. SErrSemicolonExpected = 'Unexpected token: ''%s'', expected ;';
  212. SErrDuplicateLabelName = 'Duplicate label name: ''%s''';
  213. SErrLabelNotContinuable = 'Label ''%s'' is not suitable for continue.';
  214. SErrLabelNOtDefinedOrReachable = 'Label ''%s'' is not defined or not reachable.';
  215. SErrContinueNotInLoop = 'Continue statement not in loop';
  216. SErrBreakNotInLoop = 'Break statement not in loop';
  217. SErrReturnNotInFunction = 'return statement not in a function body';
  218. SErrCaseEndExpected = 'Unexpected token: Expected }, case or default clause';
  219. SErrDuplicateSwitchDefault = 'Duplicate default clause for switch statement';
  220. SErrNewlineAfterThrow = 'Newline after throw not allowed';
  221. SErrCatchFinallyExpected = 'Unexpected token: Expected ''catch'' or ''finally''';
  222. SErrArgumentsExpected = 'Unexpected token: Expected '','' or '')'', got %s';
  223. SErrArrayEnd = 'Unexpected token: Expected '','' or '']'', got %s';
  224. SErrExpectedColonBrace = 'Unexpected token: Expected '':'' or ''('', got %s';
  225. //SErrObjectEnd = 'Unexpected token: Expected '','' or ''}'', got %s';
  226. SErrObjectElement = 'Unexpected token: Expected string, identifier or number after '','' got: %s';
  227. SErrLiteralExpected = 'Unexpected token: Expected: null, true, false, number, string, or regex, got: %s';
  228. SErrInvalidnumber = 'Invalid numerical value: %s';
  229. SErrInvalidRegularExpression = 'Invalid regular expression: %s';
  230. SErrFunctionNotAllowedHere = 'function keyword not allowed here';
  231. SErrExpectedButFound = 'Unexpected token. Expected "%s" but found "%s"';
  232. SErrExpectedMulOrCurlyBrace = 'Unexpected token: Expected * or {, got: %s';
  233. SErrExpectedMulOrCurlyBraceOrDefault = 'Unexpected token: Expected * or { or default , got: %s';
  234. SErrTypeExpected = 'Type expected, but found: "%s"';
  235. {
  236. SErrUnionWithoutType = 'Union type without type name';
  237. SErrIntersectionWithoutType = 'Intersection type without type name';
  238. SErrArrayWithoutType = 'Array type without type name';
  239. SErrGenericWithoutType = 'Generic type without base type';
  240. SErrGenericArray1Element = 'Generic array type can have only 1 element';
  241. }
  242. SErrorInTypeDef = 'Error in type definition. Expected %s';
  243. SArrowFunction = 'Arrow function';
  244. SBraceClose = 'Closing brace ")"';
  245. SErrInvalidIndexSignature = 'Invalid index signature';
  246. SErrExtendsNeedsTypeName = 'extends can only be used after type reference';
  247. SErrObjConstMustBeStaticReadonly = 'Const must be static & readonly';
  248. SErrInvalidTupleLabel = 'Invalid tuple label: got %s type';
  249. { TJSScanner }
  250. Function TJSParser.CurrentToken: TJSToken;
  251. begin
  252. Result:=FCurrent;
  253. end;
  254. Function TJSParser.CurrentTokenString: JSBase.TJSString;
  255. begin
  256. Result:=FCurrentString;
  257. end;
  258. Function TJSParser.GetNextToken: TJSToken;
  259. begin
  260. FPrevious:=FCurrent;
  261. If (FPeekToken<>tjsunknown) then
  262. begin
  263. FCurrent:=FPeekToken;
  264. FCurrentString:=FPeekTokenString;
  265. FPeekToken:=tjsUnknown;
  266. FPeekTokenString:='';
  267. end
  268. else
  269. begin
  270. FCurrent:=FScanner.FetchToken;
  271. FCurrentString:=JSBase.TJSString(FScanner.CurTokenString);
  272. if (FCurrentString='') then
  273. FCurrentString:=JSBase.TJSString(TokenInfos[FCurrent]);
  274. end;
  275. Result:=FCurrent;
  276. {$ifdef debugparser}Writeln('GetNextToken (',FScanner.CurLine,',',FScanner.CurColumn,'): ',GetEnumName(TypeInfo(TJSToken),Ord(FCurrent)), ' As string: ',FCurrentString);{$endif debugparser}
  277. end;
  278. Function TJSParser.PeekNextToken: TJSToken;
  279. begin
  280. If (FPeekToken=tjsUnknown) then
  281. begin
  282. FPeekToken:=FScanner.FetchToken;
  283. FPeekTokenString:=JSBase.TJSString(FScanner.CurTokenString);
  284. end;
  285. {$ifdef debugparser}Writeln('PeekNextToken : ',GetEnumName(TypeInfo(TJSToken),Ord(FPeekToken)), ' As string: ',FPeekTokenString);{$endif debugparser}
  286. Result:=FPeekToken;
  287. end;
  288. Function TJSParser.IsEndOfLine: Boolean;
  289. begin
  290. Result:=FScanner.IsEndOfLine;
  291. end;
  292. Function TJSParser.CurPos: Integer;
  293. begin
  294. If Assigned(FScanner) then
  295. Result:=FScanner.CurColumn
  296. else
  297. Result:=0;
  298. end;
  299. Function TJSParser.CurLine: Integer;
  300. begin
  301. If Assigned(FScanner) then
  302. Result:=FScanner.CurRow
  303. else
  304. Result:=0;
  305. end;
  306. function TJSParser.CurSource: String;
  307. begin
  308. If Assigned(FScanner) then
  309. Result:=FScanner.CurFileName
  310. else
  311. Result:='';
  312. end;
  313. Procedure TJSParser.CheckParser;
  314. begin
  315. end;
  316. procedure TJSParser.LeaveLabel;
  317. Var
  318. L : TJSLabel;
  319. begin
  320. L:=FLabels;
  321. FLabels:=FLabels.Next;
  322. L.Free; // ??
  323. end;
  324. function TJSParser.LookupLabel(const ALabelName: jsBase.TJSString; Kind: TJSToken): TJSLabel;
  325. Var
  326. L : TJSLabel;
  327. begin
  328. L:=FLabels;
  329. Result:=Nil;
  330. While (L<>Nil) and (Result=Nil) do
  331. begin
  332. If (L.Name=ALabelName) then
  333. begin
  334. if (kind=tjsContinue) and (Not L.LabelSet.Continuable) and (ALabelName<>SEmptyLabel) then
  335. Error(SErrLabelNotContinuable,[ALabelName]);
  336. Result:=L;
  337. end;
  338. L:=L.Next;
  339. end;
  340. If (Result=Nil) then
  341. begin
  342. If (ALabelName<>'') then
  343. Error(SErrLabelNOtDefinedOrReachable,[ALabelName])
  344. else if kind=tjsCOntinue then
  345. Error(SErrContinueNotInLoop)
  346. else
  347. Error(SErrBreakNotInLoop);
  348. end;
  349. end;
  350. function TJSParser.EnterLabel(const ALabelName: jsBase.TJSString): TJSLabel;
  351. Var
  352. L : TJSLabel;
  353. begin
  354. If (ALAbelName<>SEmptyLabel) then
  355. begin
  356. L:=FLabels;
  357. While (L<>Nil) do
  358. begin
  359. If (L.Name=ALabelName) then
  360. Error(SErrDuplicateLabelName,[ALabelName]);
  361. L:=L.Next;
  362. end;
  363. end;
  364. L:=TJSLabel.Create;
  365. L.Name:=ALabelName;
  366. L.LabelSet:=CurrentLabelSet;
  367. L.LocationSource:=Self.CurSource;
  368. L.LocationLine:=CurLine;
  369. L.LocationPos:=CurPos;
  370. L.Next:=FLabels;
  371. FLabels:=L;
  372. Result:=L;
  373. end;
  374. Function TJSParser.CurrentLabelSet: TJSLabelSet;
  375. Var
  376. LS : TJSLabelSet;
  377. begin
  378. If (FCurrentLabelSet=Nil) then
  379. begin
  380. LS:=TJSLabelSet.Create;
  381. If (FLabelSets=Nil) then
  382. LS.Target:=1
  383. else
  384. LS.Target:=FLabelSets.Target;
  385. LS.Next:=FLabelSets;
  386. FLabelSets:=LS;
  387. FCurrentLabelSet:=LS;
  388. end;
  389. Result:=FCurrentLabelSet;
  390. end;
  391. Function TJSParser.CreateElement(AElementClass: TJSElementClass): TJSElement;
  392. begin
  393. Result:=AElementClass.Create(CurLine,CurPos,CurSource);
  394. end;
  395. procedure TJSParser.FreeElement(aElement: TJSElement);
  396. begin
  397. aElement.Free;
  398. end;
  399. procedure TJSParser.FreeElement(aElements: TJSElementNodes);
  400. Var
  401. I : integer;
  402. begin
  403. For I:=0 to aElements.Count-1 do
  404. FreeElement(aElements[i].Node);
  405. aElements.DoClearNodes:=True;
  406. aElements.Free;
  407. end;
  408. Procedure TJSParser.Error(const Msg: String);
  409. Var
  410. ErrAt : String;
  411. E : EJSParser;
  412. begin
  413. If Assigned(FScanner) then
  414. If FScanner.CurFilename<>'' then
  415. ErrAt:=Format('Error: file "%s" line %d, pos %d: ',[FScanner.CurFileName,FScanner.CurRow,FScanner.CurColumn])
  416. else
  417. ErrAt:=Format('Error: line %d, pos %d: ',[FScanner.Currow,FScanner.CurColumn]);
  418. E:=EJSParser.Create(ErrAt+Msg);
  419. E.ErrorCol:=FScanner.CurColumn;
  420. E.ErrorRow:=FScanner.CurRow;
  421. E.FileName:=FScanner.CurFileName;
  422. Raise E;
  423. end;
  424. Procedure TJSParser.Error(const Fmt: String; Args: Array of const);
  425. begin
  426. Error(Format(Fmt,Args));
  427. end;
  428. function TJSParser.IsIdentifier(const aIdentifier: jsBase.TJSString): Boolean;
  429. begin
  430. Result:=IdentifierIsLiteral(aIdentifier);
  431. end;
  432. constructor TJSParser.Create(AInput: TStream; aVersion: TECMAVersion; aIsTypeScript: Boolean; const aFileName : String = '');
  433. begin
  434. FInput:=AInput;
  435. FCurrent:=TJSUnknown;
  436. FScanner:=TJSScanner.Create(FInput,aVersion,aFileName);
  437. FScanner.IsTypeScript:=aIsTypeScript;
  438. FFreeScanner:=True;
  439. end;
  440. Constructor TJSParser.Create(AScanner: TJSScanner);
  441. begin
  442. FCurrent:=TJSUnknown;
  443. FScanner:=AScanner;
  444. FFreeScanner:=False;
  445. end;
  446. Destructor TJSParser.Destroy;
  447. begin
  448. if FFreeScanner then
  449. FreeAndNil(FScanner);
  450. inherited;
  451. end;
  452. procedure TJSParser.Expect(aToken: TJSToken);
  453. begin
  454. {$ifdef debugparser} Writeln('Expecting : ',GetEnumName(TypeInfo(TJSToken),Ord(AToken)), ' As string: ',TokenInfos[AToken]);{$endif debugparser}
  455. If Not CheckSemiColonInsert(AToken,False) then
  456. if (CurrentToken<>aToken) then
  457. Error(SerrTokenMismatch,[CurrenttokenString,TokenInfos[aToken]]);
  458. end;
  459. function TJSParser.IdentifierIsLiteral(const aValue: jsbase.TJSString): Boolean;
  460. begin
  461. Result:=(CurrentToken=tjsIdentifier) and (CurrentTokenString=aValue);
  462. end;
  463. function TJSParser.GetIsTypeScript: Boolean;
  464. begin
  465. Result:=FScanner.IsTypeScript;
  466. end;
  467. procedure TJSParser.CheckIdentifierLiteral(const aValue: jsbase.TJSString);
  468. begin
  469. if Not IdentifierIsLiteral(aValue) then
  470. Error(SErrExpectedButFound,[aValue,CurrentTokenString]);
  471. end;
  472. function TJSParser.ConsumeIdentifierLiteral(const aValue: jsbase.TJSString): TJSToken;
  473. begin
  474. CheckidentifierLiteral(aValue);
  475. Result:=GetNextToken;
  476. end;
  477. function TJSParser.CheckSemiColonInsert(aToken : TJSToken; Consume : Boolean) : Boolean;
  478. begin
  479. Result:=(AToken=tjsSemiColon);
  480. If Result then
  481. begin
  482. Result:=(CurrentToken=tjsCurlyBraceClose) or (FScanner.WasEndOfLine) or (CurrentToken=tjsEOF);
  483. If Result and Consume then
  484. FPrevious:=tjsSemiColon;
  485. end;
  486. end;
  487. procedure TJSParser.Consume(aToken: TJSToken; AllowSemicolonInsert: Boolean);
  488. begin
  489. {$ifdef debugparser} Writeln('Consuming : ',GetEnumName(TypeInfo(TJSToken),Ord(AToken)), ' As string: ',TokenInfos[AToken]);{$endif debugparser}
  490. Expect(aToken);
  491. If not (AllowSemiColonInsert and CheckSemiColonInsert(aToken,True)) then
  492. GetNextToken;
  493. end;
  494. function TJSParser.ParseIdentifier (AcceptAsIdentifier : TJSTokens = []): JSBase.TJSString;
  495. { On entry, on identifier,
  496. on exit, after identifier
  497. }
  498. begin
  499. Result:='';
  500. if (AcceptAsIdentifier<>[]) and (CurrentToken in AcceptAsIdentifier) then
  501. Result:=CurrentTokenString
  502. else
  503. begin
  504. Expect(tjsIdentifier);
  505. Result:=CurrentTokenString;
  506. end;
  507. GetNextToken;
  508. While (CurrentToken=tjsDot) do
  509. begin
  510. GetNextToken;
  511. Expect(tjsIdentifier);
  512. Result:=Result+'.'+CurrentTokenString;
  513. GetNextToken;
  514. end;
  515. // until (CurrentToken<>tkDot) or FScanner.WasEndOfLine;
  516. end;
  517. procedure TJSParser.ParseGenericParamList(aList : TJSElementNodes);
  518. // On entry, we're on <
  519. // On exit, we're on >
  520. Var
  521. PrevRShift : Boolean;
  522. begin
  523. PrevRShift:=FScanner.DisableRShift;
  524. Try
  525. FScanner.DisableRShift:=True;
  526. ParseTypeList(aList,jstoken.tjsGT,ltTemplate);
  527. Finally
  528. FScanner.DisableRShift:=PrevRShift;
  529. end;
  530. end;
  531. function TJSParser.ParseTypeObjectDef: TJSObjectTypeDef;
  532. // on entry, on {
  533. // on exit, on }
  534. Var
  535. N : TJSObjectTypeDef;
  536. begin
  537. N:=TJSObjectTypeDef(CreateElement(TJSObjectTypeDef));
  538. try
  539. Result:=N;
  540. ParseObjectBody(N);
  541. Consume(tjsCurlyBraceClose);
  542. except
  543. FreeElement(Result);
  544. Raise;
  545. end;
  546. end;
  547. Function TJSParser.ParseIndexSignature : TJSObjectTypeElementDef;
  548. // On entry, we're on [
  549. // On exit, we're on ;
  550. Var
  551. SigDecl : TJSIndexSignatureDeclaration;
  552. begin
  553. SigDecl:=TJSIndexSignatureDeclaration(CreateElement(TJSIndexSignatureDeclaration));
  554. try
  555. Result:=SigDecl;
  556. Consume(tjsSQuaredBraceOpen);
  557. if (CurrentToken in [TJSToken.tjsNumber,TJSToken.tjsString]) then
  558. begin
  559. SigDecl.IndexName:=CurrentTokenString;
  560. GetNextToken
  561. end
  562. else
  563. SigDecl.IndexName:=ParseIdentifier;
  564. case CurrentToken of
  565. tjsColon :
  566. begin
  567. consume(tjsColon);
  568. expect(tjsIdentifier);
  569. if not (IsIdentifier('number') or IsIdentifier('string')) then
  570. Error(SErrExpectedButFound,['number or string',CurrentTokenString]);
  571. SigDecl.IndexType:=CurrentTokenString;
  572. consume(tjsIdentifier);
  573. end;
  574. tjsIn :
  575. begin
  576. consume(tjsIn);
  577. SigDecl.InIndexType:=ParseTypeDef([ptoAllowLiteral]);
  578. end;
  579. else
  580. if (CurrentToken<>tjsSQuaredBraceClose) then
  581. Error(SErrInvalidIndexSignature);
  582. end;
  583. Consume(tjsSQuaredBraceClose);
  584. SigDecl.IsFunction:=(CurrentToken=tjsBraceOpen);
  585. if SigDecl.IsFunction then
  586. begin
  587. GetNextToken;
  588. Consume(tjsBraceClose);
  589. end;
  590. if (CurrentToken in [tjsMINUS,tjsPlus]) and (PeekNextToken=tjsConditional) then
  591. begin
  592. if (CurrentToken=tjsMINUS) then
  593. SigDecl.Optional:=koDisableOptional
  594. else
  595. SigDecl.Optional:=koForceOptional;
  596. GetNextToken; // put on conditional
  597. end
  598. else if CurrentToken=tjsConditional then
  599. SigDecl.Optional:=koOptional;
  600. // Move to after conditional
  601. if SigDecl.Optional<>koDefault then
  602. GetNextToken;
  603. consume(tjsColon);
  604. SigDecl.ElementType:=ParseTypeDef([ptoAllowLiteral]);
  605. if (not (CurrentToken in [tjsComma,tjsSemiColon])) or FScanner.WasEndOfLine then
  606. Expect(tjsSEMICOLON);
  607. except
  608. FreeElement(SigDecl);
  609. Raise;
  610. end;
  611. end;
  612. function TJSParser.ParseIndexSignatureStatement: TJSIndexSignatureStatement;
  613. begin
  614. Result:=TJSIndexSignatureStatement(CreateElement(TJSIndexSignatureStatement));
  615. try
  616. Result.Decl:=ParseIndexSignature as TJSIndexSignatureDeclaration;
  617. except
  618. FreeElement(Result);
  619. Raise;
  620. end;
  621. end;
  622. Function TJSParser.CurrentTokenIsValidIdentifier : Boolean;
  623. Const
  624. Valididents = [tjsIdentifier,jstoken.tjsString,jstoken.tjsnumber,tjsDelete,
  625. tjsWith,tjsThrow,tjsDefault,tjsAwait,tjscase,tjsdebugger,tjsCatch,
  626. tjsextends,tjsexport,tjsImport,tjsEnum,tjsClass,tjsFor,tjsReturn,
  627. tjsDo,tjsFinally,tjsWhile,tjsIf,tjsYield,tjsvoid,tjsbreak,
  628. tjscontinue, tjsswitch, tjstrue, tjsNull, tjsThis,tjsFalse,
  629. tjsVar,tjsConst, tjsin, tjsInstanceOf, tjsfunction, tjstry,
  630. tjselse, tjsSuper, tjsLet, tjsTypeOf, tjsNew];
  631. begin
  632. Result:=CurrentToken in ValidIdents;
  633. end;
  634. Procedure TJSParser.ParseObjectBody(aObj: TJSObjectTypeDef);
  635. // On entry on {
  636. // On exit on }
  637. Function CreateAny : TJSTypeReference;
  638. begin
  639. Result:=TJSTypeReference(CreateElement(TJSTypeReference));
  640. Result.Name:='any';
  641. end;
  642. var
  643. aName : jsBase.TJSString;
  644. IsMinus, isReadOnly, isOptional : Boolean;
  645. E : TJSObjectTypeElementDef;
  646. F : TJSMethodDeclaration ;
  647. FS : TJSFunctionDeclarationStatement;
  648. TP : TJSElementNodes;
  649. begin
  650. Consume(tjsCurlyBraceOpen);
  651. While (CurrentToken<>tjsCurlyBraceClose) do
  652. begin
  653. aName:='';
  654. E:=Nil;
  655. While CurrentToken=tjsComma do
  656. GetNextToken;
  657. isMinus:=(CurrentToken=tjsMinus);
  658. if IsMinus then
  659. GetNextToken;
  660. isReadOnly:=IsIdentifier('readonly') and not (PeekNextToken in [tjsColon,tjsBraceOpen, tjsConditional]);
  661. if IsReadonly then
  662. GetNextToken
  663. else if IsMinus then
  664. Error(SErrExpectedColonBrace,[CurrentTokenString]);
  665. If CurrentTokenIsValidIdentifier then
  666. begin
  667. aName:=CurrentTokenString;
  668. GetNextToken;
  669. end
  670. else if (Not (CurrentToken in [tjsLT,tjsBraceOpen,tjsSQuaredBraceOpen,tjsNew])) then
  671. Error(SErrObjectElement,[CurrentTokenString]);
  672. isOptional:=(CurrentToken=tjsConditional);
  673. if isOPtional then
  674. GetNextToken;
  675. case CurrentToken of
  676. tjsSQuaredBraceOpen:
  677. begin
  678. // [a:type] : Type
  679. E:=ParseIndexSignature;
  680. end;
  681. // PropertyName : PropertyType
  682. tjsColon:
  683. begin
  684. Consume(tjsColon);
  685. E:=TJSPropertyDeclaration(CreateElement(TJSPropertyDeclaration));
  686. E.Name:=aName;
  687. E.ElementType:=ParseTypeDef([ptoAllowLiteral],[tjsCurlyBraceClose]);
  688. end;
  689. // <T1> () : TypeName;
  690. // () : TypeName;
  691. tjsNew,
  692. tjsLT,
  693. tjsBraceOpen:
  694. begin
  695. if CurrentToken=tjsNew then
  696. begin
  697. aName:='new';
  698. GetNextToken;
  699. end;
  700. TP:=Nil;
  701. F:=TJSMethodDeclaration(CreateElement(TJSMethodDeclaration));
  702. F.Name:=aName;
  703. E:=F;
  704. if CurrentToken=tjsLT then
  705. begin
  706. TP:=TJSElementNodes.Create(TJSElementNode);
  707. ParseGenericParamList(TP);
  708. consume(tjsGT);
  709. end;
  710. FS:=ParseFunctionExpression([ffGenerator]);
  711. F.FuncDef:=FS.AFunction;
  712. FS.AFunction:=Nil;
  713. F.TypeParams:=TP;
  714. if Not Assigned(F.Funcdef.ResultType) then
  715. F.Funcdef.ResultType:=CreateAny;
  716. FreeElement(FS);
  717. end;
  718. tjsComma,tjsSemicolon,tjsCurlyBraceClose:
  719. begin
  720. // PropertyName ; Type is any
  721. E:=TJSPropertyDeclaration(CreateElement(TJSPropertyDeclaration));
  722. E.Name:=aName;
  723. E.ElementType:=CreateAny;
  724. end;
  725. else
  726. Error(SErrExpectedColonBrace,[CurrentTokenString]);
  727. end;
  728. if Assigned(E) then
  729. begin
  730. if IsOptional then
  731. E.Optional:=koOptional;
  732. E.IsReadOnly:=isReadOnly;
  733. aObj.AddElement(E);
  734. end;
  735. While CurrentToken in [tjsComma,tjsSemicolon] do
  736. GetNextToken;
  737. end;
  738. Expect(tjsCurlyBraceClose);
  739. end;
  740. procedure TJSParser.ParseTypeList(aList : TJSElementNodes; aTerminator : TJSToken; ListType: TListType = ltUnknown);
  741. // Entry on < or [, exit on terminator
  742. Var
  743. aSub,aType : TJSTypeDef;
  744. aParam : TJSNamedParamTypeDef;
  745. IsSpread,IsExtends : Boolean;
  746. PTO : TParseTypeOptions;
  747. begin
  748. PTO:=[];
  749. if ListType in [ltTuple,ltTemplate] then
  750. Include(PTO,ptoAllowLiteral);
  751. GetNextToken;
  752. While (CurrentToken<>aTerminator) do
  753. begin
  754. IsSpread:=(CurrentToken=tjsEllipsis);
  755. if IsSpread then
  756. GetNextToken;
  757. IsExtends:=(CurrentToken=tjsExtends);
  758. if IsExtends then
  759. GetNextToken;
  760. aType:=Nil;
  761. aSub:=ParseTypeDef(PTO,[tjsGT,tjsAssign]+[aTerminator]);
  762. try
  763. aSub.IsExtends:=isExtends;
  764. aSub.IsSpread:=isSpread;
  765. if (ListType=ltTemplate) and (CurrentToken=tjsAssign) then
  766. begin
  767. GetNextToken;
  768. aType:=ParseTypeDef([ptoAllowLiteral]);
  769. aParam:=TJSNamedParamTypeDef(CreateElement(TJSNamedParamTypeDef));
  770. aParam.ParamName:=aSub;
  771. aParam.ParamType:=aType;
  772. aType:=Nil;
  773. aSub:=aParam;
  774. aList.AddNode.Node:=aSub;
  775. end
  776. else
  777. begin
  778. if (listType=ltTuple) then
  779. begin
  780. if (CurrentToken=tjsConditional) then
  781. GetNextToken
  782. else if (CurrentToken=tjsColon) then
  783. // Labeled tuple [a:type];
  784. begin
  785. if not (aSub is TJSTypeReference) then
  786. Error(SErrInvalidTupleLabel,[aSub.ClassName]);
  787. Consume(tjsColon);
  788. aParam:=TJSNamedParamTypeDef(CreateElement(TJSNamedParamTypeDef));
  789. aParam.ParamName:=aSub;
  790. aSub:=aParam;
  791. aParam.ParamType:=ParseTypeDef([ptoAllowLiteral]);
  792. end
  793. end;
  794. aList.AddNode.Node:=aSub;
  795. end;
  796. except
  797. FreeElement(aSub);
  798. FreeElement(aType);
  799. Raise;
  800. end;
  801. if CurrentToken=tjsComma then
  802. GetNextToken;
  803. end;
  804. end;
  805. function TJSParser.ParseArrowFunctionTypeDef(const aArgName: jsBase.TJSString; aArgIsSpread: Boolean): TJSArrowFunctionTypeDef;
  806. var
  807. P : TJSTypedParam;
  808. begin
  809. Result:=TJSArrowFunctionTypeDef(CreateElement(TJSArrowFunctionTypeDef));
  810. try
  811. P:=nil;
  812. if (AArgName<>'') then
  813. begin
  814. P:=Result.aFunction.TypedParams.AddParam(aArgName);
  815. P.IsSpread:=aArgIsSpread;
  816. end;
  817. ParseArrowFunctionTypeDef(Result,P);
  818. except
  819. FreeElement(Result);
  820. Raise;
  821. end;
  822. end;
  823. Function TJSParser.ParseArrowFunctionTypeDef (aFirst : TJSObjectTypeDef; aArgIsSpread: Boolean) : TJSArrowFunctionTypeDef;
  824. var
  825. P : TJSTypedParam;
  826. begin
  827. Result:=TJSArrowFunctionTypeDef(CreateElement(TJSArrowFunctionTypeDef));
  828. try
  829. P:=Result.aFunction.TypedParams.AddParam('');
  830. P.Destructured:=aFirst;
  831. P.IsSpread:=aArgIsSpread;
  832. ParseArrowFunctionTypeDef(Result,P);
  833. except
  834. FreeElement(Result);
  835. Raise
  836. end
  837. end;
  838. Procedure TJSParser.ParseArrowFunctionTypeDef(aDef : TJSArrowFunctionTypeDef; aFirstParam : TJSTypedParam);
  839. // On entry, we are on
  840. // ) of a () => Type
  841. // ? or : from the first argument in a (argname : ) => Type
  842. // On exit: first token after the result type
  843. Procedure ParseArgType(P : TJSTypedParam; aIsSpread : Boolean);
  844. // On entry we are on : or ?
  845. // On exit we are on , or )
  846. Var
  847. IsConditional : Boolean;
  848. begin
  849. IsConditional:=CurrentToken=tjsConditional;
  850. if IsConditional then
  851. GetNextToken;
  852. Consume(tjsColon);
  853. With P do
  854. begin
  855. Node:=ParseTypeDef([ptoAllowLiteral]);
  856. IsOptional:=IsConditional;
  857. IsSpread:=aIsSpread;
  858. end;
  859. end;
  860. Var
  861. P : TJSTypedParam;
  862. aName : jsBase.TJSString;
  863. IsSpread : Boolean;
  864. begin
  865. If aFirstParam <> nil then
  866. ParseArgType(aFirstParam,aFirstParam.IsSpread);
  867. While (CurrentToken<>tjsBraceClose) do
  868. begin
  869. if CurrentToken=tjsComma then
  870. Consume(tjscomma);
  871. if CurrentToken<>tjsBraceClose then
  872. begin
  873. isSpread:=(CurrentToken=tjsEllipsis);
  874. if IsSpread then
  875. Consume(tjsEllipsis);
  876. if (CurrentToken=tjsCurlyBraceOpen) then
  877. begin
  878. P:=ParseDestructuredParam(aDef.aFunction.TypedParams);
  879. consume(tjsCurlyBraceClose);
  880. end
  881. else
  882. begin
  883. aName:=ParseIdentifier;
  884. P:=aDef.aFunction.TypedParams.AddParam(aName);
  885. end;
  886. ParseArgType(P,IsSpread);
  887. end;
  888. end;
  889. Consume(tjsBraceClose);
  890. Consume(tjsArrow);
  891. aDef.aFunction.ResultType:=ParseTypeDef([ptoAllowLiteral]);
  892. end;
  893. Function TJSParser.ParseTypeParenthesised (aOptions : TParseTypeOptions): TJSTypeDef;
  894. // On entry, we're on (
  895. // On exit we're after the type: ) or arrow function return type.
  896. Var
  897. aDef : TJSTypeDef;
  898. aArgName : jsbase.TJSString;
  899. isSpread : Boolean;
  900. begin
  901. Result:=nil;
  902. Consume(tjsBraceOpen);
  903. if CurrentToken=tjsBraceClose then
  904. begin
  905. // () => Type
  906. Result:=ParseArrowFunctionTypeDef('',False);
  907. end
  908. else
  909. begin
  910. // (...Ident : ) => Type
  911. isSpread:=(CurrentToken=tjsEllipsis);
  912. // Actually we know it is a function at this point
  913. if IsSpread then
  914. Consume(tjsEllipsis);
  915. aDef:=ParseTypeDef(aOptions - [ptoUnion,ptoIntersection],[tjsColon,tjsConditional]);
  916. // (Ident : ) => Type
  917. if (CurrentToken in [tjsColon,tjsConditional]) then
  918. begin
  919. if (aDef is TJSTypeReference) then
  920. begin
  921. aArgName:=TJSTypeReference(aDef).Name;
  922. FreeElement(aDef);
  923. Result:=ParseArrowFunctionTypeDef(aArgName,IsSpread );
  924. end
  925. else if (aDef is TJSObjectTypeDef) then
  926. Result:=ParseArrowFunctionTypeDef(TJSObjectTypeDef(aDef),IsSpread)
  927. else
  928. Error(SErrorInTypeDef,[SArrowFunction]);
  929. end
  930. // (Type)
  931. else if (CurrentToken=tjsBraceClose) then
  932. begin
  933. Result:=aDef;
  934. Consume(tjsBraceClose);
  935. end
  936. else
  937. Error(SErrorInTypeDef,[SBraceClose])
  938. end;
  939. end;
  940. function TJSParser.ParseTypeSimple(aOptions : TParseTypeOptions): TJSTypeDef;
  941. // On entry, first token of type identifier, or ( or { .
  942. // On exit, first token after type or ) or }
  943. Function ParseRef : TJSTypeReference;
  944. Var
  945. NeedNext : Boolean;
  946. aName : jsbase.TJSString;
  947. begin
  948. Result:=TJSTypeReference(CreateElement(TJSTypeReference));
  949. try
  950. { Result.IsTypeOf:=(CurrentToken=tjsTYPEOF);
  951. if Result.IsTypeof then
  952. GetNextToken;}
  953. NeedNext:=True;
  954. Case CurrentToken of
  955. tjsVoid : aName:='void';
  956. tjsThis : aName:='this';
  957. tjsNull : aName:='null';
  958. tjsNew : aName:='new';
  959. else
  960. aName:=ParseIdentifier;
  961. needNext:=False;
  962. end;
  963. Result.Name:=aName;
  964. if NeedNext then
  965. GetNextToken;
  966. except
  967. FreeElement(Result);
  968. Raise;
  969. end;
  970. end;
  971. Var
  972. CurrT : TJSToken;
  973. isInferred,IsReadOnly,IsTypeOf,IsKeyOf : Boolean;
  974. aName : jsBase.TJSString;
  975. begin
  976. Result:=Nil;
  977. try
  978. isInferred:=IsIdentifier('infer');
  979. if isInferred then
  980. GetNextToken;
  981. IsKeyOf:=IsIdentifier('keyof');
  982. if IsKeyOf then
  983. GetNextToken;
  984. IsReadOnly:=IsIdentifier('readonly');
  985. if IsReadOnly then
  986. GetNextToken;
  987. CurrT:=CurrentToken;
  988. IsTypeOf:=(CurrT=tjsTypeof);
  989. if IsTypeOf then
  990. begin
  991. GetNextToken;
  992. CurrT:=CurrentToken;
  993. end;
  994. Case CurrT of
  995. tjsImport :
  996. begin
  997. Consume(tjsImport);
  998. Consume(tjsBraceOpen);
  999. Expect(tjsToken.tjsString);
  1000. Result:=TJSImportTypeRef(CreateElement(TJSImportTypeRef));
  1001. TJSImportTypeRef(Result).FileName:=CurrentTokenString;
  1002. getNextToken;
  1003. Consume(tjsBraceClose);
  1004. if CurrentToken=tjsDot then
  1005. begin
  1006. GetNextToken;
  1007. TJSImportTypeRef(Result).Name:=ParseIdentifier([tjsDefault]);
  1008. end;
  1009. end;
  1010. tjsVoid,tjsThis,tjsNull,tjsIdentifier:
  1011. begin
  1012. Result:=ParseRef;
  1013. if (ptoFunctionCall in aOptions) then
  1014. if CurrentToken=tjsBraceOpen then
  1015. begin
  1016. aName:=TJSTypeReference(Result).Name;
  1017. FreeElement(Result);
  1018. Result:=TJSTypeFuncCall(CreateElement(TJSTypeFuncCall));
  1019. TJSTypeFuncCall(Result).Name:=aName;
  1020. TJSTypeFuncCall(Result).ArgType:=ParseTypeParenthesised(aOptions);
  1021. end;
  1022. end;
  1023. tjsTrue,tjsFalse,tjsToken.tjsNumber,tjsToken.tjsString :
  1024. if (ptoAllowLiteral in aOptions) then
  1025. begin
  1026. Result:=TJSFixedValueReference(CreateElement(TJSFixedValueReference));
  1027. TJSFixedValueReference(Result).FixedValue:=ParseLiteral as TJSLiteral;
  1028. end;
  1029. tjsNew:
  1030. if PeekNextToken=tjsBraceOpen then
  1031. begin
  1032. GetNextToken;
  1033. Result:=ParseTypeParenthesised(aOptions)
  1034. end
  1035. else
  1036. Result:=ParseRef;
  1037. tjsBraceOpen:
  1038. Result:=ParseTypeParenthesised(aOptions);
  1039. tjsCurlyBraceOpen:
  1040. Result:=ParseTypeObjectDef;
  1041. else
  1042. Result:=Nil;
  1043. end;
  1044. if Assigned(Result) then
  1045. begin
  1046. Result.IsKeyOf:=IsKeyof;
  1047. Result.IsTypeOf:=IsTypeof;
  1048. Result.IsReadOnly:=IsReadonly;
  1049. Result.IsInferred:=IsInferred;
  1050. end;
  1051. except
  1052. FreeElement(Result);
  1053. Raise;
  1054. end
  1055. end;
  1056. Function TJSParser.ParseTypeArrayDef(aOptions : TParseTypeOptions; aSub : TJSTypeDef) : TJSArrayTypeDef;
  1057. // On entry, on [
  1058. // On exit, after ]
  1059. begin
  1060. if aOptions=[] then ;
  1061. Result:=TJSArrayTypeDef(CreateElement(TJSArrayTypeDef));
  1062. Result.BaseType:=aSub;
  1063. Consume(tjsSQuaredBraceOpen);
  1064. if (CurrentToken<>tjsSQuaredBraceClose) then
  1065. Result.IndexType:=ParseTypeDef([ptoAllowLiteral],[tjsSQuaredBraceClose]);
  1066. Consume(tjsSQuaredBraceClose);
  1067. end;
  1068. Procedure TJSParser.ParseTypeUnionIntercept(aType : TJSUnionOrTupleTypeDef; aOptions : TParseTypeOptions; aSeparator : TJSToken);
  1069. {
  1070. // On entry, we're on the | or &
  1071. // On exit, we're after the last type
  1072. }
  1073. Var
  1074. aUnionOptions : TParseTypeOptions;
  1075. begin
  1076. aUnionOptions:=([ptoAllowLiteral] * aOptions);
  1077. if aSeparator=tjsOR then
  1078. Include(aUnionOptions,ptoUnion)
  1079. else
  1080. Include(aUnionOptions,ptoIntersection);
  1081. While (CurrentToken=aSeparator) do
  1082. begin
  1083. Consume(aSeparator);
  1084. {$IFDEF debugParser} Writeln('Union, remains : ',FScanner.CurLine);{$endif}
  1085. aType.AddValue(ParseTypeDef(aUnionOptions,[aSeparator]));
  1086. end;
  1087. end;
  1088. Function TJSParser.ParseTypeTuple(aOptions : TParseTypeOptions) : TJSTupleTypeDef;
  1089. {
  1090. On entry, on [
  1091. on exit, after ]
  1092. }
  1093. begin
  1094. if aOptions=[] then ;;
  1095. Result:=TJSTupleTypeDef(CreateElement(TJSTupleTypeDef));
  1096. ParseTypeList(Result.Values,tjsSQuaredBraceClose,ltTuple);
  1097. Consume(tjsSQuaredBraceClose);
  1098. end;
  1099. function TJSParser.ParseGenericType(aType : TJSTypeDef): TJSTypeDef;
  1100. {
  1101. On Entry : on <
  1102. On Exit : after >
  1103. }
  1104. Var
  1105. RShift: Boolean;
  1106. begin
  1107. Result:=Nil;
  1108. try
  1109. if (aType is TJSTypeReference) and ((TJSTypeReference(aType).Name='Array') or (TJSTypeReference(aType).Name='ReadonlyArray')) then
  1110. begin
  1111. FreeElement(AType);
  1112. Result:=TJSArrayTypeDef(CreateElement(TJSArrayTypeDef));
  1113. consume(tjsLT);
  1114. RShift:=FScanner.DisableRShift;
  1115. FScanner.DisableRShift:=True;
  1116. try
  1117. TJSArrayTypeDef(Result).BaseType:=ParseTypeDef([ptoALlowLiteral],[tjsGT]);
  1118. Finally
  1119. FScanner.DisableRShift:=RShift;
  1120. end;
  1121. consume(tjsGT);
  1122. end
  1123. else
  1124. begin
  1125. Result:=TJSGenericTypeRef(CreateElement(TJSGenericTypeRef));
  1126. TJSGenericTypeRef(Result).BaseType:=aType;
  1127. ParseGenericParamList(TJSGenericTypeRef(Result).Values);
  1128. consume(tjsGT);
  1129. end;
  1130. except
  1131. FreeElement(Result);
  1132. Raise;
  1133. end;
  1134. end;
  1135. Procedure TJSParser.ParseTypeGuard(aType : TJSTypedef; aOptions: TParseTypeOptions; StopTokens : TJSTokens = []);
  1136. {
  1137. on entry, on is or extends
  1138. at exit, on first token after guard
  1139. }
  1140. begin
  1141. if aType=Nil then
  1142. Error(SErrExtendsNeedsTypeName);
  1143. if IsIdentifier('is') then
  1144. begin
  1145. GetNextToken;
  1146. aType.TypeGuard:=ParseTypeDef(aOptions,[tjsComma,tjsAssign,tjsConditional]+StopTokens);
  1147. aType.TypeGuardKind:=tgkIs;
  1148. end
  1149. else if CurrentToken=tjsEXTENDS then
  1150. begin
  1151. GetNextToken;
  1152. aType.ExtendsCond:=ParseTypeDef(aOptions,[tjsComma,tjsAssign,tjsConditional]+StopTokens);
  1153. if CurrentToken=tjsConditional then
  1154. begin
  1155. aType.TypeGuardKind:=tgkExtendsCond;
  1156. Consume(tjsConditional);
  1157. aType.ExtendsTrue:=ParseTypeDef(aOptions,[tjsColon]);
  1158. Consume(tjsColon);
  1159. aType.ExtendsFalse:=ParseTypeDef(aOptions,StopTokens);
  1160. end
  1161. else if CurrentToken=tjsAssign then
  1162. begin
  1163. aType.TypeGuardKind:=tgkExtendsEquals;
  1164. Consume(tjsAssign);
  1165. aType.ExtendsTrue:=ParseTypeDef(aOptions,StopTokens);
  1166. end;
  1167. end;
  1168. end;
  1169. function TJSParser.ParseTypeDef(aOptions : TParseTypeOptions; StopTokens : TJSTokens = []): TJSTypeDef;
  1170. // On entry, first token of the type definition
  1171. // On exit, we are on the first token after the type definition
  1172. Var
  1173. aType,aSub : TJSTypeDef;
  1174. aStruct : TJSStructuredTypeDef;
  1175. CurrT : TJSToken;
  1176. aStop : TJSTokens;
  1177. begin
  1178. aStop:=StopTokens+[tjsbraceClose,tjsGT,tjsSemicolon,tjsComma];
  1179. aStruct:=Nil;
  1180. aType:=Nil;
  1181. Result:=Nil;
  1182. CurrT:=CurrentToken;
  1183. if CurrT in aStop then
  1184. Exit(aType);
  1185. aType:=ParseTypeSimple(aOptions);
  1186. try
  1187. Repeat
  1188. CurrT:=CurrentToken;
  1189. if CurrT in aStop then
  1190. Exit(aType);
  1191. if (CurrT=tjsLT) then
  1192. begin
  1193. ASub:=aType;
  1194. aType:=Nil;
  1195. aType:=ParseGenericType(aSub);
  1196. CurrT:=CurrentToken;
  1197. // a : <>(b:c) => d;
  1198. if (CurrT=tjsBraceOpen) then
  1199. begin
  1200. TJSGenericTypeRef(aType).BaseType:=ParseTypeDef(aOptions,StopTokens);
  1201. CurrT:=CurrentToken;
  1202. end;
  1203. // {
  1204. // A : T<A>
  1205. // [B] : C
  1206. // }
  1207. if FScanner.WasEndOfLine then
  1208. Exit(aType);
  1209. end;
  1210. if CurrT in aStop then
  1211. Exit(aType);
  1212. if (CurrT=tjsSquaredBraceOpen) then
  1213. begin
  1214. if (aType<>Nil) then
  1215. aType:=ParseTypeArrayDef([],aType)
  1216. else
  1217. begin
  1218. aType:=ParseTypeTuple([]);
  1219. if TJSTupleTypeDef(aType).Values.Count=0 then
  1220. begin
  1221. aSub:=aType;
  1222. aType:=TJSArrayTypeDef.Create(aSub.Line,aSub.Column,aSub.Source);
  1223. FreeElement(aSub);
  1224. aSub:=TJSTypeReference.Create(aType.Line,aType.Column,aType.Source);
  1225. TJSTypeReference(aSub).Name:='any';
  1226. TJSArrayTypeDef(aType).BaseType:=aSub;
  1227. end;
  1228. end;
  1229. CurrT:=CurrentToken;
  1230. end;
  1231. if CurrT in aStop then
  1232. Exit(aType);
  1233. case CurrT of
  1234. tjsOR:
  1235. begin
  1236. aStruct:=TJSUnionTypeDef(CreateElement(TJSUnionTypeDef));
  1237. TJSUnionTypeDef(aStruct).AllowEmpty:=aType=Nil;
  1238. if Assigned(aType) then
  1239. aStruct.AddValue(aType);
  1240. aType:=aStruct;
  1241. ParseTypeUnionIntercept(TJSUnionTypeDef(aStruct),aOptions,tjsOR);
  1242. end;
  1243. tjsAnd:
  1244. begin
  1245. aStruct:=TJSIntersectionTypeDef(CreateElement(TJSIntersectionTypeDef));
  1246. TJSIntersectionTypeDef(aStruct).AllowEmpty:=aType=Nil;
  1247. aStruct.AddValue(aType);
  1248. aType:=aStruct;
  1249. ParseTypeUnionIntercept(TJSIntersectionTypeDef(aStruct),aOptions,tjsAnd);
  1250. end;
  1251. tjsExtends :
  1252. ParseTypeGuard(aType,aOptions,aStop);
  1253. else
  1254. if IsIdentifier('is') then
  1255. ParseTypeGuard(aType,aOptions,aStop);
  1256. end;
  1257. CurrT:=CurrentToken;
  1258. Until Not (CurrT in [tjsSquaredBraceOpen,tjsLT]);
  1259. Result:=aType;
  1260. if (Result=Nil) then
  1261. Error(SErrTypeExpected,[CurrentTokenString])
  1262. except
  1263. if (aStruct<>aType) then
  1264. FreeElement(aStruct);
  1265. FreeElement(aType);
  1266. Raise;
  1267. end;
  1268. end;
  1269. Function TJSParser.ParseDestructuredParam(aParams : TJSTypedParams): TJSTypedParam;
  1270. begin
  1271. Result:=aParams.AddParam('');
  1272. try
  1273. Result.Destructured:=TJSObjectTypeDef(CreateElement(TJSObjectTypeDef));
  1274. ParseObjectBody(Result.Destructured);
  1275. Except
  1276. Result.Free;
  1277. Raise;
  1278. end;
  1279. end;
  1280. Procedure TJSParser.ParseFormalParameterList(aParams : TJSTypedParams);
  1281. Var
  1282. P : TJSTypedParam;
  1283. IsSpread : Boolean;
  1284. allowed : TJSTokens;
  1285. aName : jsBase.TJSString;
  1286. begin
  1287. allowed:=[tjsEllipsis, tjsIdentifier];
  1288. if IsTypeScript then
  1289. begin
  1290. Include(Allowed,tjsThis);
  1291. Include(Allowed,tjsCurlyBraceOpen);
  1292. end;
  1293. While (CurrentToken in Allowed) do
  1294. begin
  1295. IsSpread:=(CurrentToken=tjsEllipsis);
  1296. if IsSpread then
  1297. Consume(tjsEllipsis);
  1298. if IsTypeScript and (CurrentToken=tjsThis) then
  1299. P:=aParams.AddParam('this')
  1300. else if IsTypeScript and (CurrentToken=tjsCurlyBraceOpen) then
  1301. P:=ParseDestructuredParam(aParams)
  1302. else
  1303. begin
  1304. Expect(tjsIdentifier);
  1305. aName:=CurrentTokenString;
  1306. P:=aParams.AddParam(aName);
  1307. end;
  1308. P.IsSpread:=IsSpread;
  1309. GetNextToken;
  1310. if IsTypeScript then
  1311. begin
  1312. P.IsOptional:=(CurrentToken=tjsConditional);
  1313. if P.IsOptional then
  1314. Consume(tjsConditional);
  1315. // Type is optional
  1316. if (CurrentToken=tjsColon) then
  1317. begin
  1318. Consume(tjsCOLON);
  1319. P.Node:=ParseTypeDef([ptoAllowLiteral],[tjsBraceClose]);
  1320. end;
  1321. end;
  1322. while (CurrentToken=tjsComma) do
  1323. GetNextToken;
  1324. end;
  1325. end;
  1326. function TJSParser.ParseFunctionDeclaration(aFlags : TFunctionFlags) : TJSFunctionDeclarationStatement;
  1327. Var
  1328. Id : jsBase.TJSString;
  1329. D : TJSFuncDef;
  1330. isGenerator : Boolean;
  1331. TP : TJSElementNodes;
  1332. begin
  1333. {$ifdef debugparser} Writeln('>>> Entering ParseFunctionDeclaration');{$endif debugparser}
  1334. TP:=nil;
  1335. if (ffConstructor in aFlags) then
  1336. consume(tjsIdentifier)
  1337. else if IsTypeScript and IsIdentifier('static') then
  1338. Consume(tjsIdentifier)
  1339. else
  1340. Consume(tjsFunction);
  1341. isGenerator:=(CurrentToken=tjsMUL);
  1342. if IsGenerator then
  1343. Consume(tjsMul);
  1344. if ffConstructor in aFlags then
  1345. ID:='constructor'
  1346. else if CurrentToken=tjsExtends then
  1347. begin
  1348. ID:='extends';
  1349. GetNextToken;
  1350. end
  1351. else
  1352. ID:=ParseIdentifier;
  1353. if CurrentToken=tjsLT then
  1354. begin
  1355. TP:=TJSElementNodes.Create(TJSElementNode);
  1356. ParseGenericParamList(TP);
  1357. consume(tjsGT);
  1358. end;
  1359. Result:=TJSFunctionDeclarationStatement(CreateElement(TJSFunctionDeclarationStatement));
  1360. try
  1361. Result.AFunction:=TJSFuncDef.Create;
  1362. D:=Result.AFunction;
  1363. D.GenericParams:=TP;
  1364. D.Name:=ID;
  1365. D.IsConstructor:=(ffConstructor in aFlags);
  1366. Consume(tjsBraceOpen);
  1367. ParseFormalParameterList(D.TypedParams);
  1368. D.UpdateParams;
  1369. Consume(tjsBraceClose);
  1370. if IsTypeScript and (CurrentToken=tjsColon) then
  1371. begin
  1372. consume(tjsColon);
  1373. D.IsAsserts:=IsIdentifier('asserts');
  1374. if D.IsAsserts then
  1375. Consume(tjsIdentifier);
  1376. D.ResultType:=ParseTypeDef([ptoAllowLiteral]);
  1377. end;
  1378. if not (ffAmbient in aFlags) then
  1379. begin
  1380. Consume(tjsCurlyBraceOpen);
  1381. Inc(FFunctionDepth);
  1382. try
  1383. D.Body:=ParseFunctionBody;
  1384. // GetNextToken; not sure
  1385. Consume(tjsCurlyBraceClose);
  1386. Result.IsGenerator:=IsGenerator;
  1387. finally
  1388. Dec(FFunctionDepth);
  1389. end;
  1390. end;
  1391. except
  1392. FreeAndNil(D);
  1393. Raise;
  1394. end;
  1395. {$ifdef debugparser} Writeln('>>> Exiting ParseFunctionDeclaration');{$endif debugparser}
  1396. end;
  1397. function TJSParser.ParseStatementList : TJSElement;
  1398. Var
  1399. E : TJSElement;
  1400. SL : TJSSTatementList;
  1401. begin
  1402. {$ifdef debugparser} Writeln('>>> ParseStatementList');{$endif debugparser}
  1403. E:=ParseStatement;
  1404. try
  1405. if (CurrentToken in [tjsCurlyBraceClose,tjsEof,tjsCase,tjsDefault]) then
  1406. Result:=E
  1407. else
  1408. begin
  1409. SL:=TJSSTatementList(CreateElement(TJSStatementList));
  1410. try
  1411. SL.A:=E;
  1412. SL.B:=ParseStatementlist();
  1413. Result:=SL;
  1414. except
  1415. FreeElement(SL);
  1416. Raise;
  1417. end;
  1418. end;
  1419. except
  1420. FreeElement(E);
  1421. Raise;
  1422. end;
  1423. {$ifdef debugparser} Writeln('<<< ParseStatementList');{$endif debugparser}
  1424. end;
  1425. function TJSParser.ParseBlock : TJSElement;
  1426. begin
  1427. {$ifdef debugparser} Writeln('>>> ParseBlock');{$endif debugparser}
  1428. Consume(tjsCurlyBraceOpen);
  1429. If (CurrentToken=tjsCurlyBraceClose) then
  1430. Result:=CreateElement(TJSEmptyBlockStatement)
  1431. else
  1432. result:=ParseStatementList;
  1433. Consume(tjsCurlyBraceClose);
  1434. {$ifdef debugparser} Writeln('<<< ParseBlock');{$endif debugparser}
  1435. end;
  1436. function TJSParser.ParseArrayLiteral: TJSElement;
  1437. Var
  1438. N : TJSArrayLiteral;
  1439. E : TJSArrayLiteralElement;
  1440. I : Integer;
  1441. begin
  1442. Consume(tjsSquaredBraceOpen);
  1443. N:=TJSArrayLiteral(CreateElement(TJSArrayLiteral));
  1444. Result:=N;
  1445. try
  1446. I:=0;
  1447. While (CurrentToken<>tjsSquaredBraceClose) do
  1448. begin
  1449. If (CurrentToken=tjsComma) then
  1450. begin
  1451. GetNextToken;
  1452. Inc(I);
  1453. end
  1454. else
  1455. begin
  1456. E:=N.Elements.AddElement;
  1457. E.ElementIndex:=I;
  1458. Inc(I);
  1459. E.Expr:=ParseAssignmentExpression;
  1460. If Not (CurrentToken in [tjsComma,tjsSquaredBraceClose]) then
  1461. Error(SErrArrayEnd,[CurrentTokenString])
  1462. end;
  1463. end;
  1464. Consume(tjsSquaredBraceClose);
  1465. except
  1466. FreeElement(Result);
  1467. Raise;
  1468. end;
  1469. end;
  1470. function TJSParser.ParseObjectLiteral: TJSElement;
  1471. Var
  1472. N : TJSObjectLiteral;
  1473. NeedAssign : Boolean;
  1474. E : TJSObjectLiteralElement;
  1475. begin
  1476. Consume(tjsCurlyBraceOpen);
  1477. N:=TJSObjectLiteral(CreateElement(TJSObjectLiteral));
  1478. Result:=N;
  1479. try
  1480. While (CurrentToken<>tjsCurlyBraceClose) do
  1481. begin
  1482. While CurrentToken=tjsComma do
  1483. GetNextToken;
  1484. NeedAssign:=True;
  1485. If (CurrentToken in [tjsIdentifier,jstoken.tjsString,jstoken.tjsnumber]) then
  1486. begin
  1487. E:=N.Elements.AddElement;
  1488. E.Name:=CurrentTokenString;
  1489. GetNextToken;
  1490. end
  1491. else If (CurrentToken=tjsMul) and (EcmaVersion>=MinGeneratorVersion) then
  1492. begin
  1493. E:=N.Elements.AddElement;
  1494. E.Expr:= ParseFunctionExpression([ffGenerator]);
  1495. E.Name:=TJSFunctionDeclarationStatement(E.Expr).AFunction.Name;
  1496. NeedAssign:=False;
  1497. end
  1498. else
  1499. Error(SErrObjectElement,[CurrentTokenString]);
  1500. if needAssign then
  1501. begin
  1502. Consume(tjsColon);
  1503. E.Expr:=ParseAssignmentExpression;
  1504. end;
  1505. While CurrentToken=tjsComma do
  1506. GetNextToken;
  1507. { If Not (CurrentToken in [tjsComma,tjsCurlyBraceClose]) then
  1508. Error(SErrObjectEnd,[CurrentTokenString])}
  1509. end;
  1510. Consume(tjsCurlyBraceClose);
  1511. except
  1512. FreeElement(Result);
  1513. Raise;
  1514. end;
  1515. end;
  1516. function TJSParser.ParseNumericLiteral: TJSElement;
  1517. Var
  1518. L : TJSLiteral;
  1519. D : Double;
  1520. I : Integer;
  1521. begin
  1522. {$ifdef debugparser} Writeln('Parsing numerical literal');{$endif debugparser}
  1523. Result:=Nil;
  1524. try
  1525. if Pos('0x',CurrentTokenString) = 1 then
  1526. begin
  1527. D:=StrToInt('$'+UTF8Encode(Copy(CurrentTokenString,3,Length(CurrentTokenString)-2)));
  1528. I:=0;
  1529. end
  1530. else
  1531. Val(CurrentTokenString,D,I);
  1532. If (I>0) then
  1533. Error(SErrInvalidnumber,[CurrentTokenString]);
  1534. L:=TJSLiteral(CreateElement(TJSLiteral));
  1535. GetNextToken;
  1536. L.Value.AsNumber:=D;
  1537. Result:=L;
  1538. except
  1539. FreeElement(Result);
  1540. Raise;
  1541. end;
  1542. end;
  1543. function TJSParser.ParseStringLiteral: TJSElement;
  1544. Var
  1545. L : TJSLiteral;
  1546. begin
  1547. {$ifdef debugparser} Writeln('Parsing string literal');{$endif debugparser}
  1548. Result:=Nil;
  1549. try
  1550. L:=TJSLiteral(CreateElement(TJSLiteral));
  1551. L.Value.AsString:=CurrentTokenString;
  1552. GetNextToken;
  1553. Result:=L;
  1554. except
  1555. FreeElement(Result);
  1556. Raise;
  1557. end;
  1558. end;
  1559. function TJSParser.ParseRegularExpressionLiteral: TJSElement;
  1560. Var
  1561. S,pa,fl : jsBase.TJSString;
  1562. P : integer;
  1563. R : TJSRegularExpressionLiteral;
  1564. begin
  1565. Result:=Nil;
  1566. If (CurrentToken=tjsRegex) then
  1567. begin
  1568. S:=CurrentTokenString;
  1569. P:=Length(S);
  1570. While (P>=1) and (S[P]<>'/') do
  1571. Dec(P);
  1572. If (P<=1) then
  1573. Error(SErrInvalidRegularExpression,[CurrentTokenString]);
  1574. pa:=Copy(S,2,P-1);
  1575. fl:=Copy(S,P,Length(S)-P+1);
  1576. R:=TJSRegularExpressionLiteral(CreateElement(TJSRegularExpressionLiteral));
  1577. Result:=R;
  1578. R.Pattern.AsString:=Pa;
  1579. R.PatternFlags.AsString:=Fl;
  1580. R.Argv[0]:=R.Pattern;
  1581. R.Argv[1]:=R.PatternFlags;
  1582. end;
  1583. try
  1584. Consume(tjsRegEx);
  1585. except
  1586. FreeElement(Result);
  1587. Raise;
  1588. end;
  1589. end;
  1590. function TJSParser.ParseLiteral: TJSElement;
  1591. Var
  1592. L : TJSLiteral;
  1593. begin
  1594. {$ifdef debugparser}Writeln('Parsing literal: ',GetEnumName(TypeInfo(TJSToken),Ord(CurrentToken)), ' As string: ',CurrentTokenString);{$endif debugparser}
  1595. Result:=Nil;
  1596. Case CurrentToken of
  1597. tjsNull : begin
  1598. L:=TJSLiteral(CreateElement(TJSLiteral));
  1599. Result:=L;
  1600. L.Value.IsNull:=True;
  1601. GetNextToken;
  1602. end;
  1603. tjsTrue,
  1604. tjsFalse: begin
  1605. L:=TJSLiteral(CreateElement(TJSLiteral));
  1606. Result:=L;
  1607. L.Value.AsBoolean:=(CurrentToken=tjsTrue);
  1608. GetNextToken;
  1609. end;
  1610. jstoken.tjsNumber : Result:=ParseNumericLiteral;
  1611. jstoken.tjsString : Result:=ParseStringLiteral;
  1612. tjsDiv,
  1613. tjsDivEq : Result:=ParseRegularExpressionLiteral
  1614. else
  1615. Error(SErrLiteralExpected,[CurrentTokenString]);
  1616. end;
  1617. end;
  1618. function TJSParser.ParsePrimaryExpression: TJSElement;
  1619. Var
  1620. R : TJSPrimaryExpressionIdent;
  1621. AYS : TJSUnaryExpression;
  1622. begin
  1623. {$ifdef debugparser} Writeln('ParsePrimaryExpression');{$endif debugparser}
  1624. AYS:=Nil;
  1625. Result:=Nil;
  1626. try
  1627. if (CurrentToken in [tjsYield,tjsAwait]) then
  1628. begin
  1629. if CurrentToken=tjsYield then
  1630. AYS:=TJSUnaryExpression(CreateElement(TJSYieldExpression))
  1631. else
  1632. AYS:=TJSUnaryExpression(CreateElement(TJSAwaitExpression));
  1633. GetNextToken;
  1634. end;
  1635. Case CurrentToken of
  1636. tjsThis :
  1637. begin
  1638. Result:=TJSPrimaryExpressionThis(CreateElement(TJSPrimaryExpressionThis));
  1639. GetNextToken;
  1640. end;
  1641. tjsidentifier:
  1642. begin
  1643. R:=TJSPrimaryExpressionIdent(CreateElement(TJSPrimaryExpressionIdent));
  1644. Result:=R;
  1645. R.Name:=CurrentTokenString;
  1646. GetNextToken;
  1647. end;
  1648. tjsSquaredBraceOpen: Result:=ParseArrayLiteral;
  1649. tjsCurlyBraceOpen: Result:=ParseObjectLiteral;
  1650. tjsBraceOpen:
  1651. begin
  1652. Consume(tjsBraceOpen);
  1653. Result:=ParseExpression;
  1654. Consume(tjsBraceClose);
  1655. end;
  1656. else
  1657. Result:=ParseLiteral;
  1658. end; // Case;
  1659. if (AYS<>Nil) then
  1660. begin
  1661. AYS.A:=Result;
  1662. Result:=AYS;
  1663. end;
  1664. except
  1665. FreeElement(Result);
  1666. Raise;
  1667. end;
  1668. {$ifdef debugparser} Writeln('Exit ParsePrimaryExpression');{$endif debugparser}
  1669. end;
  1670. function TJSParser.ParseMemberExpression: TJSElement;
  1671. Var
  1672. M : TJSDotMemberExpression;
  1673. N : TJSNewMemberExpression;
  1674. B : TJSBracketMemberExpression;
  1675. Done : Boolean;
  1676. begin
  1677. {$ifdef debugparser} Writeln('ParseMemberExpression');{$endif debugparser}
  1678. Case CurrentToken of
  1679. tjsClass : Result:=ParseClassExpression();
  1680. tjsFunction : Result:=ParseFunctionExpression([ffGenerator]);
  1681. tjsNew : begin
  1682. GetNextToken;
  1683. N:=TJSNewMemberExpression(CreateElement(TJSNewMemberExpression));
  1684. try
  1685. Result:=N;
  1686. N.MExpr:=ParseMemberExpression();
  1687. if (CurrentToken=tjsBraceOpen) then
  1688. N.Args:=ParseArguments;
  1689. except
  1690. FreeElement(N);
  1691. Raise;
  1692. end;
  1693. end;
  1694. else
  1695. Result:=ParsePrimaryExpression()
  1696. end;
  1697. try
  1698. Done:=False;
  1699. Repeat
  1700. Case CurrentToken of
  1701. tjsDot :
  1702. begin
  1703. M:=TJSDotMemberExpression(CreateElement(TJSDotMemberExpression));
  1704. M.MExpr:=Result;
  1705. Result:=M;
  1706. GetNextToken;
  1707. If (CurrentToken=tjsIdentifier) then
  1708. M.Name:=CurrentTokenString;
  1709. Consume(tjsIdentifier);
  1710. end;
  1711. tjsSquaredBraceOpen:
  1712. begin
  1713. B:=TJSBracketMemberExpression(CreateElement(TJSBracketMemberExpression));
  1714. B.MExpr:=Result;
  1715. Result:=B;
  1716. GetNextToken;
  1717. B.Name:=ParseExpression();
  1718. Consume(tjsSquaredBraceClose);
  1719. end;
  1720. else
  1721. Done:=True;
  1722. isLHS:=True;
  1723. end;
  1724. Until Done;
  1725. except
  1726. FreeElement(Result);
  1727. Raise;
  1728. end;
  1729. {$ifdef debugparser} Writeln('Exit ParseMemberExpression');{$endif debugparser}
  1730. end;
  1731. function TJSParser.ParseModuleDeclarationStatement: TJSModuleStatement;
  1732. begin
  1733. Result:=TJSModuleStatement(CreateElement(TJSModuleStatement));
  1734. try
  1735. Result.Decl:=ParseModuleDeclaration;
  1736. except
  1737. FreeElement(Result);
  1738. Raise;
  1739. end;
  1740. end;
  1741. function TJSParser.ParseArguments: TJSarguments;
  1742. Var
  1743. E : TJSArrayLiteralElement;
  1744. begin
  1745. Consume(tjsBraceOpen);
  1746. Result:=TJSArguments(CreateElement(TJSArguments));
  1747. try
  1748. While (CurrentToken<>tjsBraceClose) do
  1749. begin
  1750. E:=Result.Elements.AddElement;
  1751. E.Expr:=ParseAssignmentExpression;
  1752. If (CurrentToken<>tjsBraceClose) then
  1753. If CurrentToken=tjsComma then
  1754. GetNextToken
  1755. else
  1756. Error(SErrArgumentsExpected,[CurrentTokenString]);
  1757. end;
  1758. Consume(tjsBraceClose);
  1759. except
  1760. FreeElement(Result);
  1761. Raise;
  1762. end;
  1763. end;
  1764. function TJSParser.ParseLeftHandSideExpression: TJSElement;
  1765. Var
  1766. M : TJSDotMemberExpression;
  1767. B : TJSBracketMemberExpression;
  1768. C : TJSCallExpression;
  1769. Done : Boolean;
  1770. begin
  1771. {$ifdef debugparser} Writeln('ParseLeftHandSideExpression');{$endif debugparser}
  1772. Case CurrentToken of
  1773. tjsClass : Result:=ParseClassExpression;
  1774. tjsFunction : Result:=ParseFunctionExpression([]);
  1775. tjsNew : Result:=ParseMemberExpression;
  1776. else
  1777. Result:=ParsePrimaryExpression
  1778. end;
  1779. try
  1780. Done:=False;
  1781. Repeat
  1782. Case CurrentToken of
  1783. tjsDot :
  1784. begin
  1785. M:=TJSDotMemberExpression(CreateElement(TJSDotMemberExpression));
  1786. M.MExpr:=Result;
  1787. Result:=M;
  1788. GetNextToken;
  1789. If (CurrentToken=tjsIdentifier) then
  1790. M.Name:=CurrentTokenString;
  1791. Consume(tjsIdentifier);
  1792. end;
  1793. tjsSquaredBraceOpen:
  1794. begin
  1795. B:=TJSBracketMemberExpression(CreateElement(TJSBracketMemberExpression));
  1796. B.MExpr:=Result;
  1797. Result:=B;
  1798. GetNextToken;
  1799. B.Name:=ParseExpression;
  1800. Consume(tjsSquaredBraceClose);
  1801. end;
  1802. tjsBraceOpen:
  1803. begin
  1804. C:=TJSCallExpression(CreateElement(TJSCallExpression));
  1805. if (Result is TJSUnaryExpression) and (TJSUnaryExpression(Result).PrefixOperatorToken in [tjsAwait,tjsYield]) then
  1806. begin
  1807. C.Expr:=TJSUnaryExpression(Result).A;
  1808. TJSUnaryExpression(Result).A:=C;
  1809. end
  1810. else
  1811. begin
  1812. C.Expr:=Result;
  1813. Result:=C;
  1814. end;
  1815. C.Args:=ParseArguments;
  1816. end;
  1817. else
  1818. {$ifdef debugparser}Writeln('Leaving LHS');{$endif debugparser}
  1819. Done:=True;
  1820. isLHS:=True;
  1821. end;
  1822. Until Done;
  1823. except
  1824. FreeElement(Result);
  1825. Raise;
  1826. end;
  1827. {$ifdef debugparser} Writeln('Exit ParseLeftHandSideExpression');{$endif debugparser}
  1828. end;
  1829. function TJSParser.ParsePostFixExpression: TJSElement;
  1830. Var
  1831. R : TJSUnaryExpression;
  1832. begin
  1833. {$ifdef debugparser} Writeln('ParsePostfixExpression');{$endif debugparser}
  1834. Result:=ParseLeftHandSideExpression;
  1835. Try
  1836. If (Not IsEndOfLine) and (CurrentToken in [tjsPlusPlus,tjsMinusMinus]) then
  1837. begin
  1838. If (CurrentToken=tjsPlusPLus) then
  1839. R:=TJSUnaryExpression(CreateElement(TJSUnaryPostPlusPlusExpression))
  1840. else
  1841. R:=TJSUnaryExpression(CreateElement(TJSUnaryPostMinusMinusExpression));
  1842. R.A:=Result;
  1843. Result:=R;
  1844. GetNextToken;
  1845. isLHS:=False;
  1846. end;
  1847. except
  1848. FreeElement(Result);
  1849. Raise;
  1850. end;
  1851. {$ifdef debugparser} Writeln('Exit ParsePostfixExpression');{$endif debugparser}
  1852. end;
  1853. function TJSParser.ParseUnaryExpression: TJSElement;
  1854. Var
  1855. C : TJSElementClass;
  1856. R : TJSUnaryExpression;
  1857. begin
  1858. {$ifdef debugparser} Writeln('ParseUnaryExpression');{$endif debugparser}
  1859. C:=Nil;
  1860. Result:=Nil;
  1861. try
  1862. Case CurrentToken of
  1863. tjsDelete : C:=TJSUnaryDeleteExpression;
  1864. tjsVoid : C:=TJSUnaryVoidExpression;
  1865. tjsTypeOf : C:=TJSUnaryTypeOfExpression;
  1866. tjsPlusPlus : C:=TJSUnaryPrePlusPlusExpression;
  1867. tjsMinusMinus : C:=TJSUnaryPreMinusMinusExpression;
  1868. tjsPlus : C:=TJSUnaryPlusExpression;
  1869. tjsMinus : C:=TJSUnaryMinusExpression;
  1870. tjsInv : C:=TJSUnaryInvExpression;
  1871. tjsNot : C:=TJSUnaryNotExpression;
  1872. else
  1873. Result:=ParsePostFixExpression;
  1874. end;
  1875. If (Result=Nil) then
  1876. begin
  1877. {$ifdef debugparser} Writeln('Found Unary Expression',GetEnumName(TypeInfo(TJSToken),Ord(CurrentToken)), ' As string: ',CurrentTokenString);{$endif debugparser}
  1878. R:=TJSUnaryExpression(CreateElement(C));
  1879. Result:=R;
  1880. GetNextToken;
  1881. R.A:=ParseUnaryExpression();
  1882. isLHS:=False;
  1883. end;
  1884. except
  1885. FreeElement(Result);
  1886. Raise;
  1887. end;
  1888. {$ifdef debugparser} Writeln('Exit ParseUnaryExpression');{$endif debugparser}
  1889. end;
  1890. function TJSParser.ParseDebuggerStatement: TJSElement;
  1891. begin
  1892. Result:=CreateElement(TJSDebuggerStatement);
  1893. try
  1894. Consume(tjsDebugger);
  1895. except
  1896. FreeElement(Result);
  1897. end;
  1898. end;
  1899. function TJSParser.ParseMultiplicativeExpression: TJSElement;
  1900. Var
  1901. C : TJSElementClass;
  1902. R : TJSMultiplicativeExpression;
  1903. begin
  1904. {$ifdef debugparser} Writeln('ParseMultiplicativeExpression');{$endif debugparser}
  1905. Result:=ParseUnaryExpression;
  1906. try
  1907. While (CurrentToken in [tjsMul,tjsDiv,tjsMod]) do
  1908. begin
  1909. if CurrentToken=tjsMul then
  1910. C:=TJSMultiplicativeExpressionMul
  1911. else if CurrentToken=tjsDiv then
  1912. C:=TJSMultiplicativeExpressionDiv
  1913. else
  1914. C:=TJSMultiplicativeExpressionMod;
  1915. R:=TJSMultiplicativeExpression(CreateElement(C));
  1916. GetNextToken;
  1917. R.A:=Result;
  1918. Result:=R;
  1919. R.B:=ParseUnaryExpression;
  1920. isLHS:=False;
  1921. end;
  1922. except
  1923. FreeElement(Result);
  1924. Raise;
  1925. end;
  1926. {$ifdef debugparser} Writeln('Exit ParseMultiplicativeExpression');{$endif debugparser}
  1927. end;
  1928. function TJSParser.ParseNamespaceDeclarationStatement: TJSNamespaceStatement;
  1929. begin
  1930. Result:=TJSNamespaceStatement(CreateElement(TJSNameSpaceStatement));
  1931. try
  1932. Result.Decl:=ParseNameSpaceDeclaration(True);
  1933. except
  1934. FreeElement(Result);
  1935. Raise;
  1936. end;
  1937. end;
  1938. function TJSParser.ParseAdditiveExpression: TJSElement;
  1939. Var
  1940. C : TJSElementClass;
  1941. R : TJSAdditiveExpression;
  1942. begin
  1943. {$ifdef debugparser} Writeln('ParseAdditiveExpression');{$endif debugparser}
  1944. Result:=ParseMultiplicativeExpression;
  1945. try
  1946. While (CurrentToken in [tjsPlus,tjsMinus]) do
  1947. begin
  1948. if CurrentToken=tjsPlus then
  1949. C:=TJSAdditiveExpressionPlus
  1950. else
  1951. C:=TJSAdditiveExpressionMinus;
  1952. R:=TJSAdditiveExpression(CreateElement(C));
  1953. GetNextToken;
  1954. R.A:=Result;
  1955. Result:=R;
  1956. R.B:=ParseMultiplicativeExpression;
  1957. isLHS:=False;
  1958. end;
  1959. except
  1960. FreeElement(Result);
  1961. Raise;
  1962. end;
  1963. {$ifdef debugparser} Writeln('Exit ParseAdditiveExpression');{$endif debugparser}
  1964. end;
  1965. function TJSParser.ParseShiftExpression: TJSElement;
  1966. Var
  1967. C : TJSElementClass;
  1968. R : TJSShiftExpression;
  1969. begin
  1970. {$ifdef debugparser} Writeln('ParseShiftExpression');{$endif debugparser}
  1971. Result:=ParseAdditiveExpression;
  1972. try
  1973. While (CurrentToken in [tjsLshift,tjsRshift,tjsURShift]) do
  1974. begin
  1975. Case CurrentToken of
  1976. tjsLshift : C:=TJSLShiftExpression;
  1977. tjsRshift : C:=TJSRShiftExpression;
  1978. tjsURshift : C:=TJSURShiftExpression;
  1979. end;
  1980. R:=TJSShiftExpression(CreateElement(C));
  1981. R.A:=Result;
  1982. Result:=R;
  1983. GetNextToken;
  1984. R.B:=ParseAdditiveExpression;
  1985. IsLHS:=False;
  1986. end;
  1987. except
  1988. FreeElement(Result);
  1989. Raise;
  1990. end;
  1991. {$ifdef debugparser} Writeln('Exit ParseShiftExpression');{$endif debugparser}
  1992. end;
  1993. function TJSParser.ParseRelationalExpression: TJSElement;
  1994. Var
  1995. S : Set of TJSToken;
  1996. C : TJSElementClass;
  1997. R : TJSRelationalExpression;
  1998. begin
  1999. {$ifdef debugparser} Writeln('ParseRelationalExpression');{$endif debugparser}
  2000. Result:=ParseShiftExpression;
  2001. try
  2002. S:=[tjsLT,tjsGT,tjsLE,tjsGE,tjsInstanceOf];
  2003. If Not Noin then
  2004. Include(S,tjsIn);
  2005. While (CurrentToken in S) do
  2006. begin
  2007. Case CurrentToken of
  2008. tjsLT : C:=TJSRelationalExpressionLT;
  2009. tjsGT : C:=TJSRelationalExpressionGT;
  2010. tjsLE : C:=TJSRelationalExpressionLE;
  2011. tjsGE : C:=TJSRelationalExpressionGE;
  2012. tjsInstanceOf :C:=TJSRelationalExpressionInstanceOf;
  2013. tjsIn : C:=TJSRelationalExpressionIn;
  2014. end;
  2015. R:=TJSRelationalExpression(CreateElement(C));
  2016. R.A:=Result;
  2017. Result:=R;
  2018. GetNextToken;
  2019. R.B:=ParseRelationalExpression();
  2020. IsLHS:=False;
  2021. end;
  2022. except
  2023. FreeElement(Result);
  2024. Raise;
  2025. end;
  2026. {$ifdef debugparser} Writeln('Exit ParseRelationalExpression');{$endif debugparser}
  2027. end;
  2028. function TJSParser.ParseEqualityExpression: TJSElement;
  2029. Var
  2030. C : TJSElementClass;
  2031. E : TJSEqualityExpression;
  2032. begin
  2033. {$ifdef debugparser} Writeln('ParseEqualityExpression');{$endif debugparser}
  2034. Result:=ParseRelationalExpression;
  2035. try
  2036. While (CurrentToken in [tjsEq,tjsNE,tjsSEQ,tjsSNE]) do
  2037. begin
  2038. Case CurrentToken of
  2039. tjsEq : C:=TJSEqualityExpressionEQ;
  2040. tjsNE : C:=TJSEqualityExpressionNE;
  2041. tjsSEQ : C:=TJSEqualityExpressionSEQ;
  2042. tjsSNE : C:=TJSEqualityExpressionSNE;
  2043. end;
  2044. GetNextToken;
  2045. E:=TJSEqualityExpression(CreateElement(C));
  2046. Result:=E;
  2047. E.A:=Result;
  2048. E.B:=ParseEqualityExpression();
  2049. E:=Nil;
  2050. IsLHS:=False;
  2051. end;
  2052. except
  2053. FreeElement(Result);
  2054. Raise;
  2055. end;
  2056. {$ifdef debugparser} Writeln('Exit ParseEqualityExpression');{$endif debugparser}
  2057. end;
  2058. function TJSParser.ParseBitwiseAndExpression: TJSElement;
  2059. Var
  2060. L : TJSBitwiseAndExpression;
  2061. begin
  2062. {$ifdef debugparser} Writeln('ParseBitwiseAndExpression');{$endif debugparser}
  2063. Result:=ParseEqualityExpression;
  2064. try
  2065. If (CurrentToken<>tjsAnd) then
  2066. exit;
  2067. GetNextToken;
  2068. L:=TJSBitwiseAndExpression(CreateElement(TJSBitwiseAndExpression));
  2069. L.A:=Result;
  2070. Result:=L;
  2071. L.B:=ParseBitwiseAndExpression();
  2072. IsLHS:=False;
  2073. except
  2074. FreeElement(Result);
  2075. Raise;
  2076. end;
  2077. {$ifdef debugparser} Writeln('Exit ParseBitwiseAndExpression');{$endif debugparser}
  2078. end;
  2079. function TJSParser.ParseBitwiseXORExpression: TJSElement;
  2080. Var
  2081. L : TJSBitwiseXOrExpression;
  2082. begin
  2083. {$ifdef debugparser} Writeln('ParseBitwiseXorExpression');{$endif debugparser}
  2084. Result:=ParseBitwiseAndExpression;
  2085. try
  2086. If (CurrentToken<>tjsXOr) then
  2087. exit;
  2088. GetNextToken;
  2089. L:=TJSBitwiseXOrExpression(CreateElement(TJSBitwiseXOrExpression));
  2090. L.A:=Result;
  2091. Result:=L;
  2092. L.B:=ParseBitwiseXORExpression();
  2093. IsLHS:=False;
  2094. except
  2095. FreeElement(Result);
  2096. Raise;
  2097. end;
  2098. {$ifdef debugparser} Writeln('Exit ParseBitwiseXorExpression');{$endif debugparser}
  2099. end;
  2100. function TJSParser.ParseBitwiseORExpression: TJSElement;
  2101. Var
  2102. L : TJSBitwiseOrExpression;
  2103. begin
  2104. {$ifdef debugparser} Writeln('ParseBitWiseOrExpression');{$endif debugparser}
  2105. Result:=ParseBitwiseXORExpression;
  2106. try
  2107. If (CurrentToken<>tjsOr) then
  2108. exit;
  2109. GetNextToken;
  2110. L:=TJSBitwiseOrExpression(CreateElement(TJSBitwiseOrExpression));
  2111. L.A:=Result;
  2112. Result:=L;
  2113. L.B:=ParseBitwiseORExpression();
  2114. IsLHS:=False;
  2115. except
  2116. FreeElement(Result);
  2117. Raise;
  2118. end;
  2119. {$ifdef debugparser} Writeln('Exit ParseBitWiseOrExpression');{$endif debugparser}
  2120. end;
  2121. function TJSParser.ParseLogicalAndExpression: TJSElement;
  2122. Var
  2123. L : TJSLogicalAndExpression;
  2124. begin
  2125. {$ifdef debugparser} Writeln('ParseLogicalAndExpression');{$endif debugparser}
  2126. Result:=ParseBitwiseORExpression;
  2127. try
  2128. If (CurrentToken<>tjsAndAnd) then
  2129. exit;
  2130. GetNextToken;
  2131. L:=TJSLogicalAndExpression(CreateElement(TJSLogicalAndExpression));
  2132. L.A:=Result;
  2133. Result:=L;
  2134. L.B:=ParseLogicalAndExpression();
  2135. IsLHS:=False;
  2136. except
  2137. FreeElement(Result);
  2138. Raise;
  2139. end;
  2140. {$ifdef debugparser} Writeln('Exit ParseLogicalAndExpression');{$endif debugparser}
  2141. end;
  2142. function TJSParser.ParseLogicalORExpression: TJSElement;
  2143. Var
  2144. L : TJSLogicalOrExpression;
  2145. begin
  2146. {$ifdef debugparser} Writeln('ParseLogicalOrExpression');{$endif debugparser}
  2147. Result:=ParseLogicalAndExpression;
  2148. try
  2149. If (CurrentToken<>tjsOROR) then
  2150. exit;
  2151. GetNextToken;
  2152. L:=TJSLogicalOrExpression(CreateElement(TJSLogicalOrExpression));
  2153. L.A:=Result;
  2154. Result:=L;
  2155. L.B:=ParseLogicalOrExpression();
  2156. IsLHS:=False;
  2157. except
  2158. FreeElement(Result);
  2159. Raise;
  2160. end;
  2161. {$ifdef debugparser} Writeln('Exit ParseLogicalOrExpression');{$endif debugparser}
  2162. end;
  2163. function TJSParser.ParseConditionalExpression: TJSElement;
  2164. Var
  2165. N : TJSConditionalExpression;
  2166. L : TJSElement;
  2167. begin
  2168. {$ifdef debugparser} Writeln('ParseConditionalExpression');{$endif debugparser}
  2169. Result:=Nil;
  2170. Result:=ParseLogicalORExpression;
  2171. try
  2172. If (CurrentToken=tjsConditional) then
  2173. begin
  2174. {$ifdef debugparser} Writeln('ParseConditionalExpression : Detected conditional ');{$endif debugparser}
  2175. GetNextToken;
  2176. L:=Result;
  2177. N:=TJSConditionalExpression(CreateElement(TJSConditionalExpression));
  2178. Result:=N;
  2179. N.A:=L;
  2180. L:=Nil;
  2181. N.B:=ParseAssignmentExpression;
  2182. Consume(tjsColon);
  2183. N.C:=ParseAssignmentExpression;
  2184. IsLHS:=False;
  2185. end;
  2186. except
  2187. FreeElement(Result);
  2188. end;
  2189. {$ifdef debugparser} Writeln('Exit ParseConditionalExpression');{$endif debugparser}
  2190. end;
  2191. function TJSParser.ParseAssignmentExpression: TJSElement;
  2192. Var
  2193. N : TJSElement;
  2194. C : TJSElementClass;
  2195. A : TJSAssignStatement;
  2196. begin
  2197. {$ifdef debugparser} Writeln('ParseAssignmentExpression');{$endif debugparser}
  2198. Result:=Nil;
  2199. C:=Nil;
  2200. N:=ParseConditionalExpression;
  2201. If not isLHS then
  2202. Result:=N
  2203. else
  2204. Case CurrentToken of
  2205. tjsAssign : C:=TJSSimpleAssignStatement;
  2206. tjsMulEq : C:=TJSMulEqAssignStatement;
  2207. tjsDivEq : C:=TJSDivEqAssignStatement;
  2208. tjsModEq : C:=TJSModEqAssignStatement;
  2209. tjsPlusEq : C:=TJSAddEqAssignStatement;
  2210. tjsMinusEq : C:=TJSSubEqAssignStatement;
  2211. tjsLShiftEq : C:=TJSLShiftEqAssignStatement;
  2212. tjsRShiftEq : C:=TJSRShiftEqAssignStatement;
  2213. tjsURShiftEq : C:=TJSURShiftEqAssignStatement;
  2214. tjsANDEq : C:=TJSANDEqAssignStatement;
  2215. tjsOREq : C:=TJSOREqAssignStatement;
  2216. tjsXOREq : C:=TJSXOREqAssignStatement;
  2217. tjsArrow : C:=TJSArrowFunction;
  2218. else
  2219. // writeln('Strange token',GetEnumName(TypeInfo(TJSToken),Ord(CurrentToken)), ' As string: ',CurrentTokenString);
  2220. Result:=N
  2221. end;
  2222. If Result<>Nil then
  2223. begin
  2224. {$ifdef debugparser} Writeln('Exit ParseAssignmentExpression - no assignment');{$endif debugparser}
  2225. Exit;
  2226. end;
  2227. if C=Nil then
  2228. C:=TJSAssignStatement;
  2229. A:=TJSAssignStatement(CreateElement(C));
  2230. try
  2231. Result:=A;
  2232. A.Lhs:=N;
  2233. GetNextToken;
  2234. {$ifdef debugparser} Writeln('ParseAssignmentExpression - level 2');{$endif debugparser}
  2235. N:=ParseAssignmentExpression();
  2236. {$ifdef debugparser} Writeln('Exit ParseAssignmentExpression - level 2');{$endif debugparser}
  2237. A.Expr:=N;
  2238. IsLhs:=False;
  2239. except
  2240. FreeElement(Result);
  2241. Raise;
  2242. end;
  2243. {$ifdef debugparser} Writeln('Exit ParseAssignmentExpression');{$endif debugparser}
  2244. end;
  2245. function TJSParser.ParseVariableDeclaration(aVarType : TJSVarType = vtVar; IsAmbient: Boolean = False; IsExport: Boolean = False): TJSElement;
  2246. Var
  2247. V : TJSVarDeclaration;
  2248. begin
  2249. {$ifdef debugparser} Writeln('ParseVariableDeclaration');{$endif debugparser}
  2250. V:=TJSVarDeclaration(CreateElement(TJSVarDeclaration));
  2251. try
  2252. V.Name:=CurrenttokenString;
  2253. V.VarType:=aVarType;
  2254. Consume(tjsIdentifier);
  2255. if IsTypeScript and (CurrentToken=tjsColon) then
  2256. begin
  2257. Consume(tjsColon);
  2258. V.IsUnique:=IsIdentifier('unique');
  2259. if V.IsUnique then
  2260. GetNextToken;
  2261. V.Typed:=ParseTypeDef([ptoAllowLiteral]);
  2262. end;
  2263. if (CurrentToken=tjsAssign) then
  2264. begin
  2265. GetNextToken;
  2266. V.Init:=ParseAssignmentExpression;
  2267. end;
  2268. Result:=V;
  2269. FCurrentVars.AddNode(Result,IsAmbient,IsExport);
  2270. except
  2271. FreeElement(V);
  2272. Raise;
  2273. end;
  2274. {$ifdef debugparser} Writeln('Exit ParseVariableDeclaration');{$endif debugparser}
  2275. end;
  2276. function TJSParser.ParseVariableDeclarationList(aVarType : TJSVarType = vtVar; IsAmbient: Boolean = False; IsExport: Boolean = False): TJSElement;
  2277. Var
  2278. E,N : TJSElement;
  2279. L : TJSVariableDeclarationList;
  2280. SL : TJSVariableDeclarationList absolute N;
  2281. begin
  2282. {$ifdef debugparser} Writeln('ParseVariableDeclarationList entry');{$endif debugparser}
  2283. E:=ParseVariableDeclaration(aVarType,IsAmbient,IsExport);
  2284. If (CurrentToken<>tjsComma) then
  2285. Result:=E
  2286. else
  2287. begin
  2288. L:=TJSVariableDeclarationList(CreateElement(TJSVariableDeclarationList));
  2289. Result:=L;
  2290. try
  2291. Consume(tjsComma);
  2292. N:=ParseVariableDeclarationList(aVarType,IsAmbient,IsExport);
  2293. L.A:=E;
  2294. L.B:=N;
  2295. if IsTypeScript then
  2296. if (E is TJSVarDeclaration) then
  2297. if (N is TJSVarDeclaration) then
  2298. TJSVarDeclaration(E).SetForeignType((N as TJSVarDeclaration).Typed)
  2299. else if (N is TJSVariableDeclarationList) then
  2300. if (SL.A is TJSVarDeclaration) then
  2301. TJSVarDeclaration(E).SetForeignType((SL.A as TJSVarDeclaration).Typed);
  2302. except
  2303. FreeElement(Result);
  2304. Raise;
  2305. end;
  2306. end;
  2307. {$ifdef debugparser} Writeln('ParseVariableDeclarationList exit');{$endif debugparser}
  2308. end;
  2309. function TJSParser.ParseVariableStatement(aVarType: TJSVarType; IsAmbient: Boolean = False; IsExport: Boolean = False): TJSElement;
  2310. Const
  2311. InitialTokens : Array[TJSVarType] of TJSToken = (tjsVar,tjsLet,tjsConst);
  2312. Var
  2313. V : TJSVariableStatement;
  2314. begin
  2315. {$ifdef debugparser} Writeln('ParseVariableStatement entry');{$endif debugparser}
  2316. Result:=Nil;
  2317. Consume(InitialTokens[aVarType]);
  2318. Result:=ParseVariableDeclarationList(aVarType,IsAmbient,IsExport);
  2319. try
  2320. Consume(tjsSemicolon,true);
  2321. V:=TJSVariableStatement(CreateElement(TJSVariableStatement));
  2322. V.varType:=aVarType;
  2323. V.VarDecl:=Result;
  2324. Result:=V;
  2325. except
  2326. FreeElement(Result);
  2327. Raise;
  2328. end;
  2329. {$ifdef debugparser} Writeln('ParseVariableStatement exit');{$endif debugparser}
  2330. end;
  2331. function TJSParser.ParseEmptyStatement : TJSElement;
  2332. begin
  2333. Consume(tjsSemiColon,False);
  2334. Result:=CreateElement(TJSEmptyStatement);
  2335. end;
  2336. function TJSParser.ParseIfStatement : TJSElement;
  2337. Var
  2338. C,BTrue,BFalse : TJSElement;
  2339. I : TJSIFstatement;
  2340. begin
  2341. C:=Nil;
  2342. BTrue:=Nil;
  2343. BFalse:=Nil;
  2344. try
  2345. Consume(tjsIF);
  2346. Consume(tjsBraceOpen);
  2347. C:=ParseExpression;
  2348. Consume(tjsBraceClose);
  2349. BTrue:=ParseStatement;
  2350. If (CurrentToken=tjsElse) then
  2351. begin
  2352. Consume(tjsElse);
  2353. BFalse:=ParseStatement;
  2354. end;
  2355. I:=TJSIfStatement(CreateElement(TJSIfStatement));
  2356. I.Cond:=C;
  2357. I.BTrue:=Btrue;
  2358. I.BFalse:=BFalse;
  2359. Result:=I;
  2360. except
  2361. FreeElement(C);
  2362. FreeElement(BTrue);
  2363. FreeElement(BFalse);
  2364. Raise;
  2365. end;
  2366. end;
  2367. function TJSParser.ParseIterationStatement : TJSElement;
  2368. Var
  2369. F : TJSForStatement;
  2370. FI : TJSForInStatement;
  2371. W : TJSWhileStatement;
  2372. N : TJSElement;
  2373. begin
  2374. Result:=Nil;
  2375. N:=Nil;
  2376. CurrentLabelSet.Continuable:=True;
  2377. EnterLabel(SEmptyLabel);
  2378. try
  2379. try
  2380. Case CurrentToken of
  2381. tjsDo :
  2382. begin
  2383. GetNextToken;
  2384. W:=TJSDoWhileStatement(CreateElement(TJSDoWhileStatement));
  2385. Result:=W;
  2386. W.Body:=ParseStatement;
  2387. Consume(tjsWhile);
  2388. Consume(tjsBraceOpen);
  2389. W.Cond:=ParseExpression;
  2390. Consume(tjsBraceClose);
  2391. Consume(tjsSemicolon,True);
  2392. end;
  2393. tjsWhile :
  2394. begin
  2395. GetNextToken;
  2396. W:=TJSWhileStatement(CreateElement(TJSWhileStatement));
  2397. Result:=W;
  2398. Consume(tjsBraceOpen);
  2399. W.Cond:=ParseExpression;
  2400. Consume(tjsBraceClose);
  2401. W.Body:=ParseStatement;
  2402. Result:=W;
  2403. end;
  2404. else
  2405. // For ?
  2406. GetNextToken;
  2407. Consume(tjsBraceopen);
  2408. If (CurrentToken=tjsVar) then
  2409. begin
  2410. GetNextToken;
  2411. N:=ParseVariableDeclarationList;
  2412. // for (var in
  2413. If (CurrentToken=tjsIn) and (N is tJSVarDeclaration) then
  2414. begin
  2415. Fi:=TJSForInStatement(CreateElement(TJSForInStatement));
  2416. Result:=Fi;
  2417. Fi.LHS:=N;
  2418. GetNextToken;
  2419. Fi.List:=ParseExpression;
  2420. Consume(tjsBraceClose);
  2421. Fi.Body:=ParseStatement;
  2422. end;
  2423. // for (var ;
  2424. If (CurrentToken<>tjsSemicolon) then
  2425. If (N is tJSVarDeclaration) then
  2426. Error(SErrSemicolonOrInExpected,[CurrentTokenString])
  2427. else
  2428. Error(SErrSemicolonExpected,[CurrentTokenString]);
  2429. GetNextToken;
  2430. F:=TJSForStatement(CreateElement(TJSForStatement));
  2431. Result:=F;
  2432. If (CurrentToken<>tjsSemicolon) then
  2433. F.Cond:=ParseExpression;
  2434. Consume(tjsSemicolon);
  2435. If (CurrentToken<>tjsBraceClose) then
  2436. F.Incr:=ParseExpression;
  2437. Consume(tjsBraceClose);
  2438. F.Body:=ParseStatement;
  2439. end
  2440. else
  2441. begin
  2442. If (CurrentToken<>tjsSemicolon) then
  2443. begin
  2444. N:=ParseExpression;
  2445. If (CurrentToken=tjsIn) then
  2446. begin
  2447. Fi:=TJSForInStatement(CreateElement(TJSForInStatement));
  2448. Result:=Fi;
  2449. Fi.LHS:=N;
  2450. N:=Nil; // prevent freeing a second time in case of an exception.
  2451. GetNextToken;
  2452. Fi.List:=ParseExpression;
  2453. Consume(tjsBraceClose);
  2454. Fi.Body:=ParseStatement;
  2455. Exit; // We must jump out here
  2456. end
  2457. end
  2458. else
  2459. N:=Nil;
  2460. // For ( Init; Cond; incr)
  2461. F:=TJSForStatement(CreateElement(TJSForStatement));
  2462. Result:=F;
  2463. F.Init:=N;
  2464. N:=Nil; // prevent freeing a second time in case of an exception.
  2465. Consume(tjsSemicolon);
  2466. if (CurrentToken<>tjsSemicolon) then
  2467. F.Cond:=ParseExpression;
  2468. Consume(tjsSemicolon);
  2469. If (CurrentToken<>tjsBraceClose) Then
  2470. F.Incr:=ParseExpression;
  2471. Consume(tjsBraceClose);
  2472. F.Body:=ParseStatement;
  2473. end;
  2474. end; // Case
  2475. Finally
  2476. LeaveLabel;
  2477. FreeCurrentLabelSet;
  2478. end;
  2479. except
  2480. FreeElement(N);
  2481. FreeElement(Result);
  2482. Raise;
  2483. end;
  2484. end;
  2485. Procedure TJSParser.ParseAliasElements(aElements : TJSAliasElements);
  2486. // Parse { N [as M] }. On entry, must be on {, on exit curtoken is token after }
  2487. Var
  2488. aName,aAlias : jsbase.TJSString;
  2489. begin
  2490. Consume(tjsCurlyBraceOpen);
  2491. if (CurrentToken<>tjsCurlyBraceClose) then
  2492. begin
  2493. Repeat
  2494. if IsTypeScript and (currentToken=tjsDEFAULT) then
  2495. begin
  2496. aName:='default';
  2497. getNextToken
  2498. end
  2499. else
  2500. begin
  2501. Expect(tjsIdentifier);
  2502. aName:=CurrentTokenString;
  2503. Consume(tjsIdentifier);
  2504. end;
  2505. aAlias:='';
  2506. if IdentifierIsLiteral('as') then
  2507. begin
  2508. Consume(tjsIdentifier);
  2509. if IsTypeScript and (currentToken=tjsDEFAULT) then
  2510. begin
  2511. aAlias:='default';
  2512. getNextToken;
  2513. end
  2514. else
  2515. begin
  2516. if IsTypeScript and CurrentTokenIsValidIdentifier then
  2517. begin
  2518. aAlias:=CurrentTokenString;
  2519. GetNextToken
  2520. end
  2521. else
  2522. begin
  2523. Expect(tjsIdentifier);
  2524. aAlias:=CurrentTokenString;
  2525. Consume(tjsIdentifier);
  2526. end;
  2527. end;
  2528. end;
  2529. With aElements.AddAlias do
  2530. begin
  2531. Name:=aName;
  2532. Alias:=aAlias;
  2533. end;
  2534. if CurrentToken=tjsComma then
  2535. GetNextToken;
  2536. Until (CurrentToken=tjsCurlyBraceClose);
  2537. end;
  2538. Consume(tjsCurlyBraceClose);
  2539. end;
  2540. function TJSParser.ParseImportStatement: TJSElement;
  2541. Var
  2542. Imp : TJSImportStatement;
  2543. aExpectMore : Boolean;
  2544. isAssigned : Boolean;
  2545. begin
  2546. isAssigned:=False;
  2547. aExpectMore:=True;
  2548. Consume(tjsImport);
  2549. Imp:=TJSImportStatement(CreateElement(TJSImportStatement));
  2550. try
  2551. Result:=Imp;
  2552. // Just module name
  2553. if CurrentToken = jstoken.tjsString then
  2554. begin
  2555. Imp.ModuleName:=CurrentTokenString;
  2556. GetNextToken;
  2557. Exit;
  2558. end;
  2559. // ImportedDefaultBinding
  2560. if CurrentToken = tjsIdentifier then
  2561. begin
  2562. Imp.DefaultBinding:=CurrentTokenString;
  2563. aExpectMore:=GetNextToken=tjsCOMMA;
  2564. if aExpectMore then
  2565. GetNextToken;
  2566. end;
  2567. Case CurrentToken of
  2568. tjsMUL : // NameSpaceImport
  2569. begin
  2570. Consume(tjsMul);
  2571. ConsumeIdentifierLiteral('as');
  2572. Expect(tjsIdentifier);
  2573. Imp.NameSpaceImport:=CurrentTokenString;
  2574. Consume(tjsIdentifier);
  2575. end;
  2576. tjsCurlyBraceOpen:
  2577. begin
  2578. ParseAliasElements(Imp.NamedImports);
  2579. end;
  2580. tjsAssign:
  2581. begin
  2582. if IsTypeScript then
  2583. begin
  2584. Consume(tjsAssign);
  2585. isAssigned:=True;
  2586. Imp.Expression:=ParseExpression;
  2587. end;
  2588. end;
  2589. else
  2590. if aExpectMore then
  2591. Error(SErrExpectedMulOrCurlyBrace,[CurrentTokenString]);
  2592. end;
  2593. if not IsAssigned then
  2594. begin
  2595. ConsumeIdentifierLiteral('from');
  2596. Expect(jstoken.tjsString);
  2597. Imp.ModuleName:=CurrentTokenString;
  2598. Consume(jstoken.tjsString);
  2599. end;
  2600. Consume(tjsSemicolon,True);
  2601. except
  2602. FreeElement(Result);
  2603. Raise;
  2604. end;
  2605. end;
  2606. function TJSParser.ParseExportStatement(isAssign : Boolean): TJSElement;
  2607. Var
  2608. Exp : TJSExportStatement;
  2609. IsAbstract, IsAmbient, aSync, aExpectFrom : Boolean;
  2610. F : TJSFunctionDeclarationStatement;
  2611. FF : TFunctionFlags;
  2612. begin
  2613. IsAmbient:=False;
  2614. aSync:=False;
  2615. aExpectFrom:=True;
  2616. if IsAssign then
  2617. Consume(tjsAssign)
  2618. else
  2619. Consume(tjsExport);
  2620. if IsTypeScript then
  2621. begin
  2622. if CurrentToken=tjsAssign then
  2623. begin
  2624. isAssign:=True;
  2625. getnexttoken;
  2626. end;
  2627. IsAmbient:=IsIdentifier('declare');
  2628. if IsAmbient then
  2629. GetNextToken;
  2630. IsAbstract:=IsIdentifier('abstract');
  2631. if IsAbstract then
  2632. GetNextToken;
  2633. end;
  2634. Exp:=TJSExportStatement(CreateElement(TJSExportStatement));
  2635. try
  2636. Result:=Exp;
  2637. Case CurrentToken of
  2638. tjsMUL : // NameSpaceImport
  2639. begin
  2640. Consume(tjsMul);
  2641. if not IdentifierIsLiteral('as') then
  2642. Exp.NameSpaceExport:='*'
  2643. else
  2644. begin
  2645. ConsumeIdentifierLiteral('as');
  2646. Expect(tjsIdentifier);
  2647. Exp.NameSpaceExport:=CurrentTokenString;
  2648. Consume(tjsIdentifier);
  2649. end
  2650. end;
  2651. tjsCurlyBraceOpen:
  2652. begin
  2653. ParseAliasElements(Exp.ExportNames);
  2654. end;
  2655. tjsVAR:
  2656. Exp.Declaration:=ParseVariableStatement(vtVar);
  2657. tjsEnum:
  2658. Exp.Declaration:=ParseEnumDeclaration;
  2659. tjsConst:
  2660. if IsTypeScript and (PeekNextToken=tjsENUM) then
  2661. Exp.Declaration:=ParseEnumDeclarationStatement
  2662. else
  2663. Exp.Declaration:=ParseVariableStatement(vtConst);
  2664. tjsLet:
  2665. Exp.Declaration:=ParseVariableStatement(vtLet);
  2666. tjsFunction :
  2667. if IsTypeScript or isAmbient then
  2668. Exp.Declaration:=ParseFunctionDeclaration([ffAmbient])
  2669. else
  2670. Exp.Declaration:=ParseFunctionDeclaration([]);
  2671. tjsClass :
  2672. begin
  2673. Exp.Declaration:=ParseClassDeclaration(IsAmbient or IsTypeScript,IsAbstract);
  2674. end;
  2675. tjsIMPORT :
  2676. begin
  2677. Exp.Declaration:=ParseImportStatement;
  2678. end;
  2679. tjsDEFAULT:
  2680. begin
  2681. Exp.IsDefault:=True;
  2682. aExpectFrom:=False;
  2683. Consume(tjsDefault);
  2684. async:=IdentifierIsLiteral('async');
  2685. if Async then
  2686. GetNextToken;
  2687. IsAbstract:=IdentifierIsLiteral('abstract') and (PeekNextToken=tjsClass);
  2688. if IsAbstract then
  2689. GetNextToken;
  2690. case CurrentToken of
  2691. tjsFunction :
  2692. begin
  2693. FF:=[];
  2694. if IsTypeScript or IsAmbient then
  2695. Include(FF,ffAmbient);
  2696. F:=ParseFunctionExpression(FF);
  2697. F.AFunction.IsAsync:=async;
  2698. Exp.Declaration:=F;
  2699. end;
  2700. tjsClass : Exp.Declaration:=ParseClassDeclaration(True,True);
  2701. else
  2702. if IsTypeScript and IsIdentifier('interface') then
  2703. Exp.Declaration:=ParseInterfaceDeclaration
  2704. else
  2705. Exp.Declaration:=ParseAssignmentExpression;
  2706. end;
  2707. end;
  2708. jsToken.tjsAssign:
  2709. begin
  2710. if IsTypeScript then
  2711. begin
  2712. consume(tjsAssign);
  2713. aExpectFrom:=False;
  2714. Exp.Declaration:=ParseExpression;
  2715. end;
  2716. end;
  2717. tjsIdentifier:
  2718. begin
  2719. if IsTypeScript then
  2720. begin
  2721. if IsIdentifier('interface') then
  2722. Exp.Declaration:=ParseInterfaceDeclaration
  2723. else if IsIdentifier('namespace') then
  2724. Exp.Declaration:=ParseNamespaceDeclaration(True)
  2725. else if IsIdentifier('module') then
  2726. Exp.Declaration:=ParseModuleDeclaration
  2727. else if IsIdentifier('class') then
  2728. Exp.Declaration:=ParseClassDeclaration(True)
  2729. else if IsIdentifier('abstract') then
  2730. begin
  2731. consume(tjsIdentifier);
  2732. if (CurrentToken=tjsClass) then
  2733. Exp.Declaration:=ParseClassDeclaration(True,True);
  2734. end
  2735. else if IsIdentifier('type') then
  2736. Exp.Declaration:=ParseTypeDeclaration
  2737. else if IsIdentifier('enum') then
  2738. Exp.Declaration:=ParseEnumDeclaration
  2739. else if IsIdentifier('as') then
  2740. begin
  2741. consume(tjsIdentifier);
  2742. if Not IsIdentifier('namespace') then
  2743. Error(SErrExpectedButFound,['namespace',CurrentTokenString]);
  2744. consume(tjsIdentifier);
  2745. expect(tjsIdentifier);
  2746. Exp.NameSpaceExport:=CurrentTokenString;
  2747. Consume(tjsIdentifier);
  2748. end
  2749. else if IsAssign then
  2750. Exp.Declaration:=ParseExpression
  2751. else
  2752. Error(SErrExpectedMulOrCurlyBraceOrDefault,[CurrentTokenString]);
  2753. end
  2754. else
  2755. Error(SErrExpectedMulOrCurlyBraceOrDefault,[CurrentTokenString]);
  2756. end
  2757. else
  2758. Error(SErrExpectedMulOrCurlyBraceOrDefault,[CurrentTokenString]);
  2759. end;
  2760. if aExpectFrom and IdentifierIsLiteral('from') then
  2761. begin
  2762. ConsumeIdentifierLiteral('from');
  2763. Expect(jstoken.tjsString);
  2764. Exp.ModuleName:=CurrentTokenString;
  2765. Consume(jstoken.tjsString);
  2766. end;
  2767. Consume(tjsSemicolon,True);
  2768. except
  2769. FreeElement(Result);
  2770. Raise;
  2771. end;
  2772. end;
  2773. function TJSParser.ParseContinueStatement : TJSElement;
  2774. Var
  2775. L : TJSLabel;
  2776. C : TJSContinueStatement;
  2777. begin
  2778. C:=TJSContinueStatement(CreateElement(TJSContinueStatement));
  2779. try
  2780. Result:=C;
  2781. Consume(tjsContinue);
  2782. If (CurrentToken=tjsSemicolon) then
  2783. L:=LookupLabel(SEmptyLabel,tjsContinue)
  2784. else
  2785. begin
  2786. if (CurrentToken=tjsIdentifier) then
  2787. L:=LookupLabel(CurrentTokenString,tjsContinue);
  2788. Consume(tjsIdentifier);
  2789. end;
  2790. Consume(tjsSemicolon,True);
  2791. C.Target:=L.Labelset.Target;
  2792. C.TargetName:=L.Name;
  2793. except
  2794. FreeElement(C);
  2795. Raise;
  2796. end;
  2797. end;
  2798. function TJSParser.ParseBreakStatement : TJSElement;
  2799. Var
  2800. L : TJSLabel;
  2801. B : TJSBreakStatement;
  2802. begin
  2803. B:=TJSBreakStatement(CreateElement(TJSBreakStatement));
  2804. try
  2805. Result:=B;
  2806. Consume(tjsBreak);
  2807. If (CurrentToken=tjsSemicolon) then
  2808. L:=LookupLabel(SEmptyLabel,tjsBreak)
  2809. else
  2810. begin
  2811. if (CurrentToken=tjsIdentifier) then
  2812. L:=LookupLabel(CurrentTokenString,tjsBreak);
  2813. Consume(tjsIdentifier);
  2814. end;
  2815. Consume(tjsSemicolon,True);
  2816. B.Target:=L.Labelset.Target;
  2817. B.TargetName:=L.Name;
  2818. except
  2819. FreeElement(B);
  2820. Raise;
  2821. end;
  2822. end;
  2823. function TJSParser.ParseReturnStatement : TJSElement;
  2824. Var
  2825. R : TJSreturnStatement;
  2826. begin
  2827. R:=TJSReturnStatement(CreateElement(TJSReturnStatement));
  2828. try
  2829. Result:=R;
  2830. Consume(tjsReturn);
  2831. If (FunctionDepth=0) then
  2832. Error(SErrReturnNotInFunction);
  2833. If Not (CurrentToken in [tjsSemicolon,tjsCurlyBraceClose]) then
  2834. R.Expr:=ParseExpression;
  2835. Consume(tjsSemicolon,True);
  2836. except
  2837. FreeElement(R);
  2838. Raise;
  2839. end;
  2840. end;
  2841. function TJSParser.ParseWithStatement : TJSElement;
  2842. Var
  2843. W : TJSWithStatement;
  2844. begin
  2845. W:=TJSWithStatement(CreateElement(TJSWithStatement));
  2846. try
  2847. Consume(tjsWith);
  2848. Consume(tjsBraceOpen);
  2849. W.A:=ParseExpression;
  2850. Consume(tjsBraceClose);
  2851. W.B:=ParseStatement;
  2852. except
  2853. FreeElement(W);
  2854. Raise;
  2855. end;
  2856. Result:=W;
  2857. end;
  2858. function TJSParser.ParseSwitchStatement : TJSElement;
  2859. Var
  2860. N : TJSSwitchStatement;
  2861. Ca : TJSCaseElement;
  2862. begin
  2863. N:=TJSSwitchStatement(CreateElement(TJSSwitchStatement));
  2864. try
  2865. N.Target:=CurrentLabelset.Target;
  2866. EnterLabel(SEmptyLabel);
  2867. try
  2868. Consume(tjsSwitch);
  2869. Consume(tjsBraceOpen);
  2870. N.Cond:=ParseExpression;
  2871. Consume(tjsBraceClose);
  2872. Consume(tjsCurlyBraceOpen);
  2873. While (CurrentToken<>tjsCurlyBraceClose) do
  2874. begin
  2875. If (CurrentToken=tjsCase) then
  2876. begin
  2877. GetNextToken;
  2878. Ca:=N.Cases.AddCase;
  2879. Ca.Expr:=ParseExpression;
  2880. end
  2881. else if (CurrentToken=tjsDefault) then
  2882. begin
  2883. If (N.TheDefault<>Nil) then
  2884. Error(SerrDuplicateSwitchDefault);
  2885. Ca:=N.Cases.AddCase;
  2886. N.TheDefault:=Ca;
  2887. GetNextToken;
  2888. end
  2889. else
  2890. Error(SerrCaseEndExpected);
  2891. Consume(tjsColon);
  2892. If Not (CurrentToken in [tjsCurlyBraceClose,tjsCase,tjsDefault]) then
  2893. Ca.Body:=ParseStatementList;
  2894. end;
  2895. Consume(tjsCurlyBraceClose);
  2896. finally
  2897. LeaveLabel;
  2898. FreeCurrentLabelSet;
  2899. end;
  2900. Result:=N;
  2901. except
  2902. FreeElement(N);
  2903. Raise;
  2904. end;
  2905. end;
  2906. function TJSParser.ParseThrowStatement : TJSElement;
  2907. Var
  2908. TS : TJSThrowStatement;
  2909. begin
  2910. TS:=TJSThrowStatement(CreateElement(TJSThrowStatement));
  2911. try
  2912. Result:=TS;
  2913. Consume(tjsThrow);
  2914. If IsEndOfLine then
  2915. Error(SErrNewlineAfterThrow);
  2916. TS.A:=ParseExpression;
  2917. Consume(tjsSemicolon,true);
  2918. except
  2919. FreeElement(TS);
  2920. Raise;
  2921. end;
  2922. end;
  2923. function TJSParser.ParseTryStatement : TJSElement;
  2924. Var
  2925. BO,BC,BF : TJSElement;
  2926. Id : jstree.TJSString;
  2927. T : TJSTryStatement;
  2928. begin
  2929. BO:=Nil;
  2930. BC:=Nil;
  2931. BF:=Nil;
  2932. Result:=Nil;
  2933. Consume(tjsTry);
  2934. try
  2935. Bo:=ParseBlock;
  2936. if (CurrentToken=tjscatch) then
  2937. begin
  2938. Consume(tjsCatch);
  2939. Consume(tjsBraceOpen);
  2940. if (CurrentToken=tjsIdentifier) then
  2941. id:=CurrentTokenString;
  2942. Consume(tjsIdentifier);
  2943. Consume(tjsBraceClose);
  2944. BC:=ParseBlock;
  2945. end;
  2946. if (CurrentToken=tjsFinally) then
  2947. begin
  2948. consume(tjsFinally);
  2949. BF:=ParseBlock;
  2950. end;
  2951. If (BF=Nil) and (BC=Nil) then
  2952. Error(SErrCatchFinallyExpected);
  2953. If Assigned(BC) AND Assigned(BF) then
  2954. T:=TJSTryStatement(CreateElement(TJSTryCatchFinallyStatement))
  2955. else if Assigned(BC) then
  2956. T:=TJSTryStatement(CreateElement(TJSTryCatchStatement))
  2957. else
  2958. T:=TJSTryStatement(CreateElement(TJSTryFinallyStatement));
  2959. Result:=T;
  2960. T.Block:=Bo;
  2961. Bo:=Nil;
  2962. T.BCatch:=BC;
  2963. BC:=Nil;
  2964. T.BFinally:=BF;
  2965. BF:=Nil;
  2966. T.Ident:=ID;
  2967. except
  2968. FreeElement(Bo);
  2969. FreeElement(BC);
  2970. FreeElement(BF);
  2971. FreeElement(Result);
  2972. Raise;
  2973. end;
  2974. end;
  2975. function TJSParser.ParseEnumDeclaration: TJSEnumDeclaration;
  2976. // We are on the 'enum' identifier on entry, last token of type on exit
  2977. var
  2978. El : TJSEnumElement;
  2979. begin
  2980. GetNextToken; // Skip 'enum'
  2981. Result:=TJSEnumDeclaration(CreateElement(TJSEnumDeclaration));
  2982. try
  2983. Result.Name:=ParseIdentifier;
  2984. consume(tjsCurlyBraceOpen);
  2985. Result.EnumDef:=TJSEnumTypeDef(CreateElement(TJSEnumTypeDef));
  2986. While not (CurrentToken=tjsCurlyBraceClose) do
  2987. begin
  2988. if (CurrentToken=tjsComma) then
  2989. Consume(tjsComma);
  2990. // Trailing ,
  2991. if (CurrentToken<>tjsCurlyBraceClose) then
  2992. begin
  2993. if CurrentTokenIsValidIdentifier then
  2994. begin
  2995. EL:=Result.EnumDef.AddName(CurrentTokenString);
  2996. GetNextToken;
  2997. end
  2998. else
  2999. EL:=Result.EnumDef.AddName(ParseIdentifier);
  3000. if CurrentToken=tjsAssign then
  3001. begin
  3002. Consume(tjsAssign);
  3003. el.Value:=ParseLiteral;
  3004. end;
  3005. end;
  3006. end;
  3007. Consume(tjsCurlyBraceClose);
  3008. except
  3009. FreeElement(Result);
  3010. Raise;
  3011. end;
  3012. end;
  3013. function TJSParser.ParseEnumDeclarationStatement: TJSElement;
  3014. // We are on the 'const' token or 'enum' identifier on entry, last token of type on exit
  3015. Var
  3016. aES : TJSEnumStatement;
  3017. IsConst : Boolean;
  3018. begin
  3019. IsConst:=(CurrentToken=tjsConst);
  3020. if isConst then
  3021. Consume(tjsConst);
  3022. aES:=TJSEnumStatement(CreateElement(TJSEnumStatement));
  3023. Result:=aES;
  3024. try
  3025. aES.EnumDecl:=ParseEnumDeclaration;
  3026. aES.EnumDecl.EnumDef.IsConst:=IsConst;
  3027. except
  3028. FreeElement(Result);
  3029. Raise;
  3030. end;
  3031. end;
  3032. function TJSParser.ParseTypeDeclaration: TJSTypeDeclaration;
  3033. // We are on the 'type' identifier on entry, last token of type on exit
  3034. begin
  3035. GetNextToken; // Skip 'type'
  3036. Result:=TJSTypeDeclaration(CreateElement(TJSTypeDeclaration));
  3037. try
  3038. Result.Name:=ParseIdentifier;
  3039. if (CurrentToken=tjsLT) then
  3040. begin
  3041. Result.TypeParams:=TJSElementNodes.Create(TJSElementNode);
  3042. ParseGenericParamList(Result.TypeParams);
  3043. Consume(tjsGT);
  3044. end;
  3045. Consume(tjsAssign);
  3046. Result.TypeDef:=ParseTypeDef([ptoAllowLiteral]);
  3047. except
  3048. FreeElement(Result);
  3049. Raise;
  3050. end;
  3051. end;
  3052. function TJSParser.ParseTypeDeclarationStatement: TJSElement;
  3053. // We are on the 'type' identifier on entry, last token of type on exit
  3054. Var
  3055. aTS : TJSTypeStatement;
  3056. begin
  3057. aTS:=TJSTypeStatement(CreateElement(TJSTypeStatement));
  3058. Result:=aTS;
  3059. try
  3060. aTS.TypeDecl:=ParseTypeDeclaration;
  3061. except
  3062. FreeElement(Result);
  3063. Raise;
  3064. end;
  3065. end;
  3066. function TJSParser.ParseFunctionExpression(aFlags : TFunctionFlags): TJSFunctionDeclarationStatement;
  3067. Var
  3068. Oni,olhs: Boolean;
  3069. F : TJSFunctionDeclarationStatement;
  3070. TP : TJSElementNodes;
  3071. N : jsBase.TJSString;
  3072. begin
  3073. {$ifdef debugparser} Writeln('>>> ParseFunctionExpression');{$endif}
  3074. oni:=NoIn;
  3075. olhs:=IsLHS;
  3076. F:=Nil;
  3077. TP:=Nil;
  3078. try
  3079. NoIn:=False;
  3080. IsLHS:=False;
  3081. F:=TJSFunctionDeclarationStatement(CreateElement(TJSFunctionDeclarationStatement));
  3082. try
  3083. if not (ffGenerator in aFlags) then
  3084. Consume(tjsFunction);
  3085. F.isGenerator:=(CurrentToken=tjsMUL);
  3086. if F.IsGenerator then
  3087. Consume(tjsMul);
  3088. if (CurrentToken=tjsIdentifier) then
  3089. begin
  3090. n:=CurrentTokenstring;
  3091. GetNextToken;
  3092. end
  3093. else
  3094. n:='';
  3095. if n='' then ; // what to do with that?
  3096. if CurrentToken=tjsLT then
  3097. begin
  3098. TP:=TJSElementNodes.Create(TJSElementNode);
  3099. ParseGenericParamList(TP);
  3100. consume(tjsGT);
  3101. end;
  3102. Consume(tjsBraceOpen);
  3103. F.AFunction:= TJSFuncDef.Create;
  3104. F.Afunction.GenericParams:=TP;
  3105. F.AFunction.IsConstructor:=ffConstructor in aFlags;
  3106. TP:=nil;
  3107. ParseFormalParameterList(F.AFunction.TypedParams);
  3108. Consume(tjsBraceClose);
  3109. if CurrentToken=tjsColon then
  3110. begin
  3111. Consume(tjsColon);
  3112. F.AFunction.ResultType:=ParseTypeDef([ptoAllowLiteral]);
  3113. end;
  3114. if (CurrentToken=tjsCurlyBraceOpen) then
  3115. begin
  3116. Consume(tjsCurlyBraceOpen);
  3117. Inc(FFunctionDepth);
  3118. try
  3119. F.AFunction.Body:=ParseFunctionBody;
  3120. F.AFunction.Name:=n;
  3121. Finally
  3122. Dec(FFunctionDepth);
  3123. end;
  3124. Consume(tjsCurlyBraceClose);
  3125. end;
  3126. Result:=F;
  3127. except
  3128. FreeElement(F);
  3129. Raise;
  3130. end;
  3131. finally
  3132. NoIn := oni;
  3133. IsLHS := olhs;
  3134. end;
  3135. {$ifdef debugparser} Writeln('<<< ParseFunctionExpression');{$endif}
  3136. end;
  3137. function TJSParser.ParseFunctionStatement : TJSElement;
  3138. Var
  3139. F : TJSFunctionDeclarationStatement;
  3140. I : TJSPrimaryExpressionIdent;
  3141. A : TJSAssignStatement;
  3142. E : TJSExpressionStatement;
  3143. begin
  3144. {$ifdef debugparser} Writeln('>>> ParseFunctionStatement');{$endif}
  3145. F:=Nil;
  3146. I:=Nil;
  3147. A:=Nil;
  3148. try
  3149. F:=ParseFunctionExpression([]);
  3150. I:=TJSPrimaryExpressionIdent(CreateElement(TJSPrimaryExpressionIdent));
  3151. I.Name:=F.AFunction.Name;
  3152. A:=TJSAssignStatement(CreateElement(TJSAssignStatement));
  3153. A.LHS:=I;
  3154. I:=Nil;
  3155. A.Expr:=F;
  3156. F:=Nil;
  3157. E:=TJSExpressionStatement(CreateElement(TJSExpressionStatement));
  3158. E.A:=A;
  3159. A:=Nil;
  3160. Result:=E;
  3161. except
  3162. FreeElement(F);
  3163. FreeElement(I);
  3164. FreeElement(A);
  3165. Raise;
  3166. end;
  3167. {$ifdef debugparser} Writeln('<<< ParseFunctionStatement');{$endif}
  3168. end;
  3169. function TJSParser.ParseLabeledStatement : TJSElement;
  3170. Var
  3171. OL : TJSLabelSet;
  3172. LS : TJSLabeledStatement;
  3173. begin
  3174. LS:=TJSLabeledStatement(CreateElement(TJSLabeledStatement));
  3175. try
  3176. Result:=LS;
  3177. OL:=FCurrentLabelSet;
  3178. try
  3179. FCurrentLabelSet:=Nil;
  3180. LS.target:=CurrentLabelSet.Target;
  3181. Repeat
  3182. LS.TheLabel:=EnterLabel(CurrentTokenString);
  3183. Consume(tjsIdentifier);
  3184. Consume(tjsColon);
  3185. Until (CurrentToken<>tjsIdentifier) or (PeekNextToken<>tjsColon);
  3186. Case CurrentToken of
  3187. tjsDo,tjsWhile,tjsFor : LS.A:=ParseIterationStatement;
  3188. tjsswitch : LS.A:=ParseSwitchStatement;
  3189. else
  3190. LS.A:=ParseStatement;
  3191. end;
  3192. finally
  3193. FreeCurrentLabelSet;
  3194. FCurrentLabelSet:=Ol;
  3195. end;
  3196. except
  3197. FreeElement(LS);
  3198. Raise;
  3199. end;
  3200. end;
  3201. procedure TJSParser.FreeCurrentLabelSet;
  3202. Var
  3203. L : TJSLabelSet;
  3204. begin
  3205. While Assigned(FCurrentLabelSet) do
  3206. begin
  3207. L:=FCurrentLabelset.Next;
  3208. FCurrentLabelSet.Free;
  3209. FCurrentLabelSet:=L;
  3210. end;
  3211. end;
  3212. function TJSParser.GetVersion: TECMAVersion;
  3213. begin
  3214. Result:=FSCanner.ECMAVersion;
  3215. end;
  3216. function TJSParser.ParseExpressionStatement : TJSElement;
  3217. Var
  3218. E : TJSElement;
  3219. R : TJSExpressionStatement;
  3220. begin
  3221. {$ifdef debugparser} Writeln('ParseExpressionStatement');{$endif debugparser}
  3222. E:=ParseExpression;
  3223. Consume(tjsSemicolon,True);
  3224. R:=TJSExpressionStatement(CreateElement(TJSExpressionStatement));
  3225. R.A:=E;
  3226. Result:=R;
  3227. {$ifdef debugparser} Writeln('Exit ParseExpressionStatement');{$endif debugparser}
  3228. end;
  3229. function TJSParser.ParseExpression : TJSElement;
  3230. Var
  3231. C : TJSCommaExpression;
  3232. begin
  3233. {$ifdef debugparser} Writeln('ParseExpression');{$endif debugparser}
  3234. Result:=ParseAssignmentExpression;
  3235. try
  3236. If (CurrentToken=tjsComma) then
  3237. begin
  3238. C:=TJSCommaExpression(CreateElement(TJSCommaExpression));
  3239. C.A:=Result;
  3240. Result:=C;
  3241. GetNextToken;
  3242. C.B:=ParseExpression();
  3243. end;
  3244. except
  3245. FreeElement(Result);
  3246. Raise;
  3247. end;
  3248. {$ifdef debugparser} Writeln('Exit ParseExpression');{$endif debugparser}
  3249. end;
  3250. function TJSParser.ParseStatement(IsAmbient : Boolean = False;IsExport : Boolean = False): TJSElement;
  3251. Var
  3252. FF : TFunctionFlags;
  3253. begin
  3254. {$ifdef debugparser} Writeln('>>> Parsestatement');{$endif}
  3255. Result:=Nil;
  3256. FF:=[];
  3257. if isAmbient then
  3258. FF:=[ffAmbient];
  3259. Case CurrentToken of
  3260. tjsCurlyBraceOpen :
  3261. Result:=ParseBlock;
  3262. tjsLet:
  3263. Result:=ParseVariableStatement(vtLet);
  3264. tjsConst:
  3265. if IsTypeScript and (PeekNextToken=tjsEnum) then
  3266. Result:=ParseEnumDeclarationStatement
  3267. else
  3268. Result:=ParseVariableStatement(vtConst);
  3269. tjsVar:
  3270. Result:=ParseVariableStatement(vtVar,IsAmbient,IsExport);
  3271. tjsSemicolon:
  3272. Result:=ParseEmptyStatement;
  3273. tjsIf:
  3274. Result:=ParseIfStatement;
  3275. tjsDo,tjsWhile,tjsFor:
  3276. Result:=ParseIterationStatement;
  3277. tjsClass:
  3278. Result:=ParseClassStatement;
  3279. tjsContinue:
  3280. Result:=ParseContinueStatement;
  3281. tjsImport:
  3282. Result:=ParseImportStatement;
  3283. tjsExport:
  3284. Result:=ParseExportStatement(False);
  3285. tjsBreak:
  3286. Result:=ParseBreakStatement;
  3287. tjsReturn:
  3288. Result:=ParseReturnStatement;
  3289. tjsWith:
  3290. Result:=ParseWithStatement;
  3291. tjsDebugger:
  3292. Result:=ParseDebuggerStatement;
  3293. tjsSwitch:
  3294. Result:=ParseSwitchStatement;
  3295. tjsThrow:
  3296. Result:=ParseThrowStatement;
  3297. tjsTry:
  3298. Result:=ParseTryStatement;
  3299. tjsFunction:
  3300. begin
  3301. If (PeekNextToken<>tjsBraceOpen) then
  3302. Result:=ParseFunctionStatement;
  3303. Error(SErrFunctionNotAllowedHere);
  3304. end;
  3305. tjsAwait,
  3306. tjsYield,
  3307. tjsIdentifier:
  3308. If (PeekNextToken=tjsColon) then
  3309. Result:=ParseLabeledStatement
  3310. else if IsTypeScript then
  3311. begin
  3312. if IsIdentifier('type') then
  3313. Result:=ParseTypeDeclarationStatement
  3314. else if IsIdentifier('abstract') then
  3315. begin
  3316. consume(tjsIdentifier);
  3317. expect(tjsClass);
  3318. Result:=ParseClassStatement(True,True);
  3319. end
  3320. else if IsIdentifier('constructor') then
  3321. begin
  3322. Include(FF,ffConstructor);
  3323. Result:=ParseFunctionDeclaration(FF);
  3324. end
  3325. else
  3326. Result:=ParseExpressionStatement;
  3327. end
  3328. else
  3329. Result:=ParseExpressionStatement;
  3330. else
  3331. Result:=ParseExpressionStatement;
  3332. end;
  3333. {$ifdef debugparser} If Assigned(Result) then Writeln('<<< Parsestatement ',Result.ClassName) else Writeln('<<< Parsestatement (null');{$endif}
  3334. end;
  3335. Function TJSParser.AddToElements(aSource : TJSSourceElements; aElement : TJSElement; aIsAmbient : Boolean = False; aIsExport : Boolean = False): Boolean;
  3336. Var
  3337. N : TJSTransientElementNode;
  3338. begin
  3339. Result:=True;
  3340. if aElement is TJSInterfaceDeclaration then
  3341. aSource.Interfaces.AddNode(aElement,aIsAmbient,aIsExport)
  3342. else if aElement is TJSClassDeclaration then
  3343. aSource.Classes.AddNode(aElement,aIsAmbient,aIsExport)
  3344. else if aElement is TJSVarDeclaration then
  3345. aSource.Vars.AddNode(aElement,aIsAmbient,aIsExport)
  3346. else if aElement is TJSTypeDeclaration then
  3347. aSource.Types.AddNode(aElement,aIsAmbient,aIsExport)
  3348. else if aElement is TJSModuleDeclaration then
  3349. aSource.Modules.AddNode(aElement,aIsAmbient,aIsExport)
  3350. else if aElement is TJSNamespaceDeclaration then
  3351. aSource.NameSpaces.AddNode(aElement,aIsAmbient,aIsExport)
  3352. else if aElement is TJSFunctionStatement then
  3353. begin
  3354. N:=TJSTransientElementNode.Create(aSource.Functions);
  3355. N.IsAmbient:=aIsAmbient;
  3356. N.IsExport:=aIsExport;
  3357. N.Node:=aElement;
  3358. end
  3359. else
  3360. Result:=False;
  3361. end;
  3362. function TJSParser.ParseTypeStatement(Elements : TJSSourceElements; ScopeType : TScopeType; aIsAmbient : Boolean) : TJSElement;
  3363. begin
  3364. Result:=Nil;
  3365. if ScopeType=stClass then ;
  3366. if IsIdentifier('module') then
  3367. Result:=Self.ParseModuleDeclarationStatement
  3368. else if IsIdentifier('namespace') or IsIdentifier('global') then
  3369. Result:=Self.ParseNamespaceDeclarationStatement
  3370. else if IsIdentifier('type') then
  3371. Result:=Self.ParseTypeDeclarationStatement
  3372. else if IsIdentifier('interface') then
  3373. Result:=Self.ParseInterfaceDeclarationStatement
  3374. else if (IsIdentifier('static')) then
  3375. begin
  3376. if aIsAmbient then
  3377. begin
  3378. Result:=Self.ParseFunctionDeclaration([ffAmbient]);
  3379. Elements.Functions.AddNode(aIsAmbient).Node:=Result;
  3380. end;
  3381. end;
  3382. if Assigned(Result) and (Result is TJSDeclarationStatement) then
  3383. begin
  3384. Elements.Statements.AddNode(aIsAmbient).Node:=Result;
  3385. AddToElements(Elements,TJSDeclarationStatement(Result).GetDeclaration,aIsAmbient);
  3386. end;
  3387. end;
  3388. function TJSParser.ParseSourceElements (ScopeType : TScopeType = stFunction; ParentisAmbient : Boolean = False): TJSSourceElements;
  3389. Const
  3390. StatementTokens = [tjsNULL, tjsTRUE, tjsFALSE,
  3391. tjsAWait, tjsTHIS, tjsIdentifier,jstoken.tjsSTRING,jstoken.tjsNUMBER,
  3392. tjsBraceOpen,tjsCurlyBraceOpen,tjsSquaredBraceOpen,
  3393. tjsLet, tjsConst, tjsDebugger, tjsImport, tjsExport,
  3394. tjsNew,tjsDelete,tjsVoid,tjsTypeOf,
  3395. tjsPlusPlus,tjsMinusMinus,
  3396. tjsPlus,tjsMinus,tjsNot,tjsNE,tjsSNE,tjsSemicolon,
  3397. tjsVAR,tjsIF,tjsDO,tjsWHILE,tjsFOR,jstoken.tjsCONTINUE,jstoken.tjsBREAK,jstoken.tjsReturn,
  3398. tjsWith,jstoken.tjsSWITCH,tjsThrow,TjsTry,tjsDIV,tjsDIVEQ, tjsEnum];
  3399. Var
  3400. F : TJSFunctionDeclarationStatement;
  3401. C : TJSClassDeclaration;
  3402. E : TJSElement;
  3403. Done : Boolean;
  3404. VS : TJSElementNodes;
  3405. isAmbient, isAbstract, aSync : Boolean;
  3406. FF : TFunctionFlags;
  3407. procedure DefaultParsing;
  3408. begin
  3409. if CurrentToken in StatementTokens then
  3410. begin
  3411. E:=Self.ParseStatement(IsAmbient);
  3412. Result.Statements.AddNode(IsAmbient).Node:=E;
  3413. if E is TJSExportStatement then
  3414. AddToElements(Result,TJSExportStatement(E).Declaration,IsAmbient,True);
  3415. end
  3416. else
  3417. Done:=True;
  3418. end;
  3419. begin
  3420. {$ifdef debugparser} Writeln('>>> Entering source elements');{$endif}
  3421. Result:=TJSSourceElements(CreateElement(TJSSourceElements));
  3422. try
  3423. Done:=False;
  3424. aSync:=False;
  3425. VS:=FCurrentVars;
  3426. Try
  3427. FCurrentVars:=Result.Vars;
  3428. Repeat
  3429. {$ifdef debugparser} Writeln('Sourceelements start:',GetEnumName(TypeInfo(TJSToken),Ord(CurrentToken)), ' As string: ',CurrentTokenString);{$endif debugparser}
  3430. IsAmbient:=False;
  3431. if IsTypeScript then
  3432. begin
  3433. isAmbient:= (ScopeType in [stFunction,stModule]) and IsIdentifier('declare');
  3434. if IsAmbient then
  3435. GetNextToken
  3436. Else
  3437. begin
  3438. //isAmbient:= (ScopeType in [stModule,stNamespace]) and (CurrentToken=tjsEXPORT);
  3439. // if IsAmbient then
  3440. // GetNextToken;
  3441. end;
  3442. if IsAmbient then
  3443. begin
  3444. IsAbstract:=IsIdentifier('abstract');
  3445. if IsAbstract then
  3446. GetNextToken;
  3447. end;
  3448. end;
  3449. isAmbient:=isAmbient or ParentisAmbient;
  3450. aSync:= (ECMAVersion>=MinAsyncVersion) and IsIdentifier('async');
  3451. if aSync then
  3452. GetNextToken;
  3453. Case CurrentToken of
  3454. jstoken.tjsEOF:
  3455. done:=True;
  3456. jstoken.tjsFunction:
  3457. begin
  3458. If (PeekNextToken<>tjsBraceOpen) then
  3459. begin
  3460. FF:=[];
  3461. if isAmbient then
  3462. FF:=[ffAmbient];
  3463. F:=Self.ParseFunctionDeclaration(FF);
  3464. F.AFunction.IsAsync:=aSync;
  3465. Result.Functions.AddNode(IsAmbient,False).Node:=F;
  3466. end
  3467. else
  3468. begin
  3469. {$ifdef debugparser} Writeln('Function expression detected');{$endif}
  3470. E:=Self.ParseStatement;
  3471. Result.Statements.AddNode(IsAmbient).Node:=E;
  3472. end;
  3473. end;
  3474. jstoken.tjsClass:
  3475. begin
  3476. E:=Self.ParseClassStatement(isAmbient,isAbstract);
  3477. Result.Statements.AddNode(IsAmbient).Node:=E;
  3478. C:=TJSClassStatement(E).Decl;
  3479. Result.Classes.AddNode(IsAmbient).Node:=C;
  3480. end;
  3481. jstoken.tjsEnum:
  3482. begin
  3483. E:=Self.ParseEnumDeclarationStatement;
  3484. Result.Statements.AddNode(IsAmbient).Node:=E;
  3485. Result.Enums.AddNode(IsAmbient).Node:=TJSEnumStatement(E).EnumDecl;
  3486. end;
  3487. jsToken.tjsMul:
  3488. begin
  3489. if (ScopeType=stClass) then
  3490. begin
  3491. //
  3492. end
  3493. else
  3494. DefaultParsing;
  3495. end;
  3496. jsToken.tjsSQuaredBraceOpen:
  3497. begin
  3498. if isTypeScript and (ScopeType=stClass) then
  3499. begin
  3500. E:=Self.ParseIndexSignatureStatement;
  3501. Result.Statements.AddNode(IsAmbient).Node:=E;
  3502. Result.Vars.AddNode(IsAmbient).Node:=TJSIndexSignatureStatement(E).Decl;
  3503. end;
  3504. end;
  3505. else
  3506. // else of Case
  3507. if IsTypeScript then
  3508. begin
  3509. E:=ParseTypeStatement(Result,ScopeType,IsAmbient);
  3510. if E=Nil then
  3511. DefaultParsing;
  3512. end
  3513. else
  3514. DefaultParsing;
  3515. end;
  3516. {$ifdef debugparser} Writeln('Sourceelements Done : ',Done);{$endif}
  3517. Until Done;
  3518. Finally
  3519. FCurrentVars:=VS;
  3520. end;
  3521. except
  3522. FreeElement(Result);
  3523. Raise;
  3524. end;
  3525. {$ifdef debugparser} Writeln('<<< Exiting source elements');{$endif}
  3526. end;
  3527. function TJSParser.ParseFunctionBody : TJSFunctionBody;
  3528. Var
  3529. E : TJSElement;
  3530. begin
  3531. {$ifdef debugparser} Writeln('>>> Entering FunctionBody');{$endif}
  3532. Result:=TJSFunctionBody(CreateElement(TJSFunctionBody));
  3533. try
  3534. E:=Self.ParseSourceElements;
  3535. Result.A:=E;
  3536. except
  3537. FreeElement(Result);
  3538. Raise;
  3539. end;
  3540. {$ifdef debugparser} Writeln('<<< Exiting FunctionBody');{$endif}
  3541. end;
  3542. function TJSParser.ParseClassBody(isAmbient : Boolean): TJSSourceElements;
  3543. begin
  3544. {$ifdef debugparser} Writeln('>>> Entering ParseClassBody');{$endif}
  3545. Result:=Self.ParseSourceElements(stClass,IsAmbient);
  3546. {$ifdef debugparser} Writeln('<<< Exiting ParseClassBody');{$endif}
  3547. end;
  3548. procedure TJSParser.ClassDefToMembers(aClass : TJSClassDeclaration; aClassDef : TJSObjectTypeDef);
  3549. Var
  3550. El : TJSObjectTypeElementDef;
  3551. I : Integer;
  3552. begin
  3553. if (aClassDef.ElementCount>0) and (aClass.Members=Nil) then
  3554. aClass.Members:=TJSSourceElements(CreateElement(TJSSourceElements));
  3555. For I:=0 to aClassDef.ElementCount-1 do
  3556. begin
  3557. El:=aClassDef.Elements[i];
  3558. if El is TJSPropertyDeclaration then
  3559. aClass.Members.Vars.AddNode(True,False).Node:=El
  3560. else if El is TJSMethodDeclaration then
  3561. aClass.Members.Functions.AddNode(True,False).Node:=El;
  3562. end;
  3563. end;
  3564. function TJSParser.ParseClassDeclaration(isAmbient: Boolean; IsAbstract: Boolean): TJSClassDeclaration;
  3565. Var
  3566. // aName : jsBase.TJSString;
  3567. // aTypeDef : TJSTypeDef;
  3568. aClassDef : TJSObjectTypeDef;
  3569. begin
  3570. //aTypeDef:=Nil;
  3571. if IsAmbient then
  3572. Result:=TJSAmbientClassDeclaration(CreateElement(TJSAmbientClassDeclaration))
  3573. else
  3574. Result:=TJSClassDeclaration(CreateElement(TJSClassDeclaration));
  3575. try
  3576. Result.IsAbstract:=IsAbstract;
  3577. Consume(tjsClass);
  3578. if CurrentToken=tjsIdentifier then
  3579. Result.Name:=ParseIdentifier;
  3580. if CurrentToken=tjsLT then
  3581. begin
  3582. Result.TypeParams:=TJSElementNodes.Create(TJSElementNode);
  3583. ParseGenericParamList(Result.TypeParams);
  3584. Consume(tjsGT);
  3585. end;
  3586. if CurrentToken=tjsExtends then
  3587. begin
  3588. Consume(tjsExtends);
  3589. Result.Extends:=ParseTypeDef([ptoRefOnly,ptoFunctionCall],[tjsCurlyBraceOpen]);
  3590. end;
  3591. if IsIdentifier('implements') then
  3592. begin
  3593. Result.ImplementsTypes:=TJSElementNodes.Create(TJSElementNode);
  3594. Consume(tjsIdentifier);
  3595. Repeat
  3596. if CurrentToken=tjsComma then
  3597. GetNextToken;
  3598. Result.ImplementsTypes.AddNode(ParseTypeDef());
  3599. Until (CurrentToken<>tjsComma);
  3600. end;
  3601. if IsAmbient then
  3602. begin
  3603. aClassDef:=TJSObjectTypeDef(CreateElement(TJSObjectTypeDef));
  3604. TJSAmbientClassDeclaration(Result).ClassDef:=aClassDef;
  3605. ParseAmbientClassBody(aClassDef);
  3606. Consume(tjsCurlyBraceClose);
  3607. ClassDefToMembers(Result,aClassDef);
  3608. end
  3609. else
  3610. begin
  3611. Consume(tjsCurlyBraceOpen);
  3612. Result.Members:=ParseClassBody(IsAmbient);
  3613. Consume(tjsCurlyBraceClose);
  3614. end;
  3615. except
  3616. FreeElement(Result);
  3617. Raise;
  3618. end;
  3619. end;
  3620. Procedure TJSParser.ParseAmbientClassBody(aObj: TJSObjectTypeDef);
  3621. // On entry on {
  3622. // On exit on }
  3623. Function ParseAccessibility : TAccessibility;
  3624. begin
  3625. Result:=accDefault;
  3626. if CurrentToken=tjsIdentifier then
  3627. Case CurrentTokenString of
  3628. 'private' : Result:=accPrivate;
  3629. 'public' : Result:=accPublic;
  3630. 'protected' : Result:=accProtected;
  3631. end;
  3632. if Result<>accDefault then
  3633. begin
  3634. if PeekNextToken=tjsColon then
  3635. Result:=accDefault
  3636. else
  3637. GetNextToken;
  3638. end;
  3639. end;
  3640. Function CreateAny : TJSTypeReference;
  3641. begin
  3642. Result:=TJSTypeReference(CreateElement(TJSTypeReference));
  3643. Result.Name:='any';
  3644. end;
  3645. Function CheckSpecial(aName : jsBase.TJSstring) : Boolean;
  3646. begin
  3647. Result:=IsIdentifier(aName) and Not (PeekNextToken in [tjsConditional,tjsColon]);
  3648. If Result then
  3649. GetNextToken;
  3650. end;
  3651. var
  3652. aName : jsBase.TJSString;
  3653. IsSet, IsGet, IsAbstract,isStatic, isReadOnly, isOptional : Boolean;
  3654. E : TJSObjectTypeElementDef;
  3655. F : TJSMethodDeclaration ;
  3656. FS : TJSFunctionDeclarationStatement;
  3657. FuncF : TFunctionFlags;
  3658. TP : TJSElementNodes;
  3659. acc : TAccessibility;
  3660. begin
  3661. Consume(tjsCurlyBraceOpen);
  3662. While (CurrentToken<>tjsCurlyBraceClose) do
  3663. begin
  3664. aName:='';
  3665. E:=Nil;
  3666. acc:=ParseAccessibility;
  3667. isStatic:=IsIdentifier('static');
  3668. if IsStatic then
  3669. GetNextToken;
  3670. isAbstract:=IsIdentifier('abstract');
  3671. if IsAbstract then
  3672. GetNextToken;
  3673. isReadOnly:=CheckSpecial('readonly');
  3674. isGet:=CheckSpecial('get');
  3675. isSet:=CheckSpecial('set');
  3676. If CurrentTokenIsValidIdentifier then
  3677. begin
  3678. aName:=CurrentTokenString;
  3679. GetNextToken;
  3680. end
  3681. else if (IsGet or IsSet) and (CurrentToken=tjsBraceOpen) then
  3682. begin
  3683. // Regular get/set methods.
  3684. If IsGet then
  3685. aName:='get'
  3686. else
  3687. aName:='set';
  3688. isGet:=False;
  3689. isSet:=False;
  3690. end
  3691. else
  3692. if (Not (CurrentToken in [tjsBraceOpen,tjsLT,tjsSQuaredBraceOpen,tjsNew])) then
  3693. Error(SErrObjectElement,[CurrentTokenString]);
  3694. isOptional:=(CurrentToken=tjsConditional);
  3695. if isOPtional then
  3696. GetNextToken;
  3697. case CurrentToken of
  3698. // static readonly A = B;
  3699. tjsAssign :
  3700. begin
  3701. if not (isStatic and isReadOnly) then
  3702. Error(SErrObjConstMustBeStaticReadonly);
  3703. GetNextToken;
  3704. E:=TJSClassConstDeclaration(CreateElement(TJSClassConstDeclaration));
  3705. E.Name:=aName;
  3706. TJSClassConstDeclaration(E).Value:=ParseExpression;
  3707. end;
  3708. tjsSQuaredBraceOpen:
  3709. begin
  3710. // [a:type] : Type
  3711. E:=ParseIndexSignature;
  3712. end;
  3713. // PropertyName : PropertyType
  3714. tjsColon:
  3715. begin
  3716. Consume(tjsColon);
  3717. E:=TJSPropertyDeclaration(CreateElement(TJSPropertyDeclaration));
  3718. E.Name:=aName;
  3719. E.ElementType:=ParseTypeDef([ptoAllowLiteral],[tjsComma,tjsSemicolon]);
  3720. end;
  3721. // <T1> () : TypeName;
  3722. // () : TypeName;
  3723. tjsNew,
  3724. tjsWith,
  3725. tjsLT,
  3726. tjsBraceOpen:
  3727. begin
  3728. if CurrentToken=tjsNew then
  3729. begin
  3730. aName:='new';
  3731. GetNextToken;
  3732. end;
  3733. if CurrentToken=tjsWith then
  3734. begin
  3735. aName:='with';
  3736. GetNextToken;
  3737. end;
  3738. FuncF:=[ffGenerator];
  3739. if aName='constructor' then
  3740. Include(FuncF,ffConstructor);
  3741. TP:=Nil;
  3742. F:=TJSMethodDeclaration(CreateElement(TJSMethodDeclaration));
  3743. F.Name:=aName;
  3744. E:=F;
  3745. if CurrentToken=tjsLT then
  3746. begin
  3747. TP:=TJSElementNodes.Create(TJSElementNode);
  3748. ParseGenericParamList(TP);
  3749. consume(tjsGT);
  3750. end;
  3751. FS:=ParseFunctionExpression(FuncF);
  3752. FS.AFunction.Name:=aName;
  3753. F.FuncDef:=FS.AFunction;
  3754. FS.AFunction:=Nil;
  3755. F.TypeParams:=TP;
  3756. if Not Assigned(F.Funcdef.ResultType) then
  3757. F.Funcdef.ResultType:=CreateAny;
  3758. FreeElement(FS);
  3759. end;
  3760. tjsComma,tjsSemicolon:
  3761. begin
  3762. // PropertyName ; Type is any
  3763. E:=TJSPropertyDeclaration(CreateElement(TJSPropertyDeclaration));
  3764. E.Name:=aName;
  3765. E.ElementType:=CreateAny;
  3766. end;
  3767. else
  3768. Error(SErrExpectedColonBrace,[CurrentTokenString]);
  3769. end;
  3770. if Assigned(E) then
  3771. begin
  3772. E.Accessibility:=acc;
  3773. if IsOptional then
  3774. E.Optional:=koOptional;
  3775. E.IsStatic:=IsStatic;
  3776. E.IsAbstract:=IsAbstract;
  3777. E.IsGet:=IsGet;
  3778. E.IsSet:=IsSet;
  3779. E.IsReadonly:=IsReadonly;
  3780. aObj.AddElement(E);
  3781. end;
  3782. While CurrentToken in [tjsComma,tjsSemicolon] do
  3783. GetNextToken;
  3784. end;
  3785. Expect(tjsCurlyBraceClose);
  3786. end;
  3787. function TJSParser.ParseClassStatement(isAmbient : Boolean; IsAbstract : Boolean = False): TJSClassStatement;
  3788. begin
  3789. Result:=TJSClassStatement(CreateElement(TJSClassStatement));
  3790. try
  3791. Result.Decl:=ParseClassDeclaration(isAmbient,IsAbstract);
  3792. except
  3793. FreeElement(Result);
  3794. Raise;
  3795. end;
  3796. end;
  3797. function TJSParser.ParseClassExpression: TJSClassDeclaration;
  3798. Var
  3799. Oni,olhs: Boolean;
  3800. C : TJSClassDeclaration;
  3801. aName : jsBase.TJSString;
  3802. aType : TJSTypeDef;
  3803. begin
  3804. {$ifdef debugparser} Writeln('>>> ParseClassExpression');{$endif}
  3805. oni:=NoIn;
  3806. olhs:=IsLHS;
  3807. C:=Nil;
  3808. aType:=Nil;
  3809. try
  3810. NoIn:=False;
  3811. IsLHS:=False;
  3812. C:=TJSClassDeclaration(CreateElement(TJSClassDeclaration));
  3813. try
  3814. Consume(tjsClass);
  3815. if CurrentToken=tjsIdentifier then
  3816. aName:=ParseIdentifier;
  3817. if CurrentToken=tjsExtends then
  3818. begin
  3819. Consume(tjsExtends);
  3820. aType:=ParseTypeDef;
  3821. end;
  3822. Consume(tjsCurlyBraceOpen);
  3823. C.Name:=aName;
  3824. C.Extends:=aType;
  3825. C.Members:=ParseClassBody;
  3826. Consume(tjsCurlyBraceClose);
  3827. Result:=C;
  3828. except
  3829. FreeElement(C);
  3830. Raise;
  3831. end;
  3832. finally
  3833. NoIn := oni;
  3834. IsLHS := olhs;
  3835. end;
  3836. {$ifdef debugparser} Writeln('<<< ParseClassExpression');{$endif}
  3837. end;
  3838. function TJSParser.ParseModuleDeclaration: TJSModuleDeclaration;
  3839. // On entry we're on module keyword
  3840. // on exit, we're after closing }
  3841. Var
  3842. aName : jsBase.TJSString;
  3843. begin
  3844. Consume(tjsIdentifier);
  3845. if CurrentToken=tjsIdentifier then
  3846. begin
  3847. aName:=CurrentTokenString;
  3848. consume(tjsIdentifier);
  3849. end
  3850. else
  3851. begin
  3852. Expect(jstoken.tjsString);
  3853. aname:=CurrentTokenString;
  3854. Consume(jsToken.tjsString);
  3855. end;
  3856. Result:=TJSModuleDeclaration(CreateElement(TJSModuleDeclaration));
  3857. try
  3858. Result.Name:=aName;
  3859. Expect(tjsCurlyBraceOpen);
  3860. Consume(tjsCurlyBraceOpen);
  3861. Result.Members:=ParseModuleBody;
  3862. Consume(tjsCurlyBraceClose);
  3863. except
  3864. FreeElement(Result);
  3865. Raise;
  3866. end;
  3867. end;
  3868. function TJSParser.ParseInterfaceDeclarationStatement: TJSInterfaceStatement;
  3869. begin
  3870. Result:=TJSInterfaceStatement(CreateElement(TJSInterfaceStatement));
  3871. try
  3872. Result.Decl:=ParseInterfaceDeclaration;
  3873. except
  3874. FreeElement(Result);
  3875. Raise;
  3876. end;
  3877. end;
  3878. function TJSParser.ParseInterfaceDeclaration: TJSInterfaceDeclaration;
  3879. Var
  3880. aName : jsBase.TJSString;
  3881. PT : TJSElementNodes;
  3882. begin
  3883. Consume(tjsIdentifier);
  3884. aName:=ParseIdentifier;
  3885. Result:=TJSInterfaceDeclaration(CreateElement(TJSInterfaceDeclaration));
  3886. try
  3887. Result.Name:=aName;
  3888. if (CurrentToken=tjsLt) then
  3889. begin
  3890. Result.TypeParams:=TJSElementNodes.Create(TJSElementNode);
  3891. ParseGenericParamList(Result.TypeParams);
  3892. Consume(tjsGT);
  3893. end;
  3894. if (CurrentToken=tjsExtends) then
  3895. begin
  3896. Consume(tjsExtends);
  3897. While CurrentToken<>tjsCurlyBraceOpen do
  3898. begin
  3899. PT:=Nil;
  3900. aName:=ParseIdentifier;
  3901. if CurrentToken=tjsLT then
  3902. begin
  3903. PT:=TJSElementNodes.Create(TJSElementNode);
  3904. ParseGenericParamList(PT);
  3905. Consume(tjsGT);
  3906. FreeElement(PT);
  3907. end;
  3908. Result.AddExtends(aName);
  3909. if CurrentToken=tjsComma then
  3910. Consume(tjsComma);
  3911. end;
  3912. end;
  3913. ParseObjectBody(Result);
  3914. Consume(tjsCurlyBraceClose);
  3915. except
  3916. FreeElement(Result);
  3917. Raise;
  3918. end;
  3919. end;
  3920. function TJSParser.ParseModuleBody: TJSSourceElements;
  3921. begin
  3922. {$ifdef debugparser} Writeln('>>> Entering ParseModuleBody');{$endif}
  3923. Result:=Self.ParseSourceElements(stModule,IsTypeScript);
  3924. {$ifdef debugparser} Writeln('<<< Exiting ParseModuleBody');{$endif}
  3925. end;
  3926. function TJSParser.ParseNamespaceDeclaration(IsAmbient : Boolean): TJSNamespaceDeclaration;
  3927. // On entry we're on namespace or global keyword
  3928. // on exit, we're after closing }
  3929. Var
  3930. aName : jsBase.TJSString;
  3931. IsGlobal : Boolean;
  3932. begin
  3933. IsGlobal:=IsIdentifier('global');
  3934. Consume(tjsIdentifier); // namespace
  3935. if not IsGlobal then
  3936. aname:=ParseIdentifier;
  3937. Result:=TJSNamespaceDeclaration(CreateElement(TJSNamespaceDeclaration));
  3938. try
  3939. Result.IsGlobal:=IsGLobal;
  3940. Result.Name:=aName;
  3941. Consume(tjsCurlyBraceOpen);
  3942. Result.Members:=ParseNamespaceBody(IsAmbient);
  3943. Consume(tjsCurlyBraceClose);
  3944. except
  3945. FreeElement(Result);
  3946. Raise;
  3947. end;
  3948. end;
  3949. function TJSParser.ParseNamespaceBody(IsAmbient : Boolean): TJSSourceElements;
  3950. begin
  3951. {$ifdef debugparser} Writeln('>>> Entering ParseModuleBody');{$endif}
  3952. Result:=Self.ParseSourceElements(stNamespace,IsAmbient);
  3953. {$ifdef debugparser} Writeln('<<< Exiting ParseModuleBody');{$endif}
  3954. end;
  3955. Function TJSParser.ParseProgram: TJSFunctionDeclarationStatement;
  3956. Var
  3957. B : TJSElement;
  3958. begin
  3959. {$ifdef debugparser} Writeln('>>> Entering FunctionDeclarationStatement');{$endif}
  3960. B:=Parse;
  3961. If Not (B is TJSFunctionBody) then
  3962. Error('Parse did not result in functionbody');
  3963. Result:=TJSFunctionDeclarationStatement(CreateElement(TJSFunctionDeclarationStatement));
  3964. Result.AFunction:=TJSFuncDef.Create;
  3965. Result.AFunction.Body:=TJSFunctionBody(B);
  3966. {$ifdef debugparser} Writeln('<<< Exiting FunctionDeclarationStatement');{$endif}
  3967. end;
  3968. Function TJSParser.Parse: TJSElement;
  3969. Var
  3970. Body : TJSElement;
  3971. begin
  3972. {$ifdef debugparser} Writeln('>>> Parse');{$endif}
  3973. Result:=Nil;
  3974. CheckParser;
  3975. GetNextToken;
  3976. Body:=ParseFunctionBody;
  3977. Result:=Body;
  3978. try
  3979. if (CurrentToken<>tjsEOF) then
  3980. begin
  3981. if (CurrentToken=tjsCurlyBraceClose) then
  3982. Error(SErrUnmatchedCurlyBrace)
  3983. else if (CurrentToken=tjsBraceClose) then
  3984. Error(SerrUnmatchedBrace)
  3985. else if (CurrentToken=tjsSquaredBraceClose) then
  3986. Error(SerrUnmatchedSquareBrace);
  3987. Error(SErrUnexpectedToken,[CurrentTokenString]);
  3988. end;
  3989. If (Body is TJSFunctionBody) then
  3990. TJSFunctionBody(Body).isProgram:=True;
  3991. except
  3992. FreeElement(Result);
  3993. Raise;
  3994. end;
  3995. {$ifdef debugparser} Writeln('<<< Parse');{$endif}
  3996. end;
  3997. end.