github.com/dop251/goja@v0.0.0-20240220182346-e401ed450204/parser/statement.go (about) 1 package parser 2 3 import ( 4 "encoding/base64" 5 "fmt" 6 "os" 7 "strings" 8 9 "github.com/dop251/goja/ast" 10 "github.com/dop251/goja/file" 11 "github.com/dop251/goja/token" 12 "github.com/go-sourcemap/sourcemap" 13 ) 14 15 func (self *_parser) parseBlockStatement() *ast.BlockStatement { 16 node := &ast.BlockStatement{} 17 node.LeftBrace = self.expect(token.LEFT_BRACE) 18 node.List = self.parseStatementList() 19 node.RightBrace = self.expect(token.RIGHT_BRACE) 20 21 return node 22 } 23 24 func (self *_parser) parseEmptyStatement() ast.Statement { 25 idx := self.expect(token.SEMICOLON) 26 return &ast.EmptyStatement{Semicolon: idx} 27 } 28 29 func (self *_parser) parseStatementList() (list []ast.Statement) { 30 for self.token != token.RIGHT_BRACE && self.token != token.EOF { 31 self.scope.allowLet = true 32 list = append(list, self.parseStatement()) 33 } 34 35 return 36 } 37 38 func (self *_parser) parseStatement() ast.Statement { 39 40 if self.token == token.EOF { 41 self.errorUnexpectedToken(self.token) 42 return &ast.BadStatement{From: self.idx, To: self.idx + 1} 43 } 44 45 switch self.token { 46 case token.SEMICOLON: 47 return self.parseEmptyStatement() 48 case token.LEFT_BRACE: 49 return self.parseBlockStatement() 50 case token.IF: 51 return self.parseIfStatement() 52 case token.DO: 53 return self.parseDoWhileStatement() 54 case token.WHILE: 55 return self.parseWhileStatement() 56 case token.FOR: 57 return self.parseForOrForInStatement() 58 case token.BREAK: 59 return self.parseBreakStatement() 60 case token.CONTINUE: 61 return self.parseContinueStatement() 62 case token.DEBUGGER: 63 return self.parseDebuggerStatement() 64 case token.WITH: 65 return self.parseWithStatement() 66 case token.VAR: 67 return self.parseVariableStatement() 68 case token.LET: 69 tok := self.peek() 70 if tok == token.LEFT_BRACKET || self.scope.allowLet && (token.IsId(tok) || tok == token.LEFT_BRACE) { 71 return self.parseLexicalDeclaration(self.token) 72 } 73 self.insertSemicolon = true 74 case token.CONST: 75 return self.parseLexicalDeclaration(self.token) 76 case token.ASYNC: 77 if f := self.parseMaybeAsyncFunction(true); f != nil { 78 return &ast.FunctionDeclaration{ 79 Function: f, 80 } 81 } 82 case token.FUNCTION: 83 return &ast.FunctionDeclaration{ 84 Function: self.parseFunction(true, false, self.idx), 85 } 86 case token.CLASS: 87 return &ast.ClassDeclaration{ 88 Class: self.parseClass(true), 89 } 90 case token.SWITCH: 91 return self.parseSwitchStatement() 92 case token.RETURN: 93 return self.parseReturnStatement() 94 case token.THROW: 95 return self.parseThrowStatement() 96 case token.TRY: 97 return self.parseTryStatement() 98 } 99 100 expression := self.parseExpression() 101 102 if identifier, isIdentifier := expression.(*ast.Identifier); isIdentifier && self.token == token.COLON { 103 // LabelledStatement 104 colon := self.idx 105 self.next() // : 106 label := identifier.Name 107 for _, value := range self.scope.labels { 108 if label == value { 109 self.error(identifier.Idx0(), "Label '%s' already exists", label) 110 } 111 } 112 self.scope.labels = append(self.scope.labels, label) // Push the label 113 self.scope.allowLet = false 114 statement := self.parseStatement() 115 self.scope.labels = self.scope.labels[:len(self.scope.labels)-1] // Pop the label 116 return &ast.LabelledStatement{ 117 Label: identifier, 118 Colon: colon, 119 Statement: statement, 120 } 121 } 122 123 self.optionalSemicolon() 124 125 return &ast.ExpressionStatement{ 126 Expression: expression, 127 } 128 } 129 130 func (self *_parser) parseTryStatement() ast.Statement { 131 132 node := &ast.TryStatement{ 133 Try: self.expect(token.TRY), 134 Body: self.parseBlockStatement(), 135 } 136 137 if self.token == token.CATCH { 138 catch := self.idx 139 self.next() 140 var parameter ast.BindingTarget 141 if self.token == token.LEFT_PARENTHESIS { 142 self.next() 143 parameter = self.parseBindingTarget() 144 self.expect(token.RIGHT_PARENTHESIS) 145 } 146 node.Catch = &ast.CatchStatement{ 147 Catch: catch, 148 Parameter: parameter, 149 Body: self.parseBlockStatement(), 150 } 151 } 152 153 if self.token == token.FINALLY { 154 self.next() 155 node.Finally = self.parseBlockStatement() 156 } 157 158 if node.Catch == nil && node.Finally == nil { 159 self.error(node.Try, "Missing catch or finally after try") 160 return &ast.BadStatement{From: node.Try, To: node.Body.Idx1()} 161 } 162 163 return node 164 } 165 166 func (self *_parser) parseFunctionParameterList() *ast.ParameterList { 167 opening := self.expect(token.LEFT_PARENTHESIS) 168 var list []*ast.Binding 169 var rest ast.Expression 170 if !self.scope.inFuncParams { 171 self.scope.inFuncParams = true 172 defer func() { 173 self.scope.inFuncParams = false 174 }() 175 } 176 for self.token != token.RIGHT_PARENTHESIS && self.token != token.EOF { 177 if self.token == token.ELLIPSIS { 178 self.next() 179 rest = self.reinterpretAsDestructBindingTarget(self.parseAssignmentExpression()) 180 break 181 } 182 self.parseVariableDeclaration(&list) 183 if self.token != token.RIGHT_PARENTHESIS { 184 self.expect(token.COMMA) 185 } 186 } 187 closing := self.expect(token.RIGHT_PARENTHESIS) 188 189 return &ast.ParameterList{ 190 Opening: opening, 191 List: list, 192 Rest: rest, 193 Closing: closing, 194 } 195 } 196 197 func (self *_parser) parseMaybeAsyncFunction(declaration bool) *ast.FunctionLiteral { 198 if self.peek() == token.FUNCTION { 199 idx := self.idx 200 self.next() 201 return self.parseFunction(declaration, true, idx) 202 } 203 return nil 204 } 205 206 func (self *_parser) parseFunction(declaration, async bool, start file.Idx) *ast.FunctionLiteral { 207 208 node := &ast.FunctionLiteral{ 209 Function: start, 210 Async: async, 211 } 212 self.expect(token.FUNCTION) 213 214 if self.token == token.MULTIPLY { 215 node.Generator = true 216 self.next() 217 } 218 219 if !declaration { 220 if async != self.scope.allowAwait { 221 self.scope.allowAwait = async 222 defer func() { 223 self.scope.allowAwait = !async 224 }() 225 } 226 if node.Generator != self.scope.allowYield { 227 self.scope.allowYield = node.Generator 228 defer func() { 229 self.scope.allowYield = !node.Generator 230 }() 231 } 232 } 233 234 self.tokenToBindingId() 235 var name *ast.Identifier 236 if self.token == token.IDENTIFIER { 237 name = self.parseIdentifier() 238 } else if declaration { 239 // Use expect error handling 240 self.expect(token.IDENTIFIER) 241 } 242 node.Name = name 243 244 if declaration { 245 if async != self.scope.allowAwait { 246 self.scope.allowAwait = async 247 defer func() { 248 self.scope.allowAwait = !async 249 }() 250 } 251 if node.Generator != self.scope.allowYield { 252 self.scope.allowYield = node.Generator 253 defer func() { 254 self.scope.allowYield = !node.Generator 255 }() 256 } 257 } 258 259 node.ParameterList = self.parseFunctionParameterList() 260 node.Body, node.DeclarationList = self.parseFunctionBlock(async, async, self.scope.allowYield) 261 node.Source = self.slice(node.Idx0(), node.Idx1()) 262 263 return node 264 } 265 266 func (self *_parser) parseFunctionBlock(async, allowAwait, allowYield bool) (body *ast.BlockStatement, declarationList []*ast.VariableDeclaration) { 267 self.openScope() 268 self.scope.inFunction = true 269 self.scope.inAsync = async 270 self.scope.allowAwait = allowAwait 271 self.scope.allowYield = allowYield 272 defer self.closeScope() 273 body = self.parseBlockStatement() 274 declarationList = self.scope.declarationList 275 return 276 } 277 278 func (self *_parser) parseArrowFunctionBody(async bool) (ast.ConciseBody, []*ast.VariableDeclaration) { 279 if self.token == token.LEFT_BRACE { 280 return self.parseFunctionBlock(async, async, false) 281 } 282 if async != self.scope.inAsync || async != self.scope.allowAwait { 283 inAsync := self.scope.inAsync 284 allowAwait := self.scope.allowAwait 285 self.scope.inAsync = async 286 self.scope.allowAwait = async 287 allowYield := self.scope.allowYield 288 self.scope.allowYield = false 289 defer func() { 290 self.scope.inAsync = inAsync 291 self.scope.allowAwait = allowAwait 292 self.scope.allowYield = allowYield 293 }() 294 } 295 296 return &ast.ExpressionBody{ 297 Expression: self.parseAssignmentExpression(), 298 }, nil 299 } 300 301 func (self *_parser) parseClass(declaration bool) *ast.ClassLiteral { 302 if !self.scope.allowLet && self.token == token.CLASS { 303 self.errorUnexpectedToken(token.CLASS) 304 } 305 306 node := &ast.ClassLiteral{ 307 Class: self.expect(token.CLASS), 308 } 309 310 self.tokenToBindingId() 311 var name *ast.Identifier 312 if self.token == token.IDENTIFIER { 313 name = self.parseIdentifier() 314 } else if declaration { 315 // Use expect error handling 316 self.expect(token.IDENTIFIER) 317 } 318 319 node.Name = name 320 321 if self.token != token.LEFT_BRACE { 322 self.expect(token.EXTENDS) 323 node.SuperClass = self.parseLeftHandSideExpressionAllowCall() 324 } 325 326 self.expect(token.LEFT_BRACE) 327 328 for self.token != token.RIGHT_BRACE && self.token != token.EOF { 329 if self.token == token.SEMICOLON { 330 self.next() 331 continue 332 } 333 start := self.idx 334 static := false 335 if self.token == token.STATIC { 336 switch self.peek() { 337 case token.ASSIGN, token.SEMICOLON, token.RIGHT_BRACE, token.LEFT_PARENTHESIS: 338 // treat as identifier 339 default: 340 self.next() 341 if self.token == token.LEFT_BRACE { 342 b := &ast.ClassStaticBlock{ 343 Static: start, 344 } 345 b.Block, b.DeclarationList = self.parseFunctionBlock(false, true, false) 346 b.Source = self.slice(b.Block.LeftBrace, b.Block.Idx1()) 347 node.Body = append(node.Body, b) 348 continue 349 } 350 static = true 351 } 352 } 353 354 var kind ast.PropertyKind 355 var async bool 356 methodBodyStart := self.idx 357 if self.literal == "get" || self.literal == "set" { 358 if tok := self.peek(); tok != token.SEMICOLON && tok != token.LEFT_PARENTHESIS { 359 if self.literal == "get" { 360 kind = ast.PropertyKindGet 361 } else { 362 kind = ast.PropertyKindSet 363 } 364 self.next() 365 } 366 } else if self.token == token.ASYNC { 367 if tok := self.peek(); tok != token.SEMICOLON && tok != token.LEFT_PARENTHESIS { 368 async = true 369 kind = ast.PropertyKindMethod 370 self.next() 371 } 372 } 373 generator := false 374 if self.token == token.MULTIPLY && (kind == "" || kind == ast.PropertyKindMethod) { 375 generator = true 376 kind = ast.PropertyKindMethod 377 self.next() 378 } 379 380 _, keyName, value, tkn := self.parseObjectPropertyKey() 381 if value == nil { 382 continue 383 } 384 computed := tkn == token.ILLEGAL 385 _, private := value.(*ast.PrivateIdentifier) 386 387 if static && !private && keyName == "prototype" { 388 self.error(value.Idx0(), "Classes may not have a static property named 'prototype'") 389 } 390 391 if kind == "" && self.token == token.LEFT_PARENTHESIS { 392 kind = ast.PropertyKindMethod 393 } 394 395 if kind != "" { 396 // method 397 if keyName == "constructor" && !computed { 398 if !static { 399 if kind != ast.PropertyKindMethod { 400 self.error(value.Idx0(), "Class constructor may not be an accessor") 401 } else if async { 402 self.error(value.Idx0(), "Class constructor may not be an async method") 403 } else if generator { 404 self.error(value.Idx0(), "Class constructor may not be a generator") 405 } 406 } else if private { 407 self.error(value.Idx0(), "Class constructor may not be a private method") 408 } 409 } 410 md := &ast.MethodDefinition{ 411 Idx: start, 412 Key: value, 413 Kind: kind, 414 Body: self.parseMethodDefinition(methodBodyStart, kind, generator, async), 415 Static: static, 416 Computed: computed, 417 } 418 node.Body = append(node.Body, md) 419 } else { 420 // field 421 isCtor := !computed && keyName == "constructor" 422 if !isCtor { 423 if name, ok := value.(*ast.PrivateIdentifier); ok { 424 isCtor = name.Name == "constructor" 425 } 426 } 427 if isCtor { 428 self.error(value.Idx0(), "Classes may not have a field named 'constructor'") 429 } 430 var initializer ast.Expression 431 if self.token == token.ASSIGN { 432 self.next() 433 initializer = self.parseExpression() 434 } 435 436 if !self.implicitSemicolon && self.token != token.SEMICOLON && self.token != token.RIGHT_BRACE { 437 self.errorUnexpectedToken(self.token) 438 break 439 } 440 node.Body = append(node.Body, &ast.FieldDefinition{ 441 Idx: start, 442 Key: value, 443 Initializer: initializer, 444 Static: static, 445 Computed: computed, 446 }) 447 } 448 } 449 450 node.RightBrace = self.expect(token.RIGHT_BRACE) 451 node.Source = self.slice(node.Class, node.RightBrace+1) 452 453 return node 454 } 455 456 func (self *_parser) parseDebuggerStatement() ast.Statement { 457 idx := self.expect(token.DEBUGGER) 458 459 node := &ast.DebuggerStatement{ 460 Debugger: idx, 461 } 462 463 self.semicolon() 464 465 return node 466 } 467 468 func (self *_parser) parseReturnStatement() ast.Statement { 469 idx := self.expect(token.RETURN) 470 471 if !self.scope.inFunction { 472 self.error(idx, "Illegal return statement") 473 self.nextStatement() 474 return &ast.BadStatement{From: idx, To: self.idx} 475 } 476 477 node := &ast.ReturnStatement{ 478 Return: idx, 479 } 480 481 if !self.implicitSemicolon && self.token != token.SEMICOLON && self.token != token.RIGHT_BRACE && self.token != token.EOF { 482 node.Argument = self.parseExpression() 483 } 484 485 self.semicolon() 486 487 return node 488 } 489 490 func (self *_parser) parseThrowStatement() ast.Statement { 491 idx := self.expect(token.THROW) 492 493 if self.implicitSemicolon { 494 if self.chr == -1 { // Hackish 495 self.error(idx, "Unexpected end of input") 496 } else { 497 self.error(idx, "Illegal newline after throw") 498 } 499 self.nextStatement() 500 return &ast.BadStatement{From: idx, To: self.idx} 501 } 502 503 node := &ast.ThrowStatement{ 504 Throw: idx, 505 Argument: self.parseExpression(), 506 } 507 508 self.semicolon() 509 510 return node 511 } 512 513 func (self *_parser) parseSwitchStatement() ast.Statement { 514 idx := self.expect(token.SWITCH) 515 self.expect(token.LEFT_PARENTHESIS) 516 node := &ast.SwitchStatement{ 517 Switch: idx, 518 Discriminant: self.parseExpression(), 519 Default: -1, 520 } 521 self.expect(token.RIGHT_PARENTHESIS) 522 523 self.expect(token.LEFT_BRACE) 524 525 inSwitch := self.scope.inSwitch 526 self.scope.inSwitch = true 527 defer func() { 528 self.scope.inSwitch = inSwitch 529 }() 530 531 for index := 0; self.token != token.EOF; index++ { 532 if self.token == token.RIGHT_BRACE { 533 node.RightBrace = self.idx 534 self.next() 535 break 536 } 537 538 clause := self.parseCaseStatement() 539 if clause.Test == nil { 540 if node.Default != -1 { 541 self.error(clause.Case, "Already saw a default in switch") 542 } 543 node.Default = index 544 } 545 node.Body = append(node.Body, clause) 546 } 547 548 return node 549 } 550 551 func (self *_parser) parseWithStatement() ast.Statement { 552 node := &ast.WithStatement{} 553 node.With = self.expect(token.WITH) 554 self.expect(token.LEFT_PARENTHESIS) 555 node.Object = self.parseExpression() 556 self.expect(token.RIGHT_PARENTHESIS) 557 self.scope.allowLet = false 558 node.Body = self.parseStatement() 559 560 return node 561 } 562 563 func (self *_parser) parseCaseStatement() *ast.CaseStatement { 564 565 node := &ast.CaseStatement{ 566 Case: self.idx, 567 } 568 if self.token == token.DEFAULT { 569 self.next() 570 } else { 571 self.expect(token.CASE) 572 node.Test = self.parseExpression() 573 } 574 self.expect(token.COLON) 575 576 for { 577 if self.token == token.EOF || 578 self.token == token.RIGHT_BRACE || 579 self.token == token.CASE || 580 self.token == token.DEFAULT { 581 break 582 } 583 self.scope.allowLet = true 584 node.Consequent = append(node.Consequent, self.parseStatement()) 585 586 } 587 588 return node 589 } 590 591 func (self *_parser) parseIterationStatement() ast.Statement { 592 inIteration := self.scope.inIteration 593 self.scope.inIteration = true 594 defer func() { 595 self.scope.inIteration = inIteration 596 }() 597 self.scope.allowLet = false 598 return self.parseStatement() 599 } 600 601 func (self *_parser) parseForIn(idx file.Idx, into ast.ForInto) *ast.ForInStatement { 602 603 // Already have consumed "<into> in" 604 605 source := self.parseExpression() 606 self.expect(token.RIGHT_PARENTHESIS) 607 608 return &ast.ForInStatement{ 609 For: idx, 610 Into: into, 611 Source: source, 612 Body: self.parseIterationStatement(), 613 } 614 } 615 616 func (self *_parser) parseForOf(idx file.Idx, into ast.ForInto) *ast.ForOfStatement { 617 618 // Already have consumed "<into> of" 619 620 source := self.parseAssignmentExpression() 621 self.expect(token.RIGHT_PARENTHESIS) 622 623 return &ast.ForOfStatement{ 624 For: idx, 625 Into: into, 626 Source: source, 627 Body: self.parseIterationStatement(), 628 } 629 } 630 631 func (self *_parser) parseFor(idx file.Idx, initializer ast.ForLoopInitializer) *ast.ForStatement { 632 633 // Already have consumed "<initializer> ;" 634 635 var test, update ast.Expression 636 637 if self.token != token.SEMICOLON { 638 test = self.parseExpression() 639 } 640 self.expect(token.SEMICOLON) 641 642 if self.token != token.RIGHT_PARENTHESIS { 643 update = self.parseExpression() 644 } 645 self.expect(token.RIGHT_PARENTHESIS) 646 647 return &ast.ForStatement{ 648 For: idx, 649 Initializer: initializer, 650 Test: test, 651 Update: update, 652 Body: self.parseIterationStatement(), 653 } 654 } 655 656 func (self *_parser) parseForOrForInStatement() ast.Statement { 657 idx := self.expect(token.FOR) 658 self.expect(token.LEFT_PARENTHESIS) 659 660 var initializer ast.ForLoopInitializer 661 662 forIn := false 663 forOf := false 664 var into ast.ForInto 665 if self.token != token.SEMICOLON { 666 667 allowIn := self.scope.allowIn 668 self.scope.allowIn = false 669 tok := self.token 670 if tok == token.LET { 671 switch self.peek() { 672 case token.IDENTIFIER, token.LEFT_BRACKET, token.LEFT_BRACE: 673 default: 674 tok = token.IDENTIFIER 675 } 676 } 677 if tok == token.VAR || tok == token.LET || tok == token.CONST { 678 idx := self.idx 679 self.next() 680 var list []*ast.Binding 681 if tok == token.VAR { 682 list = self.parseVarDeclarationList(idx) 683 } else { 684 list = self.parseVariableDeclarationList() 685 } 686 if len(list) == 1 { 687 if self.token == token.IN { 688 self.next() // in 689 forIn = true 690 } else if self.token == token.IDENTIFIER && self.literal == "of" { 691 self.next() 692 forOf = true 693 } 694 } 695 if forIn || forOf { 696 if list[0].Initializer != nil { 697 self.error(list[0].Initializer.Idx0(), "for-in loop variable declaration may not have an initializer") 698 } 699 if tok == token.VAR { 700 into = &ast.ForIntoVar{ 701 Binding: list[0], 702 } 703 } else { 704 into = &ast.ForDeclaration{ 705 Idx: idx, 706 IsConst: tok == token.CONST, 707 Target: list[0].Target, 708 } 709 } 710 } else { 711 self.ensurePatternInit(list) 712 if tok == token.VAR { 713 initializer = &ast.ForLoopInitializerVarDeclList{ 714 List: list, 715 } 716 } else { 717 initializer = &ast.ForLoopInitializerLexicalDecl{ 718 LexicalDeclaration: ast.LexicalDeclaration{ 719 Idx: idx, 720 Token: tok, 721 List: list, 722 }, 723 } 724 } 725 } 726 } else { 727 expr := self.parseExpression() 728 if self.token == token.IN { 729 self.next() 730 forIn = true 731 } else if self.token == token.IDENTIFIER && self.literal == "of" { 732 self.next() 733 forOf = true 734 } 735 if forIn || forOf { 736 switch e := expr.(type) { 737 case *ast.Identifier, *ast.DotExpression, *ast.PrivateDotExpression, *ast.BracketExpression, *ast.Binding: 738 // These are all acceptable 739 case *ast.ObjectLiteral: 740 expr = self.reinterpretAsObjectAssignmentPattern(e) 741 case *ast.ArrayLiteral: 742 expr = self.reinterpretAsArrayAssignmentPattern(e) 743 default: 744 self.error(idx, "Invalid left-hand side in for-in or for-of") 745 self.nextStatement() 746 return &ast.BadStatement{From: idx, To: self.idx} 747 } 748 into = &ast.ForIntoExpression{ 749 Expression: expr, 750 } 751 } else { 752 initializer = &ast.ForLoopInitializerExpression{ 753 Expression: expr, 754 } 755 } 756 } 757 self.scope.allowIn = allowIn 758 } 759 760 if forIn { 761 return self.parseForIn(idx, into) 762 } 763 if forOf { 764 return self.parseForOf(idx, into) 765 } 766 767 self.expect(token.SEMICOLON) 768 return self.parseFor(idx, initializer) 769 } 770 771 func (self *_parser) ensurePatternInit(list []*ast.Binding) { 772 for _, item := range list { 773 if _, ok := item.Target.(ast.Pattern); ok { 774 if item.Initializer == nil { 775 self.error(item.Idx1(), "Missing initializer in destructuring declaration") 776 break 777 } 778 } 779 } 780 } 781 782 func (self *_parser) parseVariableStatement() *ast.VariableStatement { 783 784 idx := self.expect(token.VAR) 785 786 list := self.parseVarDeclarationList(idx) 787 self.ensurePatternInit(list) 788 self.semicolon() 789 790 return &ast.VariableStatement{ 791 Var: idx, 792 List: list, 793 } 794 } 795 796 func (self *_parser) parseLexicalDeclaration(tok token.Token) *ast.LexicalDeclaration { 797 idx := self.expect(tok) 798 if !self.scope.allowLet { 799 self.error(idx, "Lexical declaration cannot appear in a single-statement context") 800 } 801 802 list := self.parseVariableDeclarationList() 803 self.ensurePatternInit(list) 804 self.semicolon() 805 806 return &ast.LexicalDeclaration{ 807 Idx: idx, 808 Token: tok, 809 List: list, 810 } 811 } 812 813 func (self *_parser) parseDoWhileStatement() ast.Statement { 814 inIteration := self.scope.inIteration 815 self.scope.inIteration = true 816 defer func() { 817 self.scope.inIteration = inIteration 818 }() 819 820 node := &ast.DoWhileStatement{} 821 node.Do = self.expect(token.DO) 822 if self.token == token.LEFT_BRACE { 823 node.Body = self.parseBlockStatement() 824 } else { 825 self.scope.allowLet = false 826 node.Body = self.parseStatement() 827 } 828 829 self.expect(token.WHILE) 830 self.expect(token.LEFT_PARENTHESIS) 831 node.Test = self.parseExpression() 832 node.RightParenthesis = self.expect(token.RIGHT_PARENTHESIS) 833 if self.token == token.SEMICOLON { 834 self.next() 835 } 836 837 return node 838 } 839 840 func (self *_parser) parseWhileStatement() ast.Statement { 841 idx := self.expect(token.WHILE) 842 self.expect(token.LEFT_PARENTHESIS) 843 node := &ast.WhileStatement{ 844 While: idx, 845 Test: self.parseExpression(), 846 } 847 self.expect(token.RIGHT_PARENTHESIS) 848 node.Body = self.parseIterationStatement() 849 850 return node 851 } 852 853 func (self *_parser) parseIfStatement() ast.Statement { 854 self.expect(token.IF) 855 self.expect(token.LEFT_PARENTHESIS) 856 node := &ast.IfStatement{ 857 Test: self.parseExpression(), 858 } 859 self.expect(token.RIGHT_PARENTHESIS) 860 861 if self.token == token.LEFT_BRACE { 862 node.Consequent = self.parseBlockStatement() 863 } else { 864 self.scope.allowLet = false 865 node.Consequent = self.parseStatement() 866 } 867 868 if self.token == token.ELSE { 869 self.next() 870 self.scope.allowLet = false 871 node.Alternate = self.parseStatement() 872 } 873 874 return node 875 } 876 877 func (self *_parser) parseSourceElements() (body []ast.Statement) { 878 for self.token != token.EOF { 879 self.scope.allowLet = true 880 body = append(body, self.parseStatement()) 881 } 882 883 return body 884 } 885 886 func (self *_parser) parseProgram() *ast.Program { 887 prg := &ast.Program{ 888 Body: self.parseSourceElements(), 889 DeclarationList: self.scope.declarationList, 890 File: self.file, 891 } 892 self.file.SetSourceMap(self.parseSourceMap()) 893 return prg 894 } 895 896 func extractSourceMapLine(str string) string { 897 for { 898 p := strings.LastIndexByte(str, '\n') 899 line := str[p+1:] 900 if line != "" && line != "})" { 901 if strings.HasPrefix(line, "//# sourceMappingURL=") { 902 return line 903 } 904 break 905 } 906 if p >= 0 { 907 str = str[:p] 908 } else { 909 break 910 } 911 } 912 return "" 913 } 914 915 func (self *_parser) parseSourceMap() *sourcemap.Consumer { 916 if self.opts.disableSourceMaps { 917 return nil 918 } 919 if smLine := extractSourceMapLine(self.str); smLine != "" { 920 urlIndex := strings.Index(smLine, "=") 921 urlStr := smLine[urlIndex+1:] 922 923 var data []byte 924 var err error 925 if strings.HasPrefix(urlStr, "data:application/json") { 926 b64Index := strings.Index(urlStr, ",") 927 b64 := urlStr[b64Index+1:] 928 data, err = base64.StdEncoding.DecodeString(b64) 929 } else { 930 if sourceURL := file.ResolveSourcemapURL(self.file.Name(), urlStr); sourceURL != nil { 931 if self.opts.sourceMapLoader != nil { 932 data, err = self.opts.sourceMapLoader(sourceURL.String()) 933 } else { 934 if sourceURL.Scheme == "" || sourceURL.Scheme == "file" { 935 data, err = os.ReadFile(sourceURL.Path) 936 } else { 937 err = fmt.Errorf("unsupported source map URL scheme: %s", sourceURL.Scheme) 938 } 939 } 940 } 941 } 942 943 if err != nil { 944 self.error(file.Idx(0), "Could not load source map: %v", err) 945 return nil 946 } 947 if data == nil { 948 return nil 949 } 950 951 if sm, err := sourcemap.Parse(self.file.Name(), data); err == nil { 952 return sm 953 } else { 954 self.error(file.Idx(0), "Could not parse source map: %v", err) 955 } 956 } 957 return nil 958 } 959 960 func (self *_parser) parseBreakStatement() ast.Statement { 961 idx := self.expect(token.BREAK) 962 semicolon := self.implicitSemicolon 963 if self.token == token.SEMICOLON { 964 semicolon = true 965 self.next() 966 } 967 968 if semicolon || self.token == token.RIGHT_BRACE { 969 self.implicitSemicolon = false 970 if !self.scope.inIteration && !self.scope.inSwitch { 971 goto illegal 972 } 973 return &ast.BranchStatement{ 974 Idx: idx, 975 Token: token.BREAK, 976 } 977 } 978 979 self.tokenToBindingId() 980 if self.token == token.IDENTIFIER { 981 identifier := self.parseIdentifier() 982 if !self.scope.hasLabel(identifier.Name) { 983 self.error(idx, "Undefined label '%s'", identifier.Name) 984 return &ast.BadStatement{From: idx, To: identifier.Idx1()} 985 } 986 self.semicolon() 987 return &ast.BranchStatement{ 988 Idx: idx, 989 Token: token.BREAK, 990 Label: identifier, 991 } 992 } 993 994 self.expect(token.IDENTIFIER) 995 996 illegal: 997 self.error(idx, "Illegal break statement") 998 self.nextStatement() 999 return &ast.BadStatement{From: idx, To: self.idx} 1000 } 1001 1002 func (self *_parser) parseContinueStatement() ast.Statement { 1003 idx := self.expect(token.CONTINUE) 1004 semicolon := self.implicitSemicolon 1005 if self.token == token.SEMICOLON { 1006 semicolon = true 1007 self.next() 1008 } 1009 1010 if semicolon || self.token == token.RIGHT_BRACE { 1011 self.implicitSemicolon = false 1012 if !self.scope.inIteration { 1013 goto illegal 1014 } 1015 return &ast.BranchStatement{ 1016 Idx: idx, 1017 Token: token.CONTINUE, 1018 } 1019 } 1020 1021 self.tokenToBindingId() 1022 if self.token == token.IDENTIFIER { 1023 identifier := self.parseIdentifier() 1024 if !self.scope.hasLabel(identifier.Name) { 1025 self.error(idx, "Undefined label '%s'", identifier.Name) 1026 return &ast.BadStatement{From: idx, To: identifier.Idx1()} 1027 } 1028 if !self.scope.inIteration { 1029 goto illegal 1030 } 1031 self.semicolon() 1032 return &ast.BranchStatement{ 1033 Idx: idx, 1034 Token: token.CONTINUE, 1035 Label: identifier, 1036 } 1037 } 1038 1039 self.expect(token.IDENTIFIER) 1040 1041 illegal: 1042 self.error(idx, "Illegal continue statement") 1043 self.nextStatement() 1044 return &ast.BadStatement{From: idx, To: self.idx} 1045 } 1046 1047 // Find the next statement after an error (recover) 1048 func (self *_parser) nextStatement() { 1049 for { 1050 switch self.token { 1051 case token.BREAK, token.CONTINUE, 1052 token.FOR, token.IF, token.RETURN, token.SWITCH, 1053 token.VAR, token.DO, token.TRY, token.WITH, 1054 token.WHILE, token.THROW, token.CATCH, token.FINALLY: 1055 // Return only if parser made some progress since last 1056 // sync or if it has not reached 10 next calls without 1057 // progress. Otherwise consume at least one token to 1058 // avoid an endless parser loop 1059 if self.idx == self.recover.idx && self.recover.count < 10 { 1060 self.recover.count++ 1061 return 1062 } 1063 if self.idx > self.recover.idx { 1064 self.recover.idx = self.idx 1065 self.recover.count = 0 1066 return 1067 } 1068 // Reaching here indicates a parser bug, likely an 1069 // incorrect token list in this function, but it only 1070 // leads to skipping of possibly correct code if a 1071 // previous error is present, and thus is preferred 1072 // over a non-terminating parse. 1073 case token.EOF: 1074 return 1075 } 1076 self.next() 1077 } 1078 }