jsparser.pp 56 KB

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