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