jsparser.pp 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147
  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. interface
  15. uses
  16. Classes, SysUtils, jsscanner, jstree, jstoken;
  17. Const
  18. SEmptyLabel = '';
  19. Type
  20. { TJSParser }
  21. TJSParser = Class(TObject)
  22. Private
  23. FFunctionDepth: Integer;
  24. FInput : TStream;
  25. FIsLHS: Boolean;
  26. FNoIn: Boolean;
  27. FScanner : TJSScanner;
  28. FPrevious,
  29. FCurrent : TJSToken;
  30. FCurrentString : String;
  31. FFreeScanner : Boolean;
  32. FCurrentVars : TJSElementNodes;
  33. FPeekToken: TJSToken;
  34. FPeekTokenString: String;
  35. FLabelSets,
  36. FCurrentLabelSet:TJSLabelSet;
  37. FLabels : TJSLabel;
  38. function CheckSemiColonInsert(aToken: TJSToken; Consume: Boolean): Boolean;
  39. function EnterLabel(ALabelName: String): TJSLabel;
  40. procedure Expect(aToken: TJSToken);
  41. procedure Consume(aToken: TJSToken; AllowSemicolonInsert : Boolean = False);
  42. procedure FreeCurrentLabelSet;
  43. procedure LeaveLabel;
  44. function LookupLabel(ALabelName: String; Kind: TJSToken): TJSLabel;
  45. function ParseAdditiveExpression: TJSElement;
  46. function ParseArguments: TJSarguments;
  47. function ParseArrayLiteral: TJSElement;
  48. function ParseAssignmentExpression: TJSElement;
  49. function ParseBitwiseAndExpression: TJSElement;
  50. function ParseBitwiseORExpression: TJSElement;
  51. function ParseBitwiseXORExpression: TJSElement;
  52. function ParseBlock: TJSElement;
  53. function ParseBreakStatement: TJSElement;
  54. function ParseConditionalExpression: TJSElement;
  55. function ParseContinueStatement: TJSElement;
  56. function ParseEmptyStatement: TJSElement;
  57. function ParseEqualityExpression: TJSElement;
  58. function ParseExpression: TJSElement;
  59. function ParseExpressionStatement: TJSElement;
  60. function ParseFormalParameterList: TStrings;
  61. function ParseFunctionDeclaration: TJSFunctionDeclarationStatement;
  62. function ParseFunctionExpression: TJSFunctionDeclarationStatement;
  63. function ParseFunctionStatement: TJSElement;
  64. function ParseFunctionBody: TJSFunctionBody;
  65. function ParseIdentifier: String;
  66. function ParseIfStatement: TJSElement;
  67. function ParseIterationStatement: TJSElement;
  68. function ParseLabeledStatement: TJSElement;
  69. function ParseLeftHandSideExpression: TJSElement;
  70. function ParseLiteral: TJSElement;
  71. function ParseLogicalAndExpression: TJSElement;
  72. function ParseLogicalORExpression: TJSElement;
  73. function ParseMemberExpression: TJSElement;
  74. function ParseMultiplicativeExpression: TJSElement;
  75. function ParseNumericLiteral: TJSElement;
  76. function ParseObjectLiteral: TJSElement;
  77. function ParsePostFixExpression: TJSElement;
  78. function ParsePrimaryExpression: TJSElement;
  79. function ParseRegularExpressionLiteral: TJSElement;
  80. function ParseRelationalExpression: TJSElement;
  81. function ParseReturnStatement: TJSElement;
  82. function ParseShiftExpression: TJSElement;
  83. function ParseStatement: TJSElement;
  84. function ParseStatementList: TJSElement;
  85. function ParseStringLiteral: TJSElement;
  86. function ParseSwitchStatement: TJSElement;
  87. function ParseThrowStatement: TJSElement;
  88. function ParseTryStatement: TJSElement;
  89. function ParseUnaryExpression: TJSElement;
  90. function ParseVariableDeclaration: TJSElement;
  91. function ParseVariableDeclarationList: TJSElement;
  92. function ParseVariableStatement: TJSElement;
  93. function ParseWithStatement: TJSElement;
  94. Protected
  95. Procedure CheckParser;
  96. Function CurrentLabelSet : TJSLabelSet;
  97. function CurSource: String;
  98. Function CurLine : Integer;
  99. Function CurPos : Integer;
  100. Function CreateElement(AElementClass : TJSElementClass) : TJSElement;
  101. Procedure Error(Msg : String);
  102. Procedure Error(Fmt : String; Args : Array of const);
  103. // Parse functions
  104. function ParseSourceElements: TJSSourceElements;
  105. Property FunctionDepth : Integer Read FFunctionDepth Write FFunctionDepth;
  106. Property NoIn : Boolean Read FNoIn Write FNoIn;
  107. Property IsLHS : Boolean Read FIsLHS Write FIsLHS;
  108. Public
  109. Constructor Create(AInput: TStream);
  110. Constructor Create(AScanner : TJSScanner);
  111. Destructor Destroy; override;
  112. Function Parse : TJSElement;
  113. Function ParseProgram : TJSFunctionDeclarationStatement;
  114. Function CurrentToken : TJSToken;
  115. Function CurrentTokenString : String;
  116. Function GetNextToken : TJSToken;
  117. Function PeekNextToken : TJSToken;
  118. Function IsEndOfLine : Boolean;
  119. end;
  120. implementation
  121. uses typinfo;
  122. Resourcestring
  123. SErrUnmatchedCurlyBrace = 'Unmatched }';
  124. SErrUnmatchedSquareBrace = 'Unmatched ]';
  125. SErrUnmatchedBrace = 'Unmatched )';
  126. SErrUnexpectedToken = 'Unexpected token: ''%s''';
  127. SErrTokenMismatch = 'Unexpected token: ''%s'', expected: ''%s''';
  128. SErrSemicolonOrInExpected = 'Unexpected token: ''%s'', expected ; or ''in''';
  129. SErrSemicolonExpected = 'Unexpected token: ''%s'', expected ;';
  130. SErrDuplicateLabelName = 'Duplicate label name: ''%s''';
  131. SErrLabelNotContinuable = 'Label ''%s'' is not suitable for continue.';
  132. SErrLabelNOtDefinedOrReachable = 'Label ''%s'' is not defined or not reachable.';
  133. SErrContinueNotInLoop = 'Continue statement not in loop';
  134. SErrBreakNotInLoop = 'Break statement not in loop';
  135. SErrReturnNotInFunction = 'return statement not in a function body';
  136. SErrCaseEndExpected = 'Unexpected token: Expected }, case or default clause';
  137. SErrDuplicateSwitchDefault = 'Duplicate default clause for switch statement';
  138. SErrNewlineAfterThrow = 'Newline after throw not allowed';
  139. SErrCatchFinallyExpected = 'Unexpected token: Expected ''catch'' or ''finally''';
  140. SErrArgumentsExpected = 'Unexpected token: Expected '','' or '')'', got %s';
  141. SErrArrayEnd = 'Unexpected token: Expected '','' or '']'', got %s';
  142. //SErrObjectEnd = 'Unexpected token: Expected '','' or ''}'', got %s';
  143. SErrObjectElement = 'Unexpected token: Expected string, identifier or number after '','' got: %s';
  144. SErrLiteralExpected = 'Unexpected token: Expected: null, true, false, number, string, or regex, got: %s';
  145. SErrInvalidnumber = 'Invalid numerical value: %s';
  146. SErrInvalidRegularExpression = 'Invalid regular expression: %s';
  147. SErrFunctionNotAllowedHere = 'function keyword not allowed here';
  148. { TJSScanner }
  149. Function TJSParser.CurrentToken: TJSToken;
  150. begin
  151. Result:=FCurrent;
  152. end;
  153. Function TJSParser.CurrentTokenString: String;
  154. begin
  155. Result:=FCurrentString;
  156. end;
  157. Function TJSParser.GetNextToken: TJSToken;
  158. begin
  159. FPrevious:=FCurrent;
  160. If (FPeekToken<>tjsunknown) then
  161. begin
  162. FCurrent:=FPeekToken;
  163. FCurrentString:=FPeekTokenString;
  164. FPeekToken:=tjsUnknown;
  165. FPeekTokenString:='';
  166. end
  167. else
  168. begin
  169. FCurrent:=FScanner.FetchToken;
  170. FCurrentString:=FScanner.CurTokenString;
  171. end;
  172. Result:=FCurrent;
  173. {$ifdef debugparser}Writeln('GetNextToken (',FScanner.CurLine,',',FScanner.CurColumn,'): ',GetEnumName(TypeInfo(TJSToken),Ord(FCurrent)), ' As string: ',FCurrentString);{$endif debugparser}
  174. end;
  175. Function TJSParser.PeekNextToken: TJSToken;
  176. begin
  177. If (FPeekToken=tjsUnknown) then
  178. begin
  179. FPeekToken:=FScanner.FetchToken;
  180. FPeekTokenString:=FScanner.CurTokenString;
  181. end;
  182. {$ifdef debugparser}Writeln('PeekNextToken : ',GetEnumName(TypeInfo(TJSToken),Ord(FPeekToken)), ' As string: ',FPeekTokenString);{$endif debugparser}
  183. Result:=FPeekToken;
  184. end;
  185. Function TJSParser.IsEndOfLine: Boolean;
  186. begin
  187. Result:=FScanner.IsEndOfLine;
  188. end;
  189. Function TJSParser.CurPos: Integer;
  190. begin
  191. If Assigned(FScanner) then
  192. Result:=FScanner.CurColumn
  193. else
  194. Result:=0;
  195. end;
  196. Function TJSParser.CurLine: Integer;
  197. begin
  198. If Assigned(FScanner) then
  199. Result:=FScanner.CurRow
  200. else
  201. Result:=0;
  202. end;
  203. function TJSParser.CurSource: String;
  204. begin
  205. If Assigned(FScanner) then
  206. Result:=FScanner.CurFileName
  207. else
  208. Result:='';
  209. end;
  210. Procedure TJSParser.CheckParser;
  211. begin
  212. end;
  213. procedure TJSParser.LeaveLabel;
  214. Var
  215. L : TJSLabel;
  216. begin
  217. L:=FLabels;
  218. FLabels:=FLabels.Next;
  219. L.Free; // ??
  220. end;
  221. function TJSParser.LookupLabel(ALabelName : String; Kind : TJSToken) :TJSLabel;
  222. Var
  223. L : TJSLabel;
  224. begin
  225. L:=FLabels;
  226. Result:=Nil;
  227. While (L<>Nil) and (Result=Nil) do
  228. begin
  229. If (L.Name=ALabelName) then
  230. begin
  231. if (kind=tjsContinue) and (Not L.LabelSet.Continuable) and (ALabelName<>SEmptyLabel) then
  232. Error(SErrLabelNotContinuable,[ALabelName]);
  233. Result:=L;
  234. end;
  235. L:=L.Next;
  236. end;
  237. If (Result=Nil) then
  238. begin
  239. If (ALabelName<>'') then
  240. Error(SErrLabelNOtDefinedOrReachable,[ALabelName])
  241. else if kind=tjsCOntinue then
  242. Error(SErrContinueNotInLoop)
  243. else
  244. Error(SErrBreakNotInLoop);
  245. end;
  246. end;
  247. function TJSParser.EnterLabel(ALabelName : String) :TJSLabel;
  248. Var
  249. L : TJSLabel;
  250. begin
  251. If (ALAbelName<>SEmptyLabel) then
  252. begin
  253. L:=FLabels;
  254. While (L<>Nil) do
  255. begin
  256. If (L.Name=ALabelName) then
  257. Error(SErrDuplicateLabelName,[ALabelName]);
  258. L:=L.Next;
  259. end;
  260. end;
  261. L:=TJSLabel.Create;
  262. L.Name:=ALabelName;
  263. L.LabelSet:=CurrentLabelSet;
  264. L.LocationSource:=Self.CurSource;
  265. L.LocationLine:=CurLine;
  266. L.LocationPos:=CurPos;
  267. L.Next:=FLabels;
  268. FLabels:=L;
  269. Result:=L;
  270. end;
  271. Function TJSParser.CurrentLabelSet: TJSLabelSet;
  272. Var
  273. LS : TJSLabelSet;
  274. begin
  275. If (FCurrentLabelSet=Nil) then
  276. begin
  277. LS:=TJSLabelSet.Create;
  278. If (FLabelSets=Nil) then
  279. LS.Target:=1
  280. else
  281. LS.Target:=FLabelSets.Target;
  282. LS.Next:=FLabelSets;
  283. FLabelSets:=LS;
  284. FCurrentLabelSet:=LS;
  285. end;
  286. Result:=FCurrentLabelSet;
  287. end;
  288. Function TJSParser.CreateElement(AElementClass: TJSElementClass): TJSElement;
  289. begin
  290. Result:=AElementClass.Create(CurLine,CurPos,CurSource);
  291. end;
  292. Procedure TJSParser.Error(Msg: String);
  293. Var
  294. ErrAt : String;
  295. begin
  296. If Assigned(FScanner) then
  297. If FScanner.CurFilename<>'' then
  298. ErrAt:=Format('Error: file "%s" line %d, pos %d: ',[FScanner.CurFileName,FScanner.CurRow,FScanner.CurColumn])
  299. else
  300. ErrAt:=Format('Error: line %d, pos %d: ',[FScanner.Currow,FScanner.CurColumn]);
  301. Raise Exception.Create(ErrAt+Msg)
  302. end;
  303. Procedure TJSParser.Error(Fmt: String; Args: Array of const);
  304. begin
  305. Error(Format(Fmt,Args));
  306. end;
  307. Constructor TJSParser.Create(AInput: TStream);
  308. begin
  309. FInput:=AInput;
  310. FCurrent:=TJSUnknown;
  311. FScanner:=TJSScanner.Create(FInput);
  312. FFreeScanner:=True;
  313. end;
  314. Constructor TJSParser.Create(AScanner: TJSScanner);
  315. begin
  316. FCurrent:=TJSUnknown;
  317. FScanner:=AScanner;
  318. FFreeScanner:=False;
  319. end;
  320. Destructor TJSParser.Destroy;
  321. begin
  322. if FFreeScanner then
  323. FreeAndNil(FScanner);
  324. inherited;
  325. end;
  326. procedure TJSParser.Expect(aToken: TJSToken);
  327. begin
  328. {$ifdef debugparser} Writeln('Expecting : ',GetEnumName(TypeInfo(TJSToken),Ord(AToken)), ' As string: ',TokenInfos[AToken]);{$endif debugparser}
  329. If Not CheckSemiColonInsert(AToken,False) then
  330. if (CurrentToken<>aToken) then
  331. Error(SerrTokenMismatch,[CurrenttokenString,TokenInfos[aToken]]);
  332. end;
  333. function TJSParser.CheckSemiColonInsert(aToken : TJSToken; Consume : Boolean) : Boolean;
  334. begin
  335. Result:=(AToken=tjsSemiColon);
  336. If Result then
  337. begin
  338. Result:=(CurrentToken=tjsCurlyBraceClose) or (FScanner.WasEndOfLine) or (CurrentToken=tjsEOF);
  339. If Result and Consume then
  340. FPrevious:=tjsSemiColon;
  341. end;
  342. end;
  343. procedure TJSParser.Consume(aToken: TJSToken; AllowSemicolonInsert: Boolean);
  344. begin
  345. {$ifdef debugparser} Writeln('Consuming : ',GetEnumName(TypeInfo(TJSToken),Ord(AToken)), ' As string: ',TokenInfos[AToken]);{$endif debugparser}
  346. Expect(aToken);
  347. If not (AllowSemiColonInsert and CheckSemiColonInsert(aToken,True)) then
  348. GetNextToken;
  349. end;
  350. function TJSParser.ParseIdentifier : String;
  351. begin
  352. Result:='';
  353. Repeat
  354. Expect(tjsIdentifier);
  355. Result:=Result+CurrentTokenString;
  356. GetNextToken;
  357. If (CurrentToken=tjsDot) then
  358. begin
  359. If (Result<>'') then
  360. Result:=Result+'.';
  361. GetNextToken;
  362. end;
  363. until (CurrentToken<>tjsIdentifier);
  364. end;
  365. function TJSParser.ParseFormalParameterList : TStrings;
  366. begin
  367. Result:=Nil;
  368. While (CurrentToken=tjsIdentifier) do
  369. begin
  370. Expect(tjsIdentifier);
  371. If (Result=Nil) then
  372. Result:=TstringList.Create;
  373. Result.Add(CurrentTokenString);
  374. GetNextToken;
  375. If (CurrentToken=tjsComma) then
  376. GetNextToken;
  377. end;
  378. end;
  379. function TJSParser.ParseFunctionDeclaration : TJSFunctionDeclarationStatement;
  380. Var
  381. Id : String;
  382. D : TJSFuncDef;
  383. args : TStrings;
  384. body : TJSFunctionBody;
  385. begin
  386. {$ifdef debugparser} Writeln('>>> Entering ParseFunctionDeclaration');{$endif debugparser}
  387. Consume(tjsFunction);
  388. ID:=ParseIdentifier;
  389. Consume(tjsBraceOpen);
  390. Args:=ParseFormalParameterList;
  391. try
  392. Consume(tjsBraceClose);
  393. Consume(tjsCurlyBraceOpen);
  394. Inc(FFunctionDepth);
  395. try
  396. Body:=ParseFunctionBody;
  397. try
  398. // GetNextToken; not sure
  399. Consume(tjsCurlyBraceClose);
  400. D:=TJSFuncDef.Create;
  401. try
  402. D.Name:=ID;
  403. If Assigned(Args)then
  404. D.Params.Assign(Args);
  405. D.Body:=Body;
  406. Result:=TJSFunctionDeclarationStatement(CreateElement(TJSFunctionDeclarationStatement));
  407. Result.AFunction:=D;
  408. except
  409. FreeAndNil(D);
  410. Raise;
  411. end;
  412. except
  413. FreeAndNil(Body);
  414. Raise;
  415. end;
  416. finally
  417. Dec(FFunctionDepth);
  418. end;
  419. finally
  420. FreeAndNil(Args);
  421. end;
  422. {$ifdef debugparser} Writeln('>>> Exiting ParseFunctionDeclaration');{$endif debugparser}
  423. end;
  424. function TJSParser.ParseStatementList : TJSElement;
  425. Var
  426. E : TJSElement;
  427. SL : TJSSTatementList;
  428. begin
  429. {$ifdef debugparser} Writeln('>>> ParseStatementList');{$endif debugparser}
  430. E:=ParseStatement;
  431. try
  432. if (CurrentToken in [tjsCurlyBraceClose,tjsEof,tjsCase,tjsDefault]) then
  433. Result:=E
  434. else
  435. begin
  436. SL:=TJSSTatementList(CreateElement(TJSStatementList));
  437. try
  438. SL.A:=E;
  439. SL.B:=ParseStatementlist();
  440. Result:=SL;
  441. except
  442. FreeAndNil(SL);
  443. Raise;
  444. end;
  445. end;
  446. except
  447. FreeAndNil(E);
  448. Raise;
  449. end;
  450. {$ifdef debugparser} Writeln('<<< ParseStatementList');{$endif debugparser}
  451. end;
  452. function TJSParser.ParseBlock : TJSElement;
  453. begin
  454. {$ifdef debugparser} Writeln('>>> ParseBlock');{$endif debugparser}
  455. Consume(tjsCurlyBraceOpen);
  456. If (CurrentToken=tjsCurlyBraceClose) then
  457. Result:=CreateElement(TJSEmptyBlockStatement)
  458. else
  459. result:=ParseStatementList;
  460. Consume(tjsCurlyBraceClose);
  461. {$ifdef debugparser} Writeln('<<< ParseBlock');{$endif debugparser}
  462. end;
  463. function TJSParser.ParseArrayLiteral: TJSElement;
  464. Var
  465. N : TJSArrayLiteral;
  466. E : TJSArrayLiteralElement;
  467. I : Integer;
  468. begin
  469. Consume(tjsSquaredBraceOpen);
  470. N:=TJSArrayLiteral(CreateElement(TJSArrayLiteral));
  471. Result:=N;
  472. try
  473. I:=0;
  474. While (CurrentToken<>tjsSquaredBraceClose) do
  475. begin
  476. If (CurrentToken=tjsComma) then
  477. begin
  478. GetNextToken;
  479. Inc(I);
  480. end
  481. else
  482. begin
  483. E:=N.Elements.AddElement;
  484. E.ElementIndex:=I;
  485. Inc(I);
  486. E.Expr:=ParseAssignmentExpression;
  487. If Not (CurrentToken in [tjsComma,tjsSquaredBraceClose]) then
  488. Error(SErrArrayEnd,[CurrentTokenString])
  489. end;
  490. end;
  491. Consume(tjsSquaredBraceClose);
  492. except
  493. FreeAndNil(Result);
  494. Raise;
  495. end;
  496. end;
  497. function TJSParser.ParseObjectLiteral: TJSElement;
  498. Var
  499. N : TJSObjectLiteral;
  500. E : TJSObjectLiteralElement;
  501. begin
  502. Consume(tjsCurlyBraceOpen);
  503. N:=TJSObjectLiteral(CreateElement(TJSObjectLiteral));
  504. Result:=N;
  505. try
  506. While (CurrentToken<>tjsCurlyBraceClose) do
  507. begin
  508. While CurrentToken=tjsComma do
  509. GetNextToken;
  510. If (CurrentToken in [tjsIdentifier,jstoken.tjsString,tjsnumber]) then
  511. begin
  512. E:=N.Elements.AddElement;
  513. E.Name:=CurrenttokenString;
  514. GetNextToken;
  515. end
  516. else
  517. Error(SErrObjectElement,[CurrentTokenString]);
  518. Consume(tjsColon);
  519. E.Expr:=ParseAssignmentExpression;
  520. While CurrentToken=tjsComma do
  521. GetNextToken;
  522. { If Not (CurrentToken in [tjsComma,tjsCurlyBraceClose]) then
  523. Error(SErrObjectEnd,[CurrentTokenString])}
  524. end;
  525. Consume(tjsCurlyBraceClose);
  526. except
  527. FreeAndNil(Result);
  528. Raise;
  529. end;
  530. end;
  531. function TJSParser.ParseNumericLiteral: TJSElement;
  532. Var
  533. L : TJSLiteral;
  534. D : Double;
  535. I : Integer;
  536. begin
  537. {$ifdef debugparser} Writeln('Parsing numerical literal');{$endif debugparser}
  538. Result:=Nil;
  539. try
  540. Val(CurrentTokenString,D,I);
  541. If (I>0) then
  542. Error(SErrInvalidnumber,[CurrentTokenString]);
  543. L:=TJSLiteral(CreateElement(TJSLiteral));
  544. GetNextToken;
  545. L.Value.AsNumber:=D;
  546. Result:=L;
  547. except
  548. FreeAndNil(Result);
  549. Raise;
  550. end;
  551. end;
  552. function TJSParser.ParseStringLiteral: TJSElement;
  553. Var
  554. L : TJSLiteral;
  555. begin
  556. {$ifdef debugparser} Writeln('Parsing string literal');{$endif debugparser}
  557. Result:=Nil;
  558. try
  559. L:=TJSLiteral(CreateElement(TJSLiteral));
  560. L.Value.AsString:=CurrentTokenString;
  561. GetNextToken;
  562. Result:=L;
  563. except
  564. FreeAndNil(Result);
  565. Raise;
  566. end;
  567. end;
  568. function TJSParser.ParseRegularExpressionLiteral: TJSElement;
  569. Var
  570. S,pa,fl : String;
  571. P : integer;
  572. R : TJSRegularExpressionLiteral;
  573. begin
  574. Result:=Nil;
  575. If (CurrentToken=tjsRegex) then
  576. begin
  577. S:=CurrentTokenString;
  578. P:=Length(S);
  579. While (P>=1) and (S[P]<>'/') do
  580. Dec(P);
  581. If (P<=1) then
  582. Error(SErrInvalidRegularExpression,[CurrentTokenString]);
  583. pa:=Copy(S,2,P-1);
  584. fl:=Copy(S,P,Length(S)-P+1);
  585. R:=TJSRegularExpressionLiteral(CreateElement(TJSRegularExpressionLiteral));
  586. Result:=R;
  587. R.Pattern.AsString:=Pa;
  588. R.PatternFlags.AsString:=Fl;
  589. R.Argv[0]:=R.Pattern;
  590. R.Argv[1]:=R.PatternFlags;
  591. end;
  592. try
  593. Consume(tjsRegEx);
  594. except
  595. FreeAndNil(Result);
  596. Raise;
  597. end;
  598. end;
  599. function TJSParser.ParseLiteral: TJSElement;
  600. Var
  601. L : TJSLiteral;
  602. begin
  603. {$ifdef debugparser}Writeln('Parsing literal: ',GetEnumName(TypeInfo(TJSToken),Ord(CurrentToken)), ' As string: ',CurrentTokenString);{$endif debugparser}
  604. Result:=Nil;
  605. Case CurrentToken of
  606. tjsNull : begin
  607. L:=TJSLiteral(CreateElement(TJSLiteral));
  608. Result:=L;
  609. L.Value.IsNull:=True;
  610. GetNextToken;
  611. end;
  612. tjsTrue,
  613. tjsFalse: begin
  614. L:=TJSLiteral(CreateElement(TJSLiteral));
  615. Result:=L;
  616. L.Value.AsBoolean:=(CurrentToken=tjsTrue);
  617. GetNextToken;
  618. end;
  619. tjsNumber : Result:=ParseNumericLiteral;
  620. jstoken.tjsString : Result:=ParseStringLiteral;
  621. tjsDiv,
  622. tjsDivEq : Result:=ParseRegularExpressionLiteral
  623. else
  624. Error(SErrLiteralExpected,[CurrentTokenString]);
  625. end;
  626. end;
  627. function TJSParser.ParsePrimaryExpression: TJSElement;
  628. Var
  629. R : TJSPrimaryExpressionIdent;
  630. begin
  631. {$ifdef debugparser} Writeln('ParsePrimaryExpression');{$endif debugparser}
  632. Result:=Nil;
  633. try
  634. Case CurrentToken of
  635. tjsThis :
  636. begin
  637. Result:=TJSPrimaryExpressionThis(CreateElement(TJSPrimaryExpressionThis));
  638. GetNextToken;
  639. end;
  640. tjsidentifier:
  641. begin
  642. R:=TJSPrimaryExpressionIdent(CreateElement(TJSPrimaryExpressionIdent));
  643. Result:=R;
  644. R.Name:=CurrentTokenString;
  645. GetNextToken;
  646. end;
  647. tjsSquaredBraceOpen: Result:=ParseArrayLiteral;
  648. tjsCurlyBraceOpen: Result:=ParseObjectLiteral;
  649. tjsBraceOpen:
  650. begin
  651. Consume(tjsBraceOpen);
  652. Result:=ParseExpression;
  653. Consume(tjsBraceClose);
  654. end;
  655. else
  656. Result:=ParseLiteral;
  657. end; // Case;
  658. except
  659. FreeAndNil(Result);
  660. Raise;
  661. end;
  662. {$ifdef debugparser} Writeln('Exit ParsePrimaryExpression');{$endif debugparser}
  663. end;
  664. function TJSParser.ParseMemberExpression: TJSElement;
  665. Var
  666. M : TJSDotMemberExpression;
  667. N : TJSNewMemberExpression;
  668. B : TJSBracketMemberExpression;
  669. Done : Boolean;
  670. begin
  671. {$ifdef debugparser} Writeln('ParseMemberExpression');{$endif debugparser}
  672. Case CurrentToken of
  673. tjsFunction : Result:=ParseFunctionExpression();
  674. tjsNew : begin
  675. GetNextToken;
  676. N:=TJSNewMemberExpression(CreateElement(TJSNewMemberExpression));
  677. try
  678. Result:=N;
  679. N.MExpr:=ParseMemberExpression();
  680. if (CurrentToken=tjsBraceOpen) then
  681. N.Args:=ParseArguments;
  682. except
  683. FreeAndNil(N);
  684. Raise;
  685. end;
  686. end;
  687. else
  688. Result:=ParsePrimaryExpression()
  689. end;
  690. try
  691. Done:=False;
  692. Repeat
  693. Case CurrentToken of
  694. tjsDot :
  695. begin
  696. M:=TJSDotMemberExpression(CreateElement(TJSDotMemberExpression));
  697. M.MExpr:=Result;
  698. Result:=M;
  699. GetNextToken;
  700. If (CurrentToken=tjsIdentifier) then
  701. M.Name:=CurrentTokenString;
  702. Consume(tjsIdentifier);
  703. end;
  704. tjsSquaredBraceOpen:
  705. begin
  706. B:=TJSBracketMemberExpression(CreateElement(TJSBracketMemberExpression));
  707. B.MExpr:=Result;
  708. Result:=B;
  709. GetNextToken;
  710. B.Name:=ParseExpression();
  711. Consume(tjsSquaredBraceClose);
  712. end;
  713. else
  714. Done:=True;
  715. isLHS:=True;
  716. end;
  717. Until Done;
  718. except
  719. FreeAndNil(Result);
  720. Raise;
  721. end;
  722. {$ifdef debugparser} Writeln('Exit ParseMemberExpression');{$endif debugparser}
  723. end;
  724. function TJSParser.ParseArguments: TJSarguments;
  725. Var
  726. E : TJSArrayLiteralElement;
  727. begin
  728. Consume(tjsBraceOpen);
  729. Result:=TJSArguments(CreateElement(TJSArguments));
  730. try
  731. While (CurrentToken<>tjsBraceClose) do
  732. begin
  733. E:=Result.Elements.AddElement;
  734. E.Expr:=ParseAssignmentExpression;
  735. If (CurrentToken<>tjsBraceClose) then
  736. If CurrentToken=tjsComma then
  737. GetNextToken
  738. else
  739. Error(SErrArgumentsExpected,[CurrentTokenString]);
  740. end;
  741. Consume(tjsBraceClose);
  742. except
  743. FreeAndNil(Result);
  744. Raise;
  745. end;
  746. end;
  747. function TJSParser.ParseLeftHandSideExpression: TJSElement;
  748. Var
  749. M : TJSDotMemberExpression;
  750. B : TJSBracketMemberExpression;
  751. C : TJSCallExpression;
  752. Done : Boolean;
  753. begin
  754. {$ifdef debugparser} Writeln('ParseLeftHandSideExpression');{$endif debugparser}
  755. Case CurrentToken of
  756. tjsFunction : Result:=ParseFunctionExpression;
  757. tjsNew : Result:=ParseMemberExpression;
  758. else
  759. Result:=ParsePrimaryExpression
  760. end;
  761. try
  762. Done:=False;
  763. Repeat
  764. Case CurrentToken of
  765. tjsDot :
  766. begin
  767. M:=TJSDotMemberExpression(CreateElement(TJSDotMemberExpression));
  768. M.MExpr:=Result;
  769. Result:=M;
  770. GetNextToken;
  771. If (CurrentToken=tjsIdentifier) then
  772. M.Name:=CurrentTokenString;
  773. Consume(tjsIdentifier);
  774. end;
  775. tjsSquaredBraceOpen:
  776. begin
  777. B:=TJSBracketMemberExpression(CreateElement(TJSBracketMemberExpression));
  778. B.MExpr:=Result;
  779. Result:=B;
  780. GetNextToken;
  781. B.Name:=ParseExpression;
  782. Consume(tjsSquaredBraceClose);
  783. end;
  784. tjsBraceOpen:
  785. begin
  786. C:=TJSCallExpression(CreateElement(TJSCallExpression));
  787. C.Expr:=Result;
  788. Result:=C;
  789. C.Args:=ParseArguments;
  790. end;
  791. else
  792. {$ifdef debugparser}Writeln('Leaving LHS');{$endif debugparser}
  793. Done:=True;
  794. isLHS:=True;
  795. end;
  796. Until Done;
  797. except
  798. FreeAndNil(Result);
  799. Raise;
  800. end;
  801. {$ifdef debugparser} Writeln('Exit ParseLeftHandSideExpression');{$endif debugparser}
  802. end;
  803. function TJSParser.ParsePostFixExpression: TJSElement;
  804. Var
  805. R : TJSUnaryExpression;
  806. begin
  807. {$ifdef debugparser} Writeln('ParsePostfixExpression');{$endif debugparser}
  808. Result:=ParseLeftHandSideExpression;
  809. Try
  810. If (Not IsEndOfLine) and (CurrentToken in [tjsPlusPlus,tjsMinusMinus]) then
  811. begin
  812. If (CurrentToken=tjsPlusPLus) then
  813. R:=TJSUnaryExpression(CreateElement(TJSUnaryPostPlusPlusExpression))
  814. else
  815. R:=TJSUnaryExpression(CreateElement(TJSUnaryPostMinusMinusExpression));
  816. R.A:=Result;
  817. Result:=R;
  818. GetNextToken;
  819. isLHS:=False;
  820. end;
  821. except
  822. freeAndNil(Result);
  823. Raise;
  824. end;
  825. {$ifdef debugparser} Writeln('Exit ParsePostfixExpression');{$endif debugparser}
  826. end;
  827. function TJSParser.ParseUnaryExpression: TJSElement;
  828. Var
  829. C : TJSElementClass;
  830. R : TJSUnaryExpression;
  831. begin
  832. {$ifdef debugparser} Writeln('ParseUnaryExpression');{$endif debugparser}
  833. C:=Nil;
  834. Result:=Nil;
  835. try
  836. Case CurrentToken of
  837. tjsDelete : C:=TJSUnaryDeleteExpression;
  838. tjsVoid : C:=TJSUnaryVoidExpression;
  839. tjsTypeOf : C:=TJSUnaryTypeOfExpression;
  840. tjsPlusPlus : C:=TJSUnaryPrePlusPlusExpression;
  841. tjsMinusMinus : C:=TJSUnaryPreMinusMinusExpression;
  842. tjsPlus : C:=TJSUnaryPlusExpression;
  843. tjsMinus : C:=TJSUnaryMinusExpression;
  844. tjsInv : C:=TJSUnaryInvExpression;
  845. tjsNot : C:=TJSUnaryNotExpression;
  846. else
  847. Result:=ParsePostFixExpression;
  848. end;
  849. If (Result=Nil) then
  850. begin
  851. {$ifdef debugparser} Writeln('Found Unary Expression',GetEnumName(TypeInfo(TJSToken),Ord(CurrentToken)), ' As string: ',CurrentTokenString);{$endif debugparser}
  852. R:=TJSUnaryExpression(CreateElement(C));
  853. Result:=R;
  854. GetNextToken;
  855. R.A:=ParseUnaryExpression();
  856. isLHS:=False;
  857. end;
  858. except
  859. FreeAndNil(Result);
  860. Raise;
  861. end;
  862. {$ifdef debugparser} Writeln('Exit ParseUnaryExpression');{$endif debugparser}
  863. end;
  864. function TJSParser.ParseMultiplicativeExpression: TJSElement;
  865. Var
  866. C : TJSElementClass;
  867. R : TJSMultiplicativeExpression;
  868. begin
  869. {$ifdef debugparser} Writeln('ParseMultiplicativeExpression');{$endif debugparser}
  870. Result:=ParseUnaryExpression;
  871. try
  872. While (CurrentToken in [tjsMul,tjsDiv,tjsMod]) do
  873. begin
  874. if CurrentToken=tjsMul then
  875. C:=TJSMultiplicativeExpressionMul
  876. else if CurrentToken=tjsDiv then
  877. C:=TJSMultiplicativeExpressionDiv
  878. else
  879. C:=TJSMultiplicativeExpressionMod;
  880. R:=TJSMultiplicativeExpression(CreateElement(C));
  881. GetNextToken;
  882. R.A:=Result;
  883. Result:=R;
  884. R.B:=ParseUnaryExpression;
  885. isLHS:=False;
  886. end;
  887. except
  888. FreeAndNil(Result);
  889. Raise;
  890. end;
  891. {$ifdef debugparser} Writeln('Exit ParseMultiplicativeExpression');{$endif debugparser}
  892. end;
  893. function TJSParser.ParseAdditiveExpression: TJSElement;
  894. Var
  895. C : TJSElementClass;
  896. R : TJSAdditiveExpression;
  897. begin
  898. {$ifdef debugparser} Writeln('ParseAdditiveExpression');{$endif debugparser}
  899. Result:=ParseMultiplicativeExpression;
  900. try
  901. While (CurrentToken in [tjsPlus,tjsMinus]) do
  902. begin
  903. if CurrentToken=tjsPlus then
  904. C:=TJSAdditiveExpressionPlus
  905. else
  906. C:=TJSAdditiveExpressionMinus;
  907. R:=TJSAdditiveExpression(CreateElement(C));
  908. GetNextToken;
  909. R.A:=Result;
  910. Result:=R;
  911. R.B:=ParseMultiplicativeExpression;
  912. isLHS:=False;
  913. end;
  914. except
  915. FreeAndNil(Result);
  916. Raise;
  917. end;
  918. {$ifdef debugparser} Writeln('Exit ParseAdditiveExpression');{$endif debugparser}
  919. end;
  920. function TJSParser.ParseShiftExpression: TJSElement;
  921. Var
  922. C : TJSElementClass;
  923. R : TJSShiftExpression;
  924. begin
  925. {$ifdef debugparser} Writeln('ParseShiftExpression');{$endif debugparser}
  926. Result:=ParseAdditiveExpression;
  927. try
  928. While (CurrentToken in [tjsLshift,tjsRshift,tjsURShift]) do
  929. begin
  930. Case CurrentToken of
  931. tjsLshift : C:=TJSLShiftExpression;
  932. tjsRshift : C:=TJSRShiftExpression;
  933. tjsURshift : C:=TJSURShiftExpression;
  934. end;
  935. R:=TJSShiftExpression(CreateElement(C));
  936. R.A:=Result;
  937. Result:=R;
  938. GetNextToken;
  939. R.B:=ParseAdditiveExpression;
  940. IsLHS:=False;
  941. end;
  942. except
  943. FreeAndNil(Result);
  944. Raise;
  945. end;
  946. {$ifdef debugparser} Writeln('Exit ParseShiftExpression');{$endif debugparser}
  947. end;
  948. function TJSParser.ParseRelationalExpression: TJSElement;
  949. Var
  950. S : Set of TJSToken;
  951. C : TJSElementClass;
  952. R : TJSRelationalExpression;
  953. begin
  954. {$ifdef debugparser} Writeln('ParseRelationalExpression');{$endif debugparser}
  955. Result:=ParseShiftExpression;
  956. try
  957. S:=[tjsLT,tjsGT,tjsLE,tjsGE,tjsInstanceOf];
  958. If Not Noin then
  959. Include(S,tjsIn);
  960. While (CurrentToken in S) do
  961. begin
  962. Case CurrentToken of
  963. tjsLT : C:=TJSRelationalExpressionLT;
  964. tjsGT : C:=TJSRelationalExpressionGT;
  965. tjsLE : C:=TJSRelationalExpressionLE;
  966. tjsGE : C:=TJSRelationalExpressionGE;
  967. tjsInstanceOf :C:=TJSRelationalExpressionInstanceOf;
  968. tjsIn : C:=TJSRelationalExpressionIn;
  969. end;
  970. R:=TJSRelationalExpression(CreateElement(C));
  971. R.A:=Result;
  972. Result:=R;
  973. GetNextToken;
  974. R.B:=ParseRelationalExpression();
  975. IsLHS:=False;
  976. end;
  977. except
  978. FreeAndNil(Result);
  979. Raise;
  980. end;
  981. {$ifdef debugparser} Writeln('Exit ParseRelationalExpression');{$endif debugparser}
  982. end;
  983. function TJSParser.ParseEqualityExpression: TJSElement;
  984. Var
  985. C : TJSElementClass;
  986. E : TJSEqualityExpression;
  987. begin
  988. {$ifdef debugparser} Writeln('ParseEqualityExpression');{$endif debugparser}
  989. Result:=ParseRelationalExpression;
  990. try
  991. While (CurrentToken in [tjsEq,tjsNE,tjsSEQ,tjsSNE]) do
  992. begin
  993. Case CurrentToken of
  994. tjsEq : C:=TJSEqualityExpressionEQ;
  995. tjsNE : C:=TJSEqualityExpressionNE;
  996. tjsSEQ : C:=TJSEqualityExpressionSEQ;
  997. tjsSNE : C:=TJSEqualityExpressionSNE;
  998. end;
  999. GetNextToken;
  1000. E:=TJSEqualityExpression(CreateElement(C));
  1001. Result:=E;
  1002. E.A:=Result;
  1003. E.B:=ParseEqualityExpression();
  1004. E:=Nil;
  1005. IsLHS:=False;
  1006. end;
  1007. except
  1008. FreeAndNil(Result);
  1009. Raise;
  1010. end;
  1011. {$ifdef debugparser} Writeln('Exit ParseEqualityExpression');{$endif debugparser}
  1012. end;
  1013. function TJSParser.ParseBitwiseAndExpression: TJSElement;
  1014. Var
  1015. L : TJSBitwiseAndExpression;
  1016. begin
  1017. {$ifdef debugparser} Writeln('ParseBitwiseAndExpression');{$endif debugparser}
  1018. Result:=ParseEqualityExpression;
  1019. try
  1020. If (CurrentToken<>tjsAnd) then
  1021. exit;
  1022. GetNextToken;
  1023. L:=TJSBitwiseAndExpression(CreateElement(TJSBitwiseAndExpression));
  1024. L.A:=Result;
  1025. Result:=L;
  1026. L.B:=ParseBitwiseAndExpression();
  1027. IsLHS:=False;
  1028. except
  1029. FreeAndNil(Result);
  1030. Raise;
  1031. end;
  1032. {$ifdef debugparser} Writeln('Exit ParseBitwiseAndExpression');{$endif debugparser}
  1033. end;
  1034. function TJSParser.ParseBitwiseXORExpression: TJSElement;
  1035. Var
  1036. L : TJSBitwiseXOrExpression;
  1037. begin
  1038. {$ifdef debugparser} Writeln('ParseBitwiseXorExpression');{$endif debugparser}
  1039. Result:=ParseBitwiseAndExpression;
  1040. try
  1041. If (CurrentToken<>tjsXOr) then
  1042. exit;
  1043. GetNextToken;
  1044. L:=TJSBitwiseXOrExpression(CreateElement(TJSBitwiseXOrExpression));
  1045. L.A:=Result;
  1046. Result:=L;
  1047. L.B:=ParseBitwiseXORExpression();
  1048. IsLHS:=False;
  1049. except
  1050. FreeAndNil(Result);
  1051. Raise;
  1052. end;
  1053. {$ifdef debugparser} Writeln('Exit ParseBitwiseXorExpression');{$endif debugparser}
  1054. end;
  1055. function TJSParser.ParseBitwiseORExpression: TJSElement;
  1056. Var
  1057. L : TJSBitwiseOrExpression;
  1058. begin
  1059. {$ifdef debugparser} Writeln('ParseBitWiseOrExpression');{$endif debugparser}
  1060. Result:=ParseBitwiseXORExpression;
  1061. try
  1062. If (CurrentToken<>tjsOr) then
  1063. exit;
  1064. GetNextToken;
  1065. L:=TJSBitwiseOrExpression(CreateElement(TJSBitwiseOrExpression));
  1066. L.A:=Result;
  1067. Result:=L;
  1068. L.B:=ParseBitwiseORExpression();
  1069. IsLHS:=False;
  1070. except
  1071. FreeAndNil(Result);
  1072. Raise;
  1073. end;
  1074. {$ifdef debugparser} Writeln('Exit ParseBitWiseOrExpression');{$endif debugparser}
  1075. end;
  1076. function TJSParser.ParseLogicalAndExpression: TJSElement;
  1077. Var
  1078. L : TJSLogicalAndExpression;
  1079. begin
  1080. {$ifdef debugparser} Writeln('ParseLogicalAndExpression');{$endif debugparser}
  1081. Result:=ParseBitwiseORExpression;
  1082. try
  1083. If (CurrentToken<>tjsAndAnd) then
  1084. exit;
  1085. GetNextToken;
  1086. L:=TJSLogicalAndExpression(CreateElement(TJSLogicalAndExpression));
  1087. L.A:=Result;
  1088. Result:=L;
  1089. L.B:=ParseLogicalAndExpression();
  1090. IsLHS:=False;
  1091. except
  1092. FreeAndNil(Result);
  1093. Raise;
  1094. end;
  1095. {$ifdef debugparser} Writeln('Exit ParseLogicalAndExpression');{$endif debugparser}
  1096. end;
  1097. function TJSParser.ParseLogicalORExpression: TJSElement;
  1098. Var
  1099. L : TJSLogicalOrExpression;
  1100. begin
  1101. {$ifdef debugparser} Writeln('ParseLogicalOrExpression');{$endif debugparser}
  1102. Result:=ParseLogicalAndExpression;
  1103. try
  1104. If (CurrentToken<>tjsOROR) then
  1105. exit;
  1106. GetNextToken;
  1107. L:=TJSLogicalOrExpression(CreateElement(TJSLogicalOrExpression));
  1108. L.A:=Result;
  1109. Result:=L;
  1110. L.B:=ParseLogicalOrExpression();
  1111. IsLHS:=False;
  1112. except
  1113. FreeAndNil(Result);
  1114. Raise;
  1115. end;
  1116. {$ifdef debugparser} Writeln('Exit ParseLogicalOrExpression');{$endif debugparser}
  1117. end;
  1118. function TJSParser.ParseConditionalExpression: TJSElement;
  1119. Var
  1120. N : TJSConditionalExpression;
  1121. L : TJSElement;
  1122. begin
  1123. {$ifdef debugparser} Writeln('ParseConditionalExpression');{$endif debugparser}
  1124. Result:=Nil;
  1125. Result:=ParseLogicalORExpression;
  1126. try
  1127. If (CurrentToken=tjsConditional) then
  1128. begin
  1129. {$ifdef debugparser} Writeln('ParseConditionalExpression : Detected conditional ');{$endif debugparser}
  1130. GetNextToken;
  1131. L:=Result;
  1132. N:=TJSConditionalExpression(CreateElement(TJSConditionalExpression));
  1133. Result:=N;
  1134. N.A:=L;
  1135. L:=Nil;
  1136. N.B:=ParseAssignmentExpression;
  1137. Consume(tjsColon);
  1138. N.C:=ParseAssignmentExpression;
  1139. IsLHS:=False;
  1140. end;
  1141. except
  1142. FreeandNil(Result);
  1143. end;
  1144. {$ifdef debugparser} Writeln('Exit ParseConditionalExpression');{$endif debugparser}
  1145. end;
  1146. function TJSParser.ParseAssignmentExpression: TJSElement;
  1147. Var
  1148. N : TJSElement;
  1149. C : TJSElementClass;
  1150. A : TJSAssignStatement;
  1151. begin
  1152. {$ifdef debugparser} Writeln('ParseAssignmentExpression');{$endif debugparser}
  1153. Result:=Nil;
  1154. N:=ParseConditionalExpression;
  1155. If not isLHS then
  1156. Result:=N
  1157. else
  1158. Case CurrentToken of
  1159. tjsAssign : C:=TJSSimpleAssignStatement;
  1160. tjsMulEq : C:=TJSMulEqAssignStatement;
  1161. tjsDivEq : C:=TJSDivEqAssignStatement;
  1162. tjsModEq : C:=TJSModEqAssignStatement;
  1163. tjsPlusEq : C:=TJSAddEqAssignStatement;
  1164. tjsMinusEq : C:=TJSSubEqAssignStatement;
  1165. tjsLShiftEq : C:=TJSLShiftEqAssignStatement;
  1166. tjsRShiftEq : C:=TJSRShiftEqAssignStatement;
  1167. tjsURShiftEq : C:=TJSURShiftEqAssignStatement;
  1168. tjsANDEq : C:=TJSANDEqAssignStatement;
  1169. tjsOREq : C:=TJSOREqAssignStatement;
  1170. tjsXOREq : C:=TJSXOREqAssignStatement;
  1171. else
  1172. // writeln('Strange token',GetEnumName(TypeInfo(TJSToken),Ord(CurrentToken)), ' As string: ',CurrentTokenString);
  1173. Result:=N
  1174. end;
  1175. If Result<>Nil then
  1176. begin
  1177. {$ifdef debugparser} Writeln('Exit ParseAssignmentExpression - no assignment');{$endif debugparser}
  1178. Exit;
  1179. end;
  1180. A:=TJSAssignStatement(CreateElement(C));
  1181. try
  1182. Result:=A;
  1183. A.Lhs:=N;
  1184. GetNextToken;
  1185. {$ifdef debugparser} Writeln('ParseAssignmentExpression - level 2');{$endif debugparser}
  1186. N:=ParseAssignmentExpression();
  1187. {$ifdef debugparser} Writeln('Exit ParseAssignmentExpression - level 2');{$endif debugparser}
  1188. A.Expr:=N;
  1189. IsLhs:=False;
  1190. except
  1191. FreeAndNil(Result);
  1192. Raise;
  1193. end;
  1194. {$ifdef debugparser} Writeln('Exit ParseAssignmentExpression');{$endif debugparser}
  1195. end;
  1196. function TJSParser.ParseVariableDeclaration: TJSElement;
  1197. Var
  1198. V : TJSVarDeclaration;
  1199. begin
  1200. {$ifdef debugparser} Writeln('ParseVariableDeclaration');{$endif debugparser}
  1201. V:=TJSVarDeclaration(CreateElement(TJSVarDeclaration));;
  1202. try
  1203. V.Name:=CurrenttokenString;
  1204. Consume(tjsIdentifier);
  1205. if (CurrentToken=tjsAssign) then
  1206. begin
  1207. GetNextToken;
  1208. V.Init:=ParseAssignmentExpression;
  1209. end;
  1210. Result:=V;
  1211. FCurrentVars.AddNode.Node:=Result;
  1212. except
  1213. FreeAndNil(V);
  1214. Raise;
  1215. end;
  1216. {$ifdef debugparser} Writeln('Exit ParseVariableDeclaration');{$endif debugparser}
  1217. end;
  1218. function TJSParser.ParseVariableDeclarationList: TJSElement;
  1219. Var
  1220. E,N : TJSElement;
  1221. L : TJSVariableDeclarationList;
  1222. begin
  1223. {$ifdef debugparser} Writeln('ParseVariableDeclarationList entry');{$endif debugparser}
  1224. E:=ParseVariableDeclaration;
  1225. If (CurrentToken<>tjsComma) then
  1226. Result:=E
  1227. else
  1228. begin
  1229. L:=TJSVariableDeclarationList(CreateElement(TJSVariableDeclarationList));
  1230. Result:=L;
  1231. try
  1232. Consume(tjsComma);
  1233. N:=ParseVariableDeclarationList();
  1234. L.A:=E;
  1235. L.B:=N;
  1236. except
  1237. FreeAndNil(Result);
  1238. Raise;
  1239. end;
  1240. end;
  1241. {$ifdef debugparser} Writeln('ParseVariableDeclarationList exit');{$endif debugparser}
  1242. end;
  1243. function TJSParser.ParseVariableStatement : TJSElement;
  1244. Var
  1245. V : TJSVariableStatement;
  1246. begin
  1247. {$ifdef debugparser} Writeln('ParseVariableStatement entry');{$endif debugparser}
  1248. Result:=Nil;
  1249. Consume(tjsVar);
  1250. Result:=ParseVariableDeclarationList;
  1251. try
  1252. Consume(tjsSemicolon,true);
  1253. V:=TJSVariableStatement(CreateElement(TJSVariableStatement));
  1254. V.A:=Result;
  1255. Result:=V;
  1256. except
  1257. FreeAndNil(Result);
  1258. Raise;
  1259. end;
  1260. {$ifdef debugparser} Writeln('ParseVariableStatement exit');{$endif debugparser}
  1261. end;
  1262. function TJSParser.ParseEmptyStatement : TJSElement;
  1263. begin
  1264. Consume(tjsSemiColon,true);
  1265. Result:=CreateElement(TJSEmptyStatement);
  1266. end;
  1267. function TJSParser.ParseIfStatement : TJSElement;
  1268. Var
  1269. C,BTrue,BFalse : TJSElement;
  1270. I : TJSIFstatement;
  1271. begin
  1272. C:=Nil;
  1273. BTrue:=Nil;
  1274. BFalse:=Nil;
  1275. try
  1276. Consume(tjsIF);
  1277. Consume(tjsBraceOpen);
  1278. C:=ParseExpression;
  1279. Consume(tjsBraceClose);
  1280. BTrue:=ParseStatement;
  1281. If (CurrentToken=tjsElse) then
  1282. begin
  1283. Consume(tjsElse);
  1284. BFalse:=ParseStatement;
  1285. end;
  1286. I:=TJSIfStatement(CreateElement(TJSIfStatement));
  1287. I.Cond:=C;
  1288. I.BTrue:=Btrue;
  1289. I.BFalse:=BFalse;
  1290. Result:=I;
  1291. except
  1292. FreeAndNil(C);
  1293. FreeAndNil(BTrue);
  1294. FreeAndNil(BFalse);
  1295. Raise;
  1296. end;
  1297. end;
  1298. function TJSParser.ParseIterationStatement : TJSElement;
  1299. Var
  1300. F : TJSForStatement;
  1301. FI : TJSForInStatement;
  1302. W : TJSWhileStatement;
  1303. N : TJSElement;
  1304. begin
  1305. Result:=Nil;
  1306. N:=Nil;
  1307. CurrentLabelSet.Continuable:=True;
  1308. EnterLabel(SEmptyLabel);
  1309. try
  1310. try
  1311. Case CurrentToken of
  1312. tjsDo :
  1313. begin
  1314. GetNextToken;
  1315. W:=TJSDoWhileStatement(CreateElement(TJSDoWhileStatement));
  1316. Result:=W;
  1317. W.Body:=ParseStatement;
  1318. Consume(tjsWhile);
  1319. Consume(tjsBraceOpen);
  1320. W.Cond:=ParseExpression;
  1321. Consume(tjsBraceClose);
  1322. Consume(tjsSemicolon,True);
  1323. end;
  1324. tjsWhile :
  1325. begin
  1326. GetNextToken;
  1327. W:=TJSWhileStatement(CreateElement(TJSWhileStatement));
  1328. Result:=W;
  1329. Consume(tjsBraceOpen);
  1330. W.Cond:=ParseExpression;
  1331. Consume(tjsBraceClose);
  1332. W.Body:=ParseStatement;
  1333. Result:=W;
  1334. end;
  1335. else
  1336. // For ?
  1337. GetNextToken;
  1338. Consume(tjsBraceopen);
  1339. If (CurrentToken=tjsVar) then
  1340. begin
  1341. GetNextToken;
  1342. N:=ParseVariableDeclarationList;
  1343. // for (var in
  1344. If (CurrentToken=tjsIn) and (N is tJSVarDeclaration) then
  1345. begin
  1346. Fi:=TJSForInStatement(CreateElement(TJSForInStatement));
  1347. Result:=Fi;
  1348. Fi.LHS:=N;
  1349. GetNextToken;
  1350. Fi.List:=ParseExpression;
  1351. Consume(tjsBraceClose);
  1352. Fi.Body:=ParseStatement;
  1353. end;
  1354. // for (var ;
  1355. If (CurrentToken<>tjsSemicolon) then
  1356. If (N is tJSVarDeclaration) then
  1357. Error(SErrSemicolonOrInExpected,[CurrentTokenString])
  1358. else
  1359. Error(SErrSemicolonExpected,[CurrentTokenString]);
  1360. GetNextToken;
  1361. F:=TJSForStatement(CreateElement(TJSForStatement));
  1362. Result:=F;
  1363. If (CurrentToken<>tjsSemicolon) then
  1364. F.Cond:=ParseExpression;
  1365. Consume(tjsSemicolon);
  1366. If (CurrentToken<>tjsBraceClose) then
  1367. F.Incr:=ParseExpression;
  1368. Consume(tjsBraceClose);
  1369. F.Body:=ParseStatement;
  1370. end
  1371. else
  1372. begin
  1373. If (CurrentToken<>tjsSemicolon) then
  1374. begin
  1375. N:=ParseExpression;
  1376. If (CurrentToken=tjsIn) then
  1377. begin
  1378. Fi:=TJSForInStatement(CreateElement(TJSForInStatement));
  1379. Result:=Fi;
  1380. Fi.LHS:=N;
  1381. N:=Nil; // prevent freeing a second time in case of an exception.
  1382. GetNextToken;
  1383. Fi.List:=ParseExpression;
  1384. Consume(tjsBraceClose);
  1385. Fi.Body:=ParseStatement;
  1386. Exit; // We must jump out here
  1387. end
  1388. end
  1389. else
  1390. N:=Nil;
  1391. // For ( Init; Cond; incr)
  1392. F:=TJSForStatement(CreateElement(TJSForStatement));
  1393. Result:=F;
  1394. F.Init:=N;
  1395. N:=Nil; // prevent freeing a second time in case of an exception.
  1396. Consume(tjsSemicolon);
  1397. if (CurrentToken<>tjsSemicolon) then
  1398. F.Cond:=ParseExpression;
  1399. Consume(tjsSemicolon);
  1400. If (CurrentToken<>tjsBraceClose) Then
  1401. F.Incr:=ParseExpression;
  1402. Consume(tjsBraceClose);
  1403. F.Body:=ParseStatement;
  1404. end;
  1405. end; // Case
  1406. Finally
  1407. LeaveLabel;
  1408. FreeCurrentLabelSet;
  1409. end;
  1410. except
  1411. FreeAndNil(N);
  1412. FreeAndNil(Result);
  1413. Raise;
  1414. end;
  1415. end;
  1416. function TJSParser.ParseContinueStatement : TJSElement;
  1417. Var
  1418. L : TJSLabel;
  1419. C : TJSContinueStatement;
  1420. begin
  1421. C:=TJSContinueStatement(CreateElement(TJSContinueStatement));
  1422. try
  1423. Result:=C;
  1424. Consume(tjsContinue);
  1425. If (CurrentToken=tjsSemicolon) then
  1426. L:=LookupLabel(SEmptyLabel,tjsContinue)
  1427. else
  1428. begin
  1429. if (CurrentToken=tjsIdentifier) then
  1430. L:=LookupLabel(CurrentTokenString,tjsContinue);
  1431. Consume(tjsIdentifier);
  1432. end;
  1433. Consume(tjsSemicolon,True);
  1434. C.Target:=L.Labelset.Target;
  1435. C.TargetName:=L.Name;
  1436. except
  1437. FreeAndNil(C);
  1438. Raise;
  1439. end;
  1440. end;
  1441. function TJSParser.ParseBreakStatement : TJSElement;
  1442. Var
  1443. L : TJSLabel;
  1444. B : TJSBreakStatement;
  1445. begin
  1446. B:=TJSBreakStatement(CreateElement(TJSBreakStatement));
  1447. try
  1448. Result:=B;
  1449. Consume(tjsBreak);
  1450. If (CurrentToken=tjsSemicolon) then
  1451. L:=LookupLabel(SEmptyLabel,tjsBreak)
  1452. else
  1453. begin
  1454. if (CurrentToken=tjsIdentifier) then
  1455. L:=LookupLabel(CurrentTokenString,tjsBreak);
  1456. Consume(tjsIdentifier);
  1457. end;
  1458. Consume(tjsSemicolon,True);
  1459. B.Target:=L.Labelset.Target;
  1460. B.TargetName:=L.Name;
  1461. except
  1462. FreeAndNil(B);
  1463. Raise;
  1464. end;
  1465. end;
  1466. function TJSParser.ParseReturnStatement : TJSElement;
  1467. Var
  1468. R : TJSreturnStatement;
  1469. begin
  1470. R:=TJSReturnStatement(CreateElement(TJSReturnStatement));
  1471. try
  1472. Result:=R;
  1473. Consume(tjsReturn);
  1474. If (FunctionDepth=0) then
  1475. Error(SErrReturnNotInFunction);
  1476. If Not (CurrentToken in [tjsSemicolon,tjsCurlyBraceClose]) then
  1477. R.Expr:=ParseExpression;
  1478. Consume(tjsSemicolon,True);
  1479. except
  1480. FreeAndNil(R);
  1481. Raise;
  1482. end;
  1483. end;
  1484. function TJSParser.ParseWithStatement : TJSElement;
  1485. Var
  1486. W : TJSWithStatement;
  1487. begin
  1488. W:=TJSWithStatement(CreateElement(TJSWithStatement));
  1489. try
  1490. Consume(tjsWith);
  1491. Consume(tjsBraceOpen);
  1492. W.A:=ParseExpression;
  1493. Consume(tjsBraceClose);
  1494. W.B:=ParseStatement;
  1495. except
  1496. FreeAndNil(W);
  1497. Raise;
  1498. end;
  1499. Result:=W;
  1500. end;
  1501. function TJSParser.ParseSwitchStatement : TJSElement;
  1502. Var
  1503. N : TJSSwitchStatement;
  1504. Ca : TJSCaseElement;
  1505. begin
  1506. N:=TJSSwitchStatement(CreateElement(TJSSwitchStatement));
  1507. try
  1508. N.Target:=CurrentLabelset.Target;
  1509. EnterLabel(SEmptyLabel);
  1510. try
  1511. Consume(tjsSwitch);
  1512. Consume(tjsBraceOpen);
  1513. N.Cond:=ParseExpression;
  1514. Consume(tjsBraceClose);
  1515. Consume(tjsCurlyBraceOpen);
  1516. While (CurrentToken<>tjsCurlyBraceClose) do
  1517. begin
  1518. If (CurrentToken=tjsCase) then
  1519. begin
  1520. GetNextToken;
  1521. Ca:=N.Cases.AddCase;
  1522. Ca.Expr:=ParseExpression;
  1523. end
  1524. else if (CurrentToken=tjsDefault) then
  1525. begin
  1526. If (N.TheDefault<>Nil) then
  1527. Error(SerrDuplicateSwitchDefault);
  1528. Ca:=N.Cases.AddCase;
  1529. N.TheDefault:=Ca;
  1530. GetNextToken;
  1531. end
  1532. else
  1533. Error(SerrCaseEndExpected);
  1534. Consume(tjsColon);
  1535. If Not (CurrentToken in [tjsCurlyBraceClose,tjsCase,tjsDefault]) then
  1536. Ca.Body:=ParseStatementList;
  1537. end;
  1538. Consume(tjsCurlyBraceClose);
  1539. finally
  1540. LeaveLabel;
  1541. FreeCurrentLabelSet;
  1542. end;
  1543. Result:=N;
  1544. except
  1545. FreeAndNil(N);
  1546. Raise;
  1547. end;
  1548. end;
  1549. function TJSParser.ParseThrowStatement : TJSElement;
  1550. Var
  1551. TS : TJSThrowStatement;
  1552. begin
  1553. TS:=TJSThrowStatement(CreateElement(TJSThrowStatement));
  1554. try
  1555. Result:=TS;
  1556. Consume(tjsThrow);
  1557. If IsEndOfLine then
  1558. Error(SErrNewlineAfterThrow);
  1559. TS.A:=ParseExpression;
  1560. Consume(tjsSemicolon,true);
  1561. except
  1562. FreeAndNil(TS);
  1563. Raise;
  1564. end;
  1565. end;
  1566. function TJSParser.ParseTryStatement : TJSElement;
  1567. Var
  1568. BO,BC,BF : TJSElement;
  1569. Id : jstree.TJSString;
  1570. T : TJSTryStatement;
  1571. begin
  1572. BO:=Nil;
  1573. BC:=Nil;
  1574. BF:=Nil;
  1575. Result:=Nil;
  1576. Consume(tjsTry);
  1577. try
  1578. Bo:=ParseBlock;
  1579. if (CurrentToken=tjscatch) then
  1580. begin
  1581. Consume(tjsCatch);
  1582. Consume(tjsBraceOpen);
  1583. if (CurrentToken=tjsIdentifier) then
  1584. id:=CurrentTokenString;
  1585. Consume(tjsIdentifier);
  1586. Consume(tjsBraceClose);
  1587. BC:=ParseBlock;
  1588. end;
  1589. if (CurrentToken=tjsFinally) then
  1590. begin
  1591. consume(tjsFinally);
  1592. BF:=ParseBlock;
  1593. end;
  1594. If (BF=Nil) and (BC=Nil) then
  1595. Error(SErrCatchFinallyExpected);
  1596. If Assigned(BC) AND Assigned(BF) then
  1597. T:=TJSTryStatement(CreateElement(TJSTryCatchFinallyStatement))
  1598. else if Assigned(BC) then
  1599. T:=TJSTryStatement(CreateElement(TJSTryCatchStatement))
  1600. else
  1601. T:=TJSTryStatement(CreateElement(TJSTryFinallyStatement));
  1602. Result:=T;
  1603. T.Block:=Bo;
  1604. Bo:=Nil;
  1605. T.BCatch:=BC;
  1606. BC:=Nil;
  1607. T.BFinally:=BF;
  1608. BF:=Nil;
  1609. T.Ident:=ID;
  1610. except
  1611. FreeAndNil(Bo);
  1612. FreeAndNil(BC);
  1613. FreeAndNil(BF);
  1614. FreeAndNil(Result);
  1615. Raise;
  1616. end;
  1617. end;
  1618. function TJSParser.ParseFunctionExpression : TJSFunctionDeclarationStatement;
  1619. Var
  1620. Oni,olhs: Boolean;
  1621. F : TJSFunctionDeclarationStatement;
  1622. N : String;
  1623. Args : TStrings;
  1624. begin
  1625. {$ifdef debugparser} Writeln('>>> ParseFunctionExpression');{$endif}
  1626. oni:=NoIn;
  1627. olhs:=IsLHS;
  1628. F:=Nil;
  1629. Args:=Nil;
  1630. try
  1631. NoIn:=False;
  1632. IsLHS:=False;
  1633. F:=TJSFunctionDeclarationStatement(CreateElement(TJSFunctionDeclarationStatement));
  1634. try
  1635. Consume(tjsFunction);
  1636. if (CurrentToken=tjsIdentifier) then
  1637. begin
  1638. n:=CurrentTokenstring;
  1639. GetNextToken;
  1640. end
  1641. else
  1642. n:='';
  1643. if n='' then ; // what to do with that?
  1644. Consume(tjsBraceOpen);
  1645. F.AFunction:= TJSFuncDef.Create;
  1646. Args:=ParseFormalParameterList;
  1647. try
  1648. If Assigned(Args) then
  1649. F.AFunction.Params.Assign(Args);
  1650. finally
  1651. FreeAndNil(Args);
  1652. end;
  1653. Consume(tjsBraceClose);
  1654. Consume(tjsCurlyBraceOpen);
  1655. Inc(FFunctionDepth);
  1656. try
  1657. F.AFunction.Body:=ParseFunctionBody;
  1658. Finally
  1659. Dec(FFunctionDepth);
  1660. end;
  1661. Consume(tjsCurlyBraceClose);
  1662. Result:=F;
  1663. except
  1664. FreeAndNil(F);
  1665. Raise;
  1666. end;
  1667. finally
  1668. NoIn := oni;
  1669. IsLHS := olhs;
  1670. end;
  1671. {$ifdef debugparser} Writeln('<<< ParseFunctionExpression');{$endif}
  1672. end;
  1673. function TJSParser.ParseFunctionStatement : TJSElement;
  1674. Var
  1675. F : TJSFunctionDeclarationStatement;
  1676. I : TJSPrimaryExpressionIdent;
  1677. A : TJSAssignStatement;
  1678. E : TJSExpressionStatement;
  1679. begin
  1680. {$ifdef debugparser} Writeln('>>> ParseFunctionStatement');{$endif}
  1681. F:=Nil;
  1682. I:=Nil;
  1683. A:=Nil;
  1684. try
  1685. F:=ParseFunctionExpression;
  1686. I:=TJSPrimaryExpressionIdent(CreateElement(TJSPrimaryExpressionIdent));
  1687. I.Name:=F.AFunction.Name;
  1688. A:=TJSAssignStatement(CreateElement(TJSAssignStatement));
  1689. A.LHS:=I;
  1690. I:=Nil;
  1691. A.Expr:=F;
  1692. F:=Nil;
  1693. E:=TJSExpressionStatement(CreateElement(TJSExpressionStatement));
  1694. E.A:=A;
  1695. A:=Nil;
  1696. Result:=E;
  1697. except
  1698. FreeAndNil(F);
  1699. FreeAndNil(I);
  1700. FreeAndNil(A);
  1701. Raise;
  1702. end;
  1703. {$ifdef debugparser} Writeln('<<< ParseFunctionStatement');{$endif}
  1704. end;
  1705. function TJSParser.ParseLabeledStatement : TJSElement;
  1706. Var
  1707. OL : TJSLabelSet;
  1708. LS : TJSLabeledStatement;
  1709. begin
  1710. LS:=TJSLabeledStatement(CreateElement(TJSLabeledStatement));
  1711. try
  1712. Result:=LS;
  1713. OL:=FCurrentLabelSet;
  1714. try
  1715. FCurrentLabelSet:=Nil;
  1716. LS.target:=CurrentLabelSet.Target;
  1717. Repeat
  1718. LS.TheLabel:=EnterLabel(CurrentTokenString);
  1719. Consume(tjsIdentifier);
  1720. Consume(tjsColon);
  1721. Until (CurrentToken<>tjsIdentifier) or (PeekNextToken<>tjsColon);
  1722. Case CurrentToken of
  1723. tjsDo,tjsWhile,tjsFor : LS.A:=ParseIterationStatement;
  1724. tjsswitch : LS.A:=ParseSwitchStatement;
  1725. else
  1726. LS.A:=ParseStatement;
  1727. end;
  1728. finally
  1729. FreeCurrentLabelSet;
  1730. FCurrentLabelSet:=Ol;
  1731. end;
  1732. except
  1733. FreeAndNil(LS);
  1734. Raise;
  1735. end;
  1736. end;
  1737. procedure TJSParser.FreeCurrentLabelSet;
  1738. Var
  1739. L : TJSLabelSet;
  1740. begin
  1741. While Assigned(FCurrentLabelSet) do
  1742. begin
  1743. L:=FCurrentLabelset.Next;
  1744. FCurrentLabelSet.Free;
  1745. FCurrentLabelSet:=L;
  1746. end;
  1747. end;
  1748. function TJSParser.ParseExpressionStatement : TJSElement;
  1749. Var
  1750. E : TJSElement;
  1751. R : TJSExpressionStatement;
  1752. begin
  1753. {$ifdef debugparser} Writeln('ParseExpressionStatement');{$endif debugparser}
  1754. E:=ParseExpression;
  1755. Consume(tjsSemicolon,True);
  1756. R:=TJSExpressionStatement(CreateElement(TJSExpressionStatement));
  1757. R.A:=E;
  1758. Result:=R;
  1759. {$ifdef debugparser} Writeln('Exit ParseExpressionStatement');{$endif debugparser}
  1760. end;
  1761. function TJSParser.ParseExpression : TJSElement;
  1762. Var
  1763. C : TJSCommaExpression;
  1764. begin
  1765. {$ifdef debugparser} Writeln('ParseExpression');{$endif debugparser}
  1766. Result:=ParseAssignmentExpression;
  1767. try
  1768. If (CurrentToken=tjsComma) then
  1769. begin
  1770. C:=TJSCommaExpression(CreateElement(TJSCommaExpression));
  1771. C.A:=Result;
  1772. Result:=C;
  1773. GetNextToken;
  1774. C.B:=ParseExpression();
  1775. end;
  1776. except
  1777. FreeAndNil(Result);
  1778. Raise;
  1779. end;
  1780. {$ifdef debugparser} Writeln('Exit ParseExpression');{$endif debugparser}
  1781. end;
  1782. function TJSParser.ParseStatement : TJSElement;
  1783. begin
  1784. {$ifdef debugparser} Writeln('>>> Parsestatement');{$endif}
  1785. Result:=Nil;
  1786. Case CurrentToken of
  1787. tjsCurlyBraceOpen :
  1788. Result:=ParseBlock;
  1789. tjsVar:
  1790. Result:=ParseVariableStatement;
  1791. tjsSemicolon:
  1792. Result:=ParseEmptyStatement;
  1793. tjsIf:
  1794. Result:=ParseIfStatement;
  1795. tjsDo,tjsWhile,tjsFor:
  1796. Result:=ParseIterationStatement;
  1797. tjsContinue:
  1798. Result:=ParseContinueStatement;
  1799. tjsBreak:
  1800. Result:=ParseBreakStatement;
  1801. tjsReturn:
  1802. Result:=ParseReturnStatement;
  1803. tjsWith:
  1804. Result:=ParseWithStatement;
  1805. tjsSwitch:
  1806. Result:=ParseSwitchStatement;
  1807. tjsThrow:
  1808. Result:=ParseThrowStatement;
  1809. tjsTry:
  1810. Result:=ParseTryStatement;
  1811. tjsFunction:
  1812. begin
  1813. If (PeekNextToken<>tjsBraceOpen) then
  1814. Result:=ParseFunctionStatement;
  1815. Error(SErrFunctionNotAllowedHere);
  1816. end;
  1817. tjsIdentifier:
  1818. If (PeekNextToken=tjsColon) then
  1819. Result:=ParseLabeledStatement
  1820. else
  1821. Result:=ParseExpressionStatement;
  1822. else
  1823. Result:=ParseExpressionStatement;
  1824. end;
  1825. {$ifdef debugparser} If Assigned(Result) then Writeln('<<< Parsestatement ',Result.ClassName) else Writeln('<<< Parsestatement (null');{$endif}
  1826. end;
  1827. function TJSParser.ParseSourceElements : TJSSourceElements;
  1828. Const
  1829. StatementTokens = [tjsNULL, tjsTRUE, tjsFALSE,
  1830. tjsTHIS, tjsIdentifier,jstoken.tjsSTRING,tjsNUMBER,
  1831. tjsBraceOpen,tjsCurlyBraceOpen,tjsSquaredBraceOpen,
  1832. tjsNew,tjsDelete,tjsVoid,tjsTypeOf,
  1833. tjsPlusPlus,tjsMinusMinus,
  1834. tjsPlus,tjsMinus,tjsNot,tjsNE,tjsSNE,tjsSemicolon,
  1835. tjsVAR,tjsIF,tjsDO,tjsWHILE,tjsFOR,jstoken.tjsCONTINUE,jstoken.tjsBREAK,jstoken.tjsReturn,
  1836. tjsWith,jstoken.tjsSWITCH,tjsThrow,TjsTry,tjsDIV,tjsDIVEQ];
  1837. Var
  1838. F : TJSFunctionDeclarationStatement;
  1839. E : TJSElement;
  1840. Done : Boolean;
  1841. VS : TJSElementNodes;
  1842. begin
  1843. {$ifdef debugparser} Writeln('>>> Entering source elements');{$endif}
  1844. Result:=TJSSourceElements(CreateElement(TJSSourceElements));
  1845. try
  1846. Done:=False;
  1847. VS:=FCurrentVars;
  1848. Try
  1849. FCurrentVars:=Result.Vars;
  1850. Repeat
  1851. {$ifdef debugparser} Writeln('Sourceelements start:',GetEnumName(TypeInfo(TJSToken),Ord(CurrentToken)), ' As string: ',CurrentTokenString);{$endif debugparser}
  1852. If (CurrentToken=jstoken.tjsFunction) then
  1853. begin
  1854. If (PeekNextToken<>tjsBraceOpen) then
  1855. begin
  1856. F:=Self.ParseFunctionDeclaration;
  1857. Result.Functions.AddNode.Node:=F;
  1858. end
  1859. else
  1860. begin
  1861. {$ifdef debugparser} Writeln('Function expression detected');{$endif}
  1862. E:=Self.ParseStatement;
  1863. Result.Statements.AddNode.Node:=E;
  1864. end;
  1865. end
  1866. else if CurrentToken in StatementTokens then
  1867. begin
  1868. E:=Self.ParseStatement;
  1869. Result.Statements.AddNode.Node:=E;
  1870. end
  1871. else
  1872. Done:=True;
  1873. {$ifdef debugparser} Writeln('Sourceelements Done : ',Done);{$endif}
  1874. Until Done;
  1875. Finally
  1876. FCurrentVars:=VS;
  1877. end;
  1878. except
  1879. FreeAndNil(Result);
  1880. Raise;
  1881. end;
  1882. {$ifdef debugparser} Writeln('<<< Exiting source elements');{$endif}
  1883. end;
  1884. function TJSParser.ParseFunctionBody : TJSFunctionBody;
  1885. Var
  1886. E : TJSElement;
  1887. begin
  1888. {$ifdef debugparser} Writeln('>>> Entering FunctionBody');{$endif}
  1889. Result:=TJSFunctionBody(CreateElement(TJSFunctionBody));
  1890. try
  1891. E:=Self.ParseSourceElements;
  1892. Result.A:=E;
  1893. except
  1894. FreeAndNil(Result);
  1895. Raise;
  1896. end;
  1897. {$ifdef debugparser} Writeln('<<< Exiting FunctionBody');{$endif}
  1898. end;
  1899. Function TJSParser.ParseProgram: TJSFunctionDeclarationStatement;
  1900. Var
  1901. B : TJSElement;
  1902. begin
  1903. {$ifdef debugparser} Writeln('>>> Entering FunctionDeclarationStatement');{$endif}
  1904. B:=Parse;
  1905. If Not (B is TJSFunctionBody) then
  1906. Error('Parse did not result in functionbody');
  1907. Result:=TJSFunctionDeclarationStatement(CreateElement(TJSFunctionDeclarationStatement));
  1908. Result.AFunction:=TJSFuncDef.Create;
  1909. Result.AFunction.Body:=TJSFunctionBody(B);
  1910. {$ifdef debugparser} Writeln('<<< Exiting FunctionDeclarationStatement');{$endif}
  1911. end;
  1912. Function TJSParser.Parse: TJSElement;
  1913. Var
  1914. Body : TJSElement;
  1915. begin
  1916. {$ifdef debugparser} Writeln('>>> Parse');{$endif}
  1917. Result:=Nil;
  1918. CheckParser;
  1919. GetNextToken;
  1920. Body:=ParseFunctionBody;
  1921. Result:=Body;
  1922. try
  1923. if (CurrentToken<>tjsEOF) then
  1924. begin
  1925. if (CurrentToken=tjsCurlyBraceClose) then
  1926. Error(SErrUnmatchedCurlyBrace)
  1927. else if (CurrentToken=tjsBraceClose) then
  1928. Error(SerrUnmatchedBrace)
  1929. else if (CurrentToken=tjsSquaredBraceClose) then
  1930. Error(SerrUnmatchedSquareBrace);
  1931. Error(SErrUnexpectedToken,[CurrentTokenString]);
  1932. end;
  1933. If (Body is TJSFunctionBody) then
  1934. TJSFunctionBody(Body).isProgram:=True;
  1935. except
  1936. FreeAndNil(Result);
  1937. Raise;
  1938. end;
  1939. {$ifdef debugparser} Writeln('<<< Parse');{$endif}
  1940. end;
  1941. end.