github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/parser/statement.go (about) 1 package parser 2 3 import ( 4 "encoding/base64" 5 "fmt" 6 "os" 7 "strings" 8 9 "github.com/go-sourcemap/sourcemap" 10 "github.com/nuvolaris/goja/ast" 11 "github.com/nuvolaris/goja/file" 12 "github.com/nuvolaris/goja/token" 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 self.expect(token.SWITCH) 515 self.expect(token.LEFT_PARENTHESIS) 516 node := &ast.SwitchStatement{ 517 Discriminant: self.parseExpression(), 518 Default: -1, 519 } 520 self.expect(token.RIGHT_PARENTHESIS) 521 522 self.expect(token.LEFT_BRACE) 523 524 inSwitch := self.scope.inSwitch 525 self.scope.inSwitch = true 526 defer func() { 527 self.scope.inSwitch = inSwitch 528 }() 529 530 for index := 0; self.token != token.EOF; index++ { 531 if self.token == token.RIGHT_BRACE { 532 self.next() 533 break 534 } 535 536 clause := self.parseCaseStatement() 537 if clause.Test == nil { 538 if node.Default != -1 { 539 self.error(clause.Case, "Already saw a default in switch") 540 } 541 node.Default = index 542 } 543 node.Body = append(node.Body, clause) 544 } 545 546 return node 547 } 548 549 func (self *_parser) parseWithStatement() ast.Statement { 550 self.expect(token.WITH) 551 self.expect(token.LEFT_PARENTHESIS) 552 node := &ast.WithStatement{ 553 Object: self.parseExpression(), 554 } 555 self.expect(token.RIGHT_PARENTHESIS) 556 self.scope.allowLet = false 557 node.Body = self.parseStatement() 558 559 return node 560 } 561 562 func (self *_parser) parseCaseStatement() *ast.CaseStatement { 563 564 node := &ast.CaseStatement{ 565 Case: self.idx, 566 } 567 if self.token == token.DEFAULT { 568 self.next() 569 } else { 570 self.expect(token.CASE) 571 node.Test = self.parseExpression() 572 } 573 self.expect(token.COLON) 574 575 for { 576 if self.token == token.EOF || 577 self.token == token.RIGHT_BRACE || 578 self.token == token.CASE || 579 self.token == token.DEFAULT { 580 break 581 } 582 self.scope.allowLet = true 583 node.Consequent = append(node.Consequent, self.parseStatement()) 584 585 } 586 587 return node 588 } 589 590 func (self *_parser) parseIterationStatement() ast.Statement { 591 inIteration := self.scope.inIteration 592 self.scope.inIteration = true 593 defer func() { 594 self.scope.inIteration = inIteration 595 }() 596 self.scope.allowLet = false 597 return self.parseStatement() 598 } 599 600 func (self *_parser) parseForIn(idx file.Idx, into ast.ForInto) *ast.ForInStatement { 601 602 // Already have consumed "<into> in" 603 604 source := self.parseExpression() 605 self.expect(token.RIGHT_PARENTHESIS) 606 607 return &ast.ForInStatement{ 608 For: idx, 609 Into: into, 610 Source: source, 611 Body: self.parseIterationStatement(), 612 } 613 } 614 615 func (self *_parser) parseForOf(idx file.Idx, into ast.ForInto) *ast.ForOfStatement { 616 617 // Already have consumed "<into> of" 618 619 source := self.parseAssignmentExpression() 620 self.expect(token.RIGHT_PARENTHESIS) 621 622 return &ast.ForOfStatement{ 623 For: idx, 624 Into: into, 625 Source: source, 626 Body: self.parseIterationStatement(), 627 } 628 } 629 630 func (self *_parser) parseFor(idx file.Idx, initializer ast.ForLoopInitializer) *ast.ForStatement { 631 632 // Already have consumed "<initializer> ;" 633 634 var test, update ast.Expression 635 636 if self.token != token.SEMICOLON { 637 test = self.parseExpression() 638 } 639 self.expect(token.SEMICOLON) 640 641 if self.token != token.RIGHT_PARENTHESIS { 642 update = self.parseExpression() 643 } 644 self.expect(token.RIGHT_PARENTHESIS) 645 646 return &ast.ForStatement{ 647 For: idx, 648 Initializer: initializer, 649 Test: test, 650 Update: update, 651 Body: self.parseIterationStatement(), 652 } 653 } 654 655 func (self *_parser) parseForOrForInStatement() ast.Statement { 656 idx := self.expect(token.FOR) 657 self.expect(token.LEFT_PARENTHESIS) 658 659 var initializer ast.ForLoopInitializer 660 661 forIn := false 662 forOf := false 663 var into ast.ForInto 664 if self.token != token.SEMICOLON { 665 666 allowIn := self.scope.allowIn 667 self.scope.allowIn = false 668 tok := self.token 669 if tok == token.LET { 670 switch self.peek() { 671 case token.IDENTIFIER, token.LEFT_BRACKET, token.LEFT_BRACE: 672 default: 673 tok = token.IDENTIFIER 674 } 675 } 676 if tok == token.VAR || tok == token.LET || tok == token.CONST { 677 idx := self.idx 678 self.next() 679 var list []*ast.Binding 680 if tok == token.VAR { 681 list = self.parseVarDeclarationList(idx) 682 } else { 683 list = self.parseVariableDeclarationList() 684 } 685 if len(list) == 1 { 686 if self.token == token.IN { 687 self.next() // in 688 forIn = true 689 } else if self.token == token.IDENTIFIER && self.literal == "of" { 690 self.next() 691 forOf = true 692 } 693 } 694 if forIn || forOf { 695 if list[0].Initializer != nil { 696 self.error(list[0].Initializer.Idx0(), "for-in loop variable declaration may not have an initializer") 697 } 698 if tok == token.VAR { 699 into = &ast.ForIntoVar{ 700 Binding: list[0], 701 } 702 } else { 703 into = &ast.ForDeclaration{ 704 Idx: idx, 705 IsConst: tok == token.CONST, 706 Target: list[0].Target, 707 } 708 } 709 } else { 710 self.ensurePatternInit(list) 711 if tok == token.VAR { 712 initializer = &ast.ForLoopInitializerVarDeclList{ 713 List: list, 714 } 715 } else { 716 initializer = &ast.ForLoopInitializerLexicalDecl{ 717 LexicalDeclaration: ast.LexicalDeclaration{ 718 Idx: idx, 719 Token: tok, 720 List: list, 721 }, 722 } 723 } 724 } 725 } else { 726 expr := self.parseExpression() 727 if self.token == token.IN { 728 self.next() 729 forIn = true 730 } else if self.token == token.IDENTIFIER && self.literal == "of" { 731 self.next() 732 forOf = true 733 } 734 if forIn || forOf { 735 switch e := expr.(type) { 736 case *ast.Identifier, *ast.DotExpression, *ast.PrivateDotExpression, *ast.BracketExpression, *ast.Binding: 737 // These are all acceptable 738 case *ast.ObjectLiteral: 739 expr = self.reinterpretAsObjectAssignmentPattern(e) 740 case *ast.ArrayLiteral: 741 expr = self.reinterpretAsArrayAssignmentPattern(e) 742 default: 743 self.error(idx, "Invalid left-hand side in for-in or for-of") 744 self.nextStatement() 745 return &ast.BadStatement{From: idx, To: self.idx} 746 } 747 into = &ast.ForIntoExpression{ 748 Expression: expr, 749 } 750 } else { 751 initializer = &ast.ForLoopInitializerExpression{ 752 Expression: expr, 753 } 754 } 755 } 756 self.scope.allowIn = allowIn 757 } 758 759 if forIn { 760 return self.parseForIn(idx, into) 761 } 762 if forOf { 763 return self.parseForOf(idx, into) 764 } 765 766 self.expect(token.SEMICOLON) 767 return self.parseFor(idx, initializer) 768 } 769 770 func (self *_parser) ensurePatternInit(list []*ast.Binding) { 771 for _, item := range list { 772 if _, ok := item.Target.(ast.Pattern); ok { 773 if item.Initializer == nil { 774 self.error(item.Idx1(), "Missing initializer in destructuring declaration") 775 break 776 } 777 } 778 } 779 } 780 781 func (self *_parser) parseVariableStatement() *ast.VariableStatement { 782 783 idx := self.expect(token.VAR) 784 785 list := self.parseVarDeclarationList(idx) 786 self.ensurePatternInit(list) 787 self.semicolon() 788 789 return &ast.VariableStatement{ 790 Var: idx, 791 List: list, 792 } 793 } 794 795 func (self *_parser) parseLexicalDeclaration(tok token.Token) *ast.LexicalDeclaration { 796 idx := self.expect(tok) 797 if !self.scope.allowLet { 798 self.error(idx, "Lexical declaration cannot appear in a single-statement context") 799 } 800 801 list := self.parseVariableDeclarationList() 802 self.ensurePatternInit(list) 803 self.semicolon() 804 805 return &ast.LexicalDeclaration{ 806 Idx: idx, 807 Token: tok, 808 List: list, 809 } 810 } 811 812 func (self *_parser) parseDoWhileStatement() ast.Statement { 813 inIteration := self.scope.inIteration 814 self.scope.inIteration = true 815 defer func() { 816 self.scope.inIteration = inIteration 817 }() 818 819 self.expect(token.DO) 820 node := &ast.DoWhileStatement{} 821 if self.token == token.LEFT_BRACE { 822 node.Body = self.parseBlockStatement() 823 } else { 824 self.scope.allowLet = false 825 node.Body = self.parseStatement() 826 } 827 828 self.expect(token.WHILE) 829 self.expect(token.LEFT_PARENTHESIS) 830 node.Test = self.parseExpression() 831 self.expect(token.RIGHT_PARENTHESIS) 832 if self.token == token.SEMICOLON { 833 self.next() 834 } 835 836 return node 837 } 838 839 func (self *_parser) parseWhileStatement() ast.Statement { 840 self.expect(token.WHILE) 841 self.expect(token.LEFT_PARENTHESIS) 842 node := &ast.WhileStatement{ 843 Test: self.parseExpression(), 844 } 845 self.expect(token.RIGHT_PARENTHESIS) 846 node.Body = self.parseIterationStatement() 847 848 return node 849 } 850 851 func (self *_parser) parseIfStatement() ast.Statement { 852 self.expect(token.IF) 853 self.expect(token.LEFT_PARENTHESIS) 854 node := &ast.IfStatement{ 855 Test: self.parseExpression(), 856 } 857 self.expect(token.RIGHT_PARENTHESIS) 858 859 if self.token == token.LEFT_BRACE { 860 node.Consequent = self.parseBlockStatement() 861 } else { 862 self.scope.allowLet = false 863 node.Consequent = self.parseStatement() 864 } 865 866 if self.token == token.ELSE { 867 self.next() 868 self.scope.allowLet = false 869 node.Alternate = self.parseStatement() 870 } 871 872 return node 873 } 874 875 func (self *_parser) parseSourceElements() (body []ast.Statement) { 876 for self.token != token.EOF { 877 self.scope.allowLet = true 878 body = append(body, self.parseStatement()) 879 } 880 881 return body 882 } 883 884 func (self *_parser) parseProgram() *ast.Program { 885 prg := &ast.Program{ 886 Body: self.parseSourceElements(), 887 DeclarationList: self.scope.declarationList, 888 File: self.file, 889 } 890 self.file.SetSourceMap(self.parseSourceMap()) 891 return prg 892 } 893 894 func extractSourceMapLine(str string) string { 895 for { 896 p := strings.LastIndexByte(str, '\n') 897 line := str[p+1:] 898 if line != "" && line != "})" { 899 if strings.HasPrefix(line, "//# sourceMappingURL=") { 900 return line 901 } 902 break 903 } 904 if p >= 0 { 905 str = str[:p] 906 } else { 907 break 908 } 909 } 910 return "" 911 } 912 913 func (self *_parser) parseSourceMap() *sourcemap.Consumer { 914 if self.opts.disableSourceMaps { 915 return nil 916 } 917 if smLine := extractSourceMapLine(self.str); smLine != "" { 918 urlIndex := strings.Index(smLine, "=") 919 urlStr := smLine[urlIndex+1:] 920 921 var data []byte 922 var err error 923 if strings.HasPrefix(urlStr, "data:application/json") { 924 b64Index := strings.Index(urlStr, ",") 925 b64 := urlStr[b64Index+1:] 926 data, err = base64.StdEncoding.DecodeString(b64) 927 } else { 928 if sourceURL := file.ResolveSourcemapURL(self.file.Name(), urlStr); sourceURL != nil { 929 if self.opts.sourceMapLoader != nil { 930 data, err = self.opts.sourceMapLoader(sourceURL.String()) 931 } else { 932 if sourceURL.Scheme == "" || sourceURL.Scheme == "file" { 933 data, err = os.ReadFile(sourceURL.Path) 934 } else { 935 err = fmt.Errorf("unsupported source map URL scheme: %s", sourceURL.Scheme) 936 } 937 } 938 } 939 } 940 941 if err != nil { 942 self.error(file.Idx(0), "Could not load source map: %v", err) 943 return nil 944 } 945 if data == nil { 946 return nil 947 } 948 949 if sm, err := sourcemap.Parse(self.file.Name(), data); err == nil { 950 return sm 951 } else { 952 self.error(file.Idx(0), "Could not parse source map: %v", err) 953 } 954 } 955 return nil 956 } 957 958 func (self *_parser) parseBreakStatement() ast.Statement { 959 idx := self.expect(token.BREAK) 960 semicolon := self.implicitSemicolon 961 if self.token == token.SEMICOLON { 962 semicolon = true 963 self.next() 964 } 965 966 if semicolon || self.token == token.RIGHT_BRACE { 967 self.implicitSemicolon = false 968 if !self.scope.inIteration && !self.scope.inSwitch { 969 goto illegal 970 } 971 return &ast.BranchStatement{ 972 Idx: idx, 973 Token: token.BREAK, 974 } 975 } 976 977 self.tokenToBindingId() 978 if self.token == token.IDENTIFIER { 979 identifier := self.parseIdentifier() 980 if !self.scope.hasLabel(identifier.Name) { 981 self.error(idx, "Undefined label '%s'", identifier.Name) 982 return &ast.BadStatement{From: idx, To: identifier.Idx1()} 983 } 984 self.semicolon() 985 return &ast.BranchStatement{ 986 Idx: idx, 987 Token: token.BREAK, 988 Label: identifier, 989 } 990 } 991 992 self.expect(token.IDENTIFIER) 993 994 illegal: 995 self.error(idx, "Illegal break statement") 996 self.nextStatement() 997 return &ast.BadStatement{From: idx, To: self.idx} 998 } 999 1000 func (self *_parser) parseContinueStatement() ast.Statement { 1001 idx := self.expect(token.CONTINUE) 1002 semicolon := self.implicitSemicolon 1003 if self.token == token.SEMICOLON { 1004 semicolon = true 1005 self.next() 1006 } 1007 1008 if semicolon || self.token == token.RIGHT_BRACE { 1009 self.implicitSemicolon = false 1010 if !self.scope.inIteration { 1011 goto illegal 1012 } 1013 return &ast.BranchStatement{ 1014 Idx: idx, 1015 Token: token.CONTINUE, 1016 } 1017 } 1018 1019 self.tokenToBindingId() 1020 if self.token == token.IDENTIFIER { 1021 identifier := self.parseIdentifier() 1022 if !self.scope.hasLabel(identifier.Name) { 1023 self.error(idx, "Undefined label '%s'", identifier.Name) 1024 return &ast.BadStatement{From: idx, To: identifier.Idx1()} 1025 } 1026 if !self.scope.inIteration { 1027 goto illegal 1028 } 1029 self.semicolon() 1030 return &ast.BranchStatement{ 1031 Idx: idx, 1032 Token: token.CONTINUE, 1033 Label: identifier, 1034 } 1035 } 1036 1037 self.expect(token.IDENTIFIER) 1038 1039 illegal: 1040 self.error(idx, "Illegal continue statement") 1041 self.nextStatement() 1042 return &ast.BadStatement{From: idx, To: self.idx} 1043 } 1044 1045 // Find the next statement after an error (recover) 1046 func (self *_parser) nextStatement() { 1047 for { 1048 switch self.token { 1049 case token.BREAK, token.CONTINUE, 1050 token.FOR, token.IF, token.RETURN, token.SWITCH, 1051 token.VAR, token.DO, token.TRY, token.WITH, 1052 token.WHILE, token.THROW, token.CATCH, token.FINALLY: 1053 // Return only if parser made some progress since last 1054 // sync or if it has not reached 10 next calls without 1055 // progress. Otherwise consume at least one token to 1056 // avoid an endless parser loop 1057 if self.idx == self.recover.idx && self.recover.count < 10 { 1058 self.recover.count++ 1059 return 1060 } 1061 if self.idx > self.recover.idx { 1062 self.recover.idx = self.idx 1063 self.recover.count = 0 1064 return 1065 } 1066 // Reaching here indicates a parser bug, likely an 1067 // incorrect token list in this function, but it only 1068 // leads to skipping of possibly correct code if a 1069 // previous error is present, and thus is preferred 1070 // over a non-terminating parse. 1071 case token.EOF: 1072 return 1073 } 1074 self.next() 1075 } 1076 }