1# -*- coding: utf-8 -*- 2# Copyright JS Foundation and other contributors, https://js.foundation/ 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions are met: 6# 7# * Redistributions of source code must retain the above copyright 8# notice, this list of conditions and the following disclaimer. 9# * Redistributions in binary form must reproduce the above copyright 10# notice, this list of conditions and the following disclaimer in the 11# documentation and/or other materials provided with the distribution. 12# 13# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY 17# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 24from __future__ import absolute_import, unicode_literals 25 26from .objects import Object 27from .compat import basestring, unicode 28from .utils import format 29from .error_handler import ErrorHandler 30from .messages import Messages 31from .scanner import RawToken, Scanner, SourceLocation, Position, RegExp 32from .token import Token, TokenName 33from .syntax import Syntax 34from . import nodes as Node 35 36 37class Value(object): 38 def __init__(self, value): 39 self.value = value 40 41 42class Params(object): 43 def __init__(self, simple=None, message=None, stricted=None, firstRestricted=None, inFor=None, paramSet=None, params=None, get=None): 44 self.simple = simple 45 self.message = message 46 self.stricted = stricted 47 self.firstRestricted = firstRestricted 48 self.inFor = inFor 49 self.paramSet = paramSet 50 self.params = params 51 self.get = get 52 53 54class Config(Object): 55 def __init__(self, range=False, loc=False, source=None, tokens=False, comment=False, tolerant=False, **options): 56 self.range = range 57 self.loc = loc 58 self.source = source 59 self.tokens = tokens 60 self.comment = comment 61 self.tolerant = tolerant 62 for k, v in options.items(): 63 setattr(self, k, v) 64 65 66class Context(object): 67 def __init__(self, isModule=False, allowAwait=False, allowIn=True, allowStrictDirective=True, allowYield=True, firstCoverInitializedNameError=None, isAssignmentTarget=False, isBindingElement=False, inFunctionBody=False, inIteration=False, inSwitch=False, labelSet=None, strict=False): 68 self.isModule = isModule 69 self.allowAwait = allowAwait 70 self.allowIn = allowIn 71 self.allowStrictDirective = allowStrictDirective 72 self.allowYield = allowYield 73 self.firstCoverInitializedNameError = firstCoverInitializedNameError 74 self.isAssignmentTarget = isAssignmentTarget 75 self.isBindingElement = isBindingElement 76 self.inFunctionBody = inFunctionBody 77 self.inIteration = inIteration 78 self.inSwitch = inSwitch 79 self.labelSet = {} if labelSet is None else labelSet 80 self.strict = strict 81 82 83class Marker(object): 84 def __init__(self, index=None, line=None, column=None): 85 self.index = index 86 self.line = line 87 self.column = column 88 89 90class TokenEntry(Object): 91 def __init__(self, type=None, value=None, regex=None, range=None, loc=None): 92 self.type = type 93 self.value = value 94 self.regex = regex 95 self.range = range 96 self.loc = loc 97 98 99class Parser(object): 100 def __init__(self, code, options={}, delegate=None): 101 self.config = Config(**options) 102 103 self.delegate = delegate 104 105 self.errorHandler = ErrorHandler() 106 self.errorHandler.tolerant = self.config.tolerant 107 self.scanner = Scanner(code, self.errorHandler) 108 self.scanner.trackComment = self.config.comment 109 110 self.operatorPrecedence = { 111 '||': 1, 112 '&&': 2, 113 '|': 3, 114 '^': 4, 115 '&': 5, 116 '==': 6, 117 '!=': 6, 118 '===': 6, 119 '!==': 6, 120 '<': 7, 121 '>': 7, 122 '<=': 7, 123 '>=': 7, 124 'instanceof': 7, 125 'in': 7, 126 '<<': 8, 127 '>>': 8, 128 '>>>': 8, 129 '+': 9, 130 '-': 9, 131 '*': 11, 132 '/': 11, 133 '%': 11, 134 } 135 136 self.lookahead = RawToken( 137 type=Token.EOF, 138 value='', 139 lineNumber=self.scanner.lineNumber, 140 lineStart=0, 141 start=0, 142 end=0 143 ) 144 self.hasLineTerminator = False 145 146 self.context = Context( 147 isModule=False, 148 allowAwait=False, 149 allowIn=True, 150 allowStrictDirective=True, 151 allowYield=True, 152 firstCoverInitializedNameError=None, 153 isAssignmentTarget=False, 154 isBindingElement=False, 155 inFunctionBody=False, 156 inIteration=False, 157 inSwitch=False, 158 labelSet={}, 159 strict=False 160 ) 161 self.tokens = [] 162 163 self.startMarker = Marker( 164 index=0, 165 line=self.scanner.lineNumber, 166 column=0 167 ) 168 self.lastMarker = Marker( 169 index=0, 170 line=self.scanner.lineNumber, 171 column=0 172 ) 173 self.nextToken() 174 self.lastMarker = Marker( 175 index=self.scanner.index, 176 line=self.scanner.lineNumber, 177 column=self.scanner.index - self.scanner.lineStart 178 ) 179 180 def throwError(self, messageFormat, *args): 181 msg = format(messageFormat, *args) 182 index = self.lastMarker.index 183 line = self.lastMarker.line 184 column = self.lastMarker.column + 1 185 raise self.errorHandler.createError(index, line, column, msg) 186 187 def tolerateError(self, messageFormat, *args): 188 msg = format(messageFormat, *args) 189 index = self.lastMarker.index 190 line = self.scanner.lineNumber 191 column = self.lastMarker.column + 1 192 self.errorHandler.tolerateError(index, line, column, msg) 193 194 # Throw an exception because of the token. 195 196 def unexpectedTokenError(self, token=None, message=None): 197 msg = message or Messages.UnexpectedToken 198 if token: 199 if not message: 200 typ = token.type 201 if typ is Token.EOF: 202 msg = Messages.UnexpectedEOS 203 elif typ is Token.Identifier: 204 msg = Messages.UnexpectedIdentifier 205 elif typ is Token.NumericLiteral: 206 msg = Messages.UnexpectedNumber 207 elif typ is Token.StringLiteral: 208 msg = Messages.UnexpectedString 209 elif typ is Token.Template: 210 msg = Messages.UnexpectedTemplate 211 elif typ is Token.Keyword: 212 if self.scanner.isFutureReservedWord(token.value): 213 msg = Messages.UnexpectedReserved 214 elif self.context.strict and self.scanner.isStrictModeReservedWord(token.value): 215 msg = Messages.StrictReservedWord 216 else: 217 msg = Messages.UnexpectedToken 218 value = token.value 219 else: 220 value = 'ILLEGAL' 221 222 msg = msg.replace('%0', unicode(value), 1) 223 224 if token and isinstance(token.lineNumber, int): 225 index = token.start 226 line = token.lineNumber 227 lastMarkerLineStart = self.lastMarker.index - self.lastMarker.column 228 column = token.start - lastMarkerLineStart + 1 229 return self.errorHandler.createError(index, line, column, msg) 230 else: 231 index = self.lastMarker.index 232 line = self.lastMarker.line 233 column = self.lastMarker.column + 1 234 return self.errorHandler.createError(index, line, column, msg) 235 236 def throwUnexpectedToken(self, token=None, message=None): 237 raise self.unexpectedTokenError(token, message) 238 239 def tolerateUnexpectedToken(self, token=None, message=None): 240 self.errorHandler.tolerate(self.unexpectedTokenError(token, message)) 241 242 def collectComments(self): 243 if not self.config.comment: 244 self.scanner.scanComments() 245 else: 246 comments = self.scanner.scanComments() 247 if comments: 248 for e in comments: 249 if e.multiLine: 250 node = Node.BlockComment(self.scanner.source[e.slice[0]:e.slice[1]]) 251 else: 252 node = Node.LineComment(self.scanner.source[e.slice[0]:e.slice[1]]) 253 if self.config.range: 254 node.range = e.range 255 if self.config.loc: 256 node.loc = e.loc 257 if self.delegate: 258 metadata = SourceLocation( 259 start=Position( 260 line=e.loc.start.line, 261 column=e.loc.start.column, 262 offset=e.range[0], 263 ), 264 end=Position( 265 line=e.loc.end.line, 266 column=e.loc.end.column, 267 offset=e.range[1], 268 ) 269 ) 270 new_node = self.delegate(node, metadata) 271 if new_node is not None: 272 node = new_node 273 274 # From internal representation to an external structure 275 276 def getTokenRaw(self, token): 277 return self.scanner.source[token.start:token.end] 278 279 def convertToken(self, token): 280 t = TokenEntry( 281 type=TokenName[token.type], 282 value=self.getTokenRaw(token), 283 ) 284 if self.config.range: 285 t.range = [token.start, token.end] 286 if self.config.loc: 287 t.loc = SourceLocation( 288 start=Position( 289 line=self.startMarker.line, 290 column=self.startMarker.column, 291 ), 292 end=Position( 293 line=self.scanner.lineNumber, 294 column=self.scanner.index - self.scanner.lineStart, 295 ), 296 ) 297 if token.type is Token.RegularExpression: 298 t.regex = RegExp( 299 pattern=token.pattern, 300 flags=token.flags, 301 ) 302 303 return t 304 305 def nextToken(self): 306 token = self.lookahead 307 308 self.lastMarker.index = self.scanner.index 309 self.lastMarker.line = self.scanner.lineNumber 310 self.lastMarker.column = self.scanner.index - self.scanner.lineStart 311 312 self.collectComments() 313 314 if self.scanner.index != self.startMarker.index: 315 self.startMarker.index = self.scanner.index 316 self.startMarker.line = self.scanner.lineNumber 317 self.startMarker.column = self.scanner.index - self.scanner.lineStart 318 319 next = self.scanner.lex() 320 self.hasLineTerminator = token.lineNumber != next.lineNumber 321 322 if next and self.context.strict and next.type is Token.Identifier: 323 if self.scanner.isStrictModeReservedWord(next.value): 324 next.type = Token.Keyword 325 self.lookahead = next 326 327 if self.config.tokens and next.type is not Token.EOF: 328 self.tokens.append(self.convertToken(next)) 329 330 return token 331 332 def nextRegexToken(self): 333 self.collectComments() 334 335 token = self.scanner.scanRegExp() 336 if self.config.tokens: 337 # Pop the previous token, '/' or '/=' 338 # self is added from the lookahead token. 339 self.tokens.pop() 340 341 self.tokens.append(self.convertToken(token)) 342 343 # Prime the next lookahead. 344 self.lookahead = token 345 self.nextToken() 346 347 return token 348 349 def createNode(self): 350 return Marker( 351 index=self.startMarker.index, 352 line=self.startMarker.line, 353 column=self.startMarker.column, 354 ) 355 356 def startNode(self, token, lastLineStart=0): 357 column = token.start - token.lineStart 358 line = token.lineNumber 359 if column < 0: 360 column += lastLineStart 361 line -= 1 362 363 return Marker( 364 index=token.start, 365 line=line, 366 column=column, 367 ) 368 369 def finalize(self, marker, node): 370 if self.config.range: 371 node.range = [marker.index, self.lastMarker.index] 372 373 if self.config.loc: 374 node.loc = SourceLocation( 375 start=Position( 376 line=marker.line, 377 column=marker.column, 378 ), 379 end=Position( 380 line=self.lastMarker.line, 381 column=self.lastMarker.column, 382 ), 383 ) 384 if self.config.source: 385 node.loc.source = self.config.source 386 387 if self.delegate: 388 metadata = SourceLocation( 389 start=Position( 390 line=marker.line, 391 column=marker.column, 392 offset=marker.index, 393 ), 394 end=Position( 395 line=self.lastMarker.line, 396 column=self.lastMarker.column, 397 offset=self.lastMarker.index, 398 ) 399 ) 400 new_node = self.delegate(node, metadata) 401 if new_node is not None: 402 node = new_node 403 404 return node 405 406 # Expect the next token to match the specified punctuator. 407 # If not, an exception will be thrown. 408 409 def expect(self, value): 410 token = self.nextToken() 411 if token.type is not Token.Punctuator or token.value != value: 412 self.throwUnexpectedToken(token) 413 414 # Quietly expect a comma when in tolerant mode, otherwise delegates to expect(). 415 416 def expectCommaSeparator(self): 417 if self.config.tolerant: 418 token = self.lookahead 419 if token.type is Token.Punctuator and token.value == ',': 420 self.nextToken() 421 elif token.type is Token.Punctuator and token.value == ';': 422 self.nextToken() 423 self.tolerateUnexpectedToken(token) 424 else: 425 self.tolerateUnexpectedToken(token, Messages.UnexpectedToken) 426 else: 427 self.expect(',') 428 429 # Expect the next token to match the specified keyword. 430 # If not, an exception will be thrown. 431 432 def expectKeyword(self, keyword): 433 token = self.nextToken() 434 if token.type is not Token.Keyword or token.value != keyword: 435 self.throwUnexpectedToken(token) 436 437 # Return true if the next token matches the specified punctuator. 438 439 def match(self, *value): 440 return self.lookahead.type is Token.Punctuator and self.lookahead.value in value 441 442 # Return true if the next token matches the specified keyword 443 444 def matchKeyword(self, *keyword): 445 return self.lookahead.type is Token.Keyword and self.lookahead.value in keyword 446 447 # Return true if the next token matches the specified contextual keyword 448 # (where an identifier is sometimes a keyword depending on the context) 449 450 def matchContextualKeyword(self, *keyword): 451 return self.lookahead.type is Token.Identifier and self.lookahead.value in keyword 452 453 # Return true if the next token is an assignment operator 454 455 def matchAssign(self): 456 if self.lookahead.type is not Token.Punctuator: 457 return False 458 459 op = self.lookahead.value 460 return op in ('=', '*=', '**=', '/=', '%=', '+=', '-=', '<<=', '>>=', '>>>=', '&=', '^=', '|=') 461 462 # Cover grammar support. 463 # 464 # When an assignment expression position starts with an left parenthesis, the determination of the type 465 # of the syntax is to be deferred arbitrarily long until the end of the parentheses pair (plus a lookahead) 466 # or the first comma. This situation also defers the determination of all the expressions nested in the pair. 467 # 468 # There are three productions that can be parsed in a parentheses pair that needs to be determined 469 # after the outermost pair is closed. They are: 470 # 471 # 1. AssignmentExpression 472 # 2. BindingElements 473 # 3. AssignmentTargets 474 # 475 # In order to avoid exponential backtracking, we use two flags to denote if the production can be 476 # binding element or assignment target. 477 # 478 # The three productions have the relationship: 479 # 480 # BindingElements ⊆ AssignmentTargets ⊆ AssignmentExpression 481 # 482 # with a single exception that CoverInitializedName when used directly in an Expression, generates 483 # an early error. Therefore, we need the third state, firstCoverInitializedNameError, to track the 484 # first usage of CoverInitializedName and report it when we reached the end of the parentheses pair. 485 # 486 # isolateCoverGrammar function runs the given parser function with a new cover grammar context, and it does not 487 # effect the current flags. This means the production the parser parses is only used as an expression. Therefore 488 # the CoverInitializedName check is conducted. 489 # 490 # inheritCoverGrammar function runs the given parse function with a new cover grammar context, and it propagates 491 # the flags outside of the parser. This means the production the parser parses is used as a part of a potential 492 # pattern. The CoverInitializedName check is deferred. 493 494 def isolateCoverGrammar(self, parseFunction): 495 previousIsBindingElement = self.context.isBindingElement 496 previousIsAssignmentTarget = self.context.isAssignmentTarget 497 previousFirstCoverInitializedNameError = self.context.firstCoverInitializedNameError 498 499 self.context.isBindingElement = True 500 self.context.isAssignmentTarget = True 501 self.context.firstCoverInitializedNameError = None 502 503 result = parseFunction() 504 if self.context.firstCoverInitializedNameError is not None: 505 self.throwUnexpectedToken(self.context.firstCoverInitializedNameError) 506 507 self.context.isBindingElement = previousIsBindingElement 508 self.context.isAssignmentTarget = previousIsAssignmentTarget 509 self.context.firstCoverInitializedNameError = previousFirstCoverInitializedNameError 510 511 return result 512 513 def inheritCoverGrammar(self, parseFunction): 514 previousIsBindingElement = self.context.isBindingElement 515 previousIsAssignmentTarget = self.context.isAssignmentTarget 516 previousFirstCoverInitializedNameError = self.context.firstCoverInitializedNameError 517 518 self.context.isBindingElement = True 519 self.context.isAssignmentTarget = True 520 self.context.firstCoverInitializedNameError = None 521 522 result = parseFunction() 523 524 self.context.isBindingElement = self.context.isBindingElement and previousIsBindingElement 525 self.context.isAssignmentTarget = self.context.isAssignmentTarget and previousIsAssignmentTarget 526 self.context.firstCoverInitializedNameError = previousFirstCoverInitializedNameError or self.context.firstCoverInitializedNameError 527 528 return result 529 530 def consumeSemicolon(self): 531 if self.match(';'): 532 self.nextToken() 533 elif not self.hasLineTerminator: 534 if self.lookahead.type is not Token.EOF and not self.match('}'): 535 self.throwUnexpectedToken(self.lookahead) 536 self.lastMarker.index = self.startMarker.index 537 self.lastMarker.line = self.startMarker.line 538 self.lastMarker.column = self.startMarker.column 539 540 # https://tc39.github.io/ecma262/#sec-primary-expression 541 542 def parsePrimaryExpression(self): 543 node = self.createNode() 544 545 typ = self.lookahead.type 546 if typ is Token.Identifier: 547 if (self.context.isModule or self.context.allowAwait) and self.lookahead.value == 'await': 548 self.tolerateUnexpectedToken(self.lookahead) 549 expr = self.parseFunctionExpression() if self.matchAsyncFunction() else self.finalize(node, Node.Identifier(self.nextToken().value)) 550 551 elif typ in ( 552 Token.NumericLiteral, 553 Token.StringLiteral, 554 ): 555 if self.context.strict and self.lookahead.octal: 556 self.tolerateUnexpectedToken(self.lookahead, Messages.StrictOctalLiteral) 557 self.context.isAssignmentTarget = False 558 self.context.isBindingElement = False 559 token = self.nextToken() 560 raw = self.getTokenRaw(token) 561 expr = self.finalize(node, Node.Literal(token.value, raw)) 562 563 elif typ is Token.BooleanLiteral: 564 self.context.isAssignmentTarget = False 565 self.context.isBindingElement = False 566 token = self.nextToken() 567 raw = self.getTokenRaw(token) 568 expr = self.finalize(node, Node.Literal(token.value == 'true', raw)) 569 570 elif typ is Token.NullLiteral: 571 self.context.isAssignmentTarget = False 572 self.context.isBindingElement = False 573 token = self.nextToken() 574 raw = self.getTokenRaw(token) 575 expr = self.finalize(node, Node.Literal(None, raw)) 576 577 elif typ is Token.Template: 578 expr = self.parseTemplateLiteral() 579 580 elif typ is Token.Punctuator: 581 value = self.lookahead.value 582 if value == '(': 583 self.context.isBindingElement = False 584 expr = self.inheritCoverGrammar(self.parseGroupExpression) 585 elif value == '[': 586 expr = self.inheritCoverGrammar(self.parseArrayInitializer) 587 elif value == '{': 588 expr = self.inheritCoverGrammar(self.parseObjectInitializer) 589 elif value in ('/', '/='): 590 self.context.isAssignmentTarget = False 591 self.context.isBindingElement = False 592 self.scanner.index = self.startMarker.index 593 token = self.nextRegexToken() 594 raw = self.getTokenRaw(token) 595 expr = self.finalize(node, Node.RegexLiteral(token.regex, raw, token.pattern, token.flags)) 596 else: 597 expr = self.throwUnexpectedToken(self.nextToken()) 598 599 elif typ is Token.Keyword: 600 if not self.context.strict and self.context.allowYield and self.matchKeyword('yield'): 601 expr = self.parseIdentifierName() 602 elif not self.context.strict and self.matchKeyword('let'): 603 expr = self.finalize(node, Node.Identifier(self.nextToken().value)) 604 else: 605 self.context.isAssignmentTarget = False 606 self.context.isBindingElement = False 607 if self.matchKeyword('function'): 608 expr = self.parseFunctionExpression() 609 elif self.matchKeyword('this'): 610 self.nextToken() 611 expr = self.finalize(node, Node.ThisExpression()) 612 elif self.matchKeyword('class'): 613 expr = self.parseClassExpression() 614 elif self.matchImportCall(): 615 expr = self.parseImportCall() 616 else: 617 expr = self.throwUnexpectedToken(self.nextToken()) 618 619 else: 620 expr = self.throwUnexpectedToken(self.nextToken()) 621 622 return expr 623 624 # https://tc39.github.io/ecma262/#sec-array-initializer 625 626 def parseSpreadElement(self): 627 node = self.createNode() 628 self.expect('...') 629 arg = self.inheritCoverGrammar(self.parseAssignmentExpression) 630 return self.finalize(node, Node.SpreadElement(arg)) 631 632 def parseArrayInitializer(self): 633 node = self.createNode() 634 elements = [] 635 636 self.expect('[') 637 while not self.match(']'): 638 if self.match(','): 639 self.nextToken() 640 elements.append(None) 641 elif self.match('...'): 642 element = self.parseSpreadElement() 643 if not self.match(']'): 644 self.context.isAssignmentTarget = False 645 self.context.isBindingElement = False 646 self.expect(',') 647 elements.append(element) 648 else: 649 elements.append(self.inheritCoverGrammar(self.parseAssignmentExpression)) 650 if not self.match(']'): 651 self.expect(',') 652 self.expect(']') 653 654 return self.finalize(node, Node.ArrayExpression(elements)) 655 656 # https://tc39.github.io/ecma262/#sec-object-initializer 657 658 def parsePropertyMethod(self, params): 659 self.context.isAssignmentTarget = False 660 self.context.isBindingElement = False 661 662 previousStrict = self.context.strict 663 previousAllowStrictDirective = self.context.allowStrictDirective 664 self.context.allowStrictDirective = params.simple 665 body = self.isolateCoverGrammar(self.parseFunctionSourceElements) 666 if self.context.strict and params.firstRestricted: 667 self.tolerateUnexpectedToken(params.firstRestricted, params.message) 668 if self.context.strict and params.stricted: 669 self.tolerateUnexpectedToken(params.stricted, params.message) 670 self.context.strict = previousStrict 671 self.context.allowStrictDirective = previousAllowStrictDirective 672 673 return body 674 675 def parsePropertyMethodFunction(self): 676 isGenerator = False 677 node = self.createNode() 678 679 previousAllowYield = self.context.allowYield 680 self.context.allowYield = True 681 params = self.parseFormalParameters() 682 method = self.parsePropertyMethod(params) 683 self.context.allowYield = previousAllowYield 684 685 return self.finalize(node, Node.FunctionExpression(None, params.params, method, isGenerator)) 686 687 def parsePropertyMethodAsyncFunction(self): 688 node = self.createNode() 689 690 previousAllowYield = self.context.allowYield 691 previousAwait = self.context.allowAwait 692 self.context.allowYield = False 693 self.context.allowAwait = True 694 params = self.parseFormalParameters() 695 method = self.parsePropertyMethod(params) 696 self.context.allowYield = previousAllowYield 697 self.context.allowAwait = previousAwait 698 699 return self.finalize(node, Node.AsyncFunctionExpression(None, params.params, method)) 700 701 def parseObjectPropertyKey(self): 702 node = self.createNode() 703 token = self.nextToken() 704 705 typ = token.type 706 if typ in ( 707 Token.StringLiteral, 708 Token.NumericLiteral, 709 ): 710 if self.context.strict and token.octal: 711 self.tolerateUnexpectedToken(token, Messages.StrictOctalLiteral) 712 raw = self.getTokenRaw(token) 713 key = self.finalize(node, Node.Literal(token.value, raw)) 714 715 elif typ in ( 716 Token.Identifier, 717 Token.BooleanLiteral, 718 Token.NullLiteral, 719 Token.Keyword, 720 ): 721 key = self.finalize(node, Node.Identifier(token.value)) 722 723 elif typ is Token.Punctuator: 724 if token.value == '[': 725 key = self.isolateCoverGrammar(self.parseAssignmentExpression) 726 self.expect(']') 727 else: 728 key = self.throwUnexpectedToken(token) 729 730 else: 731 key = self.throwUnexpectedToken(token) 732 733 return key 734 735 def isPropertyKey(self, key, value): 736 return ( 737 (key.type is Syntax.Identifier and key.name == value) or 738 (key.type is Syntax.Literal and key.value == value) 739 ) 740 741 def parseObjectProperty(self, hasProto): 742 node = self.createNode() 743 token = self.lookahead 744 745 key = None 746 value = None 747 748 computed = False 749 method = False 750 shorthand = False 751 isAsync = False 752 753 if token.type is Token.Identifier: 754 id = token.value 755 self.nextToken() 756 computed = self.match('[') 757 isAsync = not self.hasLineTerminator and (id == 'async') and not (self.match(':', '(', '*', ',')) 758 key = self.parseObjectPropertyKey() if isAsync else self.finalize(node, Node.Identifier(id)) 759 elif self.match('*'): 760 self.nextToken() 761 else: 762 computed = self.match('[') 763 key = self.parseObjectPropertyKey() 764 765 lookaheadPropertyKey = self.qualifiedPropertyName(self.lookahead) 766 if token.type is Token.Identifier and not isAsync and token.value == 'get' and lookaheadPropertyKey: 767 kind = 'get' 768 computed = self.match('[') 769 key = self.parseObjectPropertyKey() 770 self.context.allowYield = False 771 value = self.parseGetterMethod() 772 773 elif token.type is Token.Identifier and not isAsync and token.value == 'set' and lookaheadPropertyKey: 774 kind = 'set' 775 computed = self.match('[') 776 key = self.parseObjectPropertyKey() 777 value = self.parseSetterMethod() 778 779 elif token.type is Token.Punctuator and token.value == '*' and lookaheadPropertyKey: 780 kind = 'init' 781 computed = self.match('[') 782 key = self.parseObjectPropertyKey() 783 value = self.parseGeneratorMethod() 784 method = True 785 786 else: 787 if not key: 788 self.throwUnexpectedToken(self.lookahead) 789 790 kind = 'init' 791 if self.match(':') and not isAsync: 792 if not computed and self.isPropertyKey(key, '__proto__'): 793 if hasProto.value: 794 self.tolerateError(Messages.DuplicateProtoProperty) 795 hasProto.value = True 796 self.nextToken() 797 value = self.inheritCoverGrammar(self.parseAssignmentExpression) 798 799 elif self.match('('): 800 value = self.parsePropertyMethodAsyncFunction() if isAsync else self.parsePropertyMethodFunction() 801 method = True 802 803 elif token.type is Token.Identifier: 804 id = self.finalize(node, Node.Identifier(token.value)) 805 if self.match('='): 806 self.context.firstCoverInitializedNameError = self.lookahead 807 self.nextToken() 808 shorthand = True 809 init = self.isolateCoverGrammar(self.parseAssignmentExpression) 810 value = self.finalize(node, Node.AssignmentPattern(id, init)) 811 else: 812 shorthand = True 813 value = id 814 else: 815 self.throwUnexpectedToken(self.nextToken()) 816 817 return self.finalize(node, Node.Property(kind, key, computed, value, method, shorthand)) 818 819 def parseObjectInitializer(self): 820 node = self.createNode() 821 822 self.expect('{') 823 properties = [] 824 hasProto = Value(False) 825 while not self.match('}'): 826 properties.append(self.parseSpreadElement() if self.match('...') else self.parseObjectProperty(hasProto)) 827 if not self.match('}'): 828 self.expectCommaSeparator() 829 self.expect('}') 830 831 return self.finalize(node, Node.ObjectExpression(properties)) 832 833 # https://tc39.github.io/ecma262/#sec-template-literals 834 835 def parseTemplateHead(self): 836 assert self.lookahead.head, 'Template literal must start with a template head' 837 838 node = self.createNode() 839 token = self.nextToken() 840 raw = token.value 841 cooked = token.cooked 842 843 return self.finalize(node, Node.TemplateElement(raw, cooked, token.tail)) 844 845 def parseTemplateElement(self): 846 if self.lookahead.type is not Token.Template: 847 self.throwUnexpectedToken() 848 849 node = self.createNode() 850 token = self.nextToken() 851 raw = token.value 852 cooked = token.cooked 853 854 return self.finalize(node, Node.TemplateElement(raw, cooked, token.tail)) 855 856 def parseTemplateLiteral(self): 857 node = self.createNode() 858 859 expressions = [] 860 quasis = [] 861 862 quasi = self.parseTemplateHead() 863 quasis.append(quasi) 864 while not quasi.tail: 865 expressions.append(self.parseExpression()) 866 quasi = self.parseTemplateElement() 867 quasis.append(quasi) 868 869 return self.finalize(node, Node.TemplateLiteral(quasis, expressions)) 870 871 # https://tc39.github.io/ecma262/#sec-grouping-operator 872 873 def reinterpretExpressionAsPattern(self, expr): 874 typ = expr.type 875 if typ in ( 876 Syntax.Identifier, 877 Syntax.MemberExpression, 878 Syntax.RestElement, 879 Syntax.AssignmentPattern, 880 ): 881 pass 882 elif typ is Syntax.SpreadElement: 883 expr.type = Syntax.RestElement 884 self.reinterpretExpressionAsPattern(expr.argument) 885 elif typ is Syntax.ArrayExpression: 886 expr.type = Syntax.ArrayPattern 887 for elem in expr.elements: 888 if elem is not None: 889 self.reinterpretExpressionAsPattern(elem) 890 elif typ is Syntax.ObjectExpression: 891 expr.type = Syntax.ObjectPattern 892 for prop in expr.properties: 893 self.reinterpretExpressionAsPattern(prop if prop.type is Syntax.SpreadElement else prop.value) 894 elif typ is Syntax.AssignmentExpression: 895 expr.type = Syntax.AssignmentPattern 896 del expr.operator 897 self.reinterpretExpressionAsPattern(expr.left) 898 else: 899 # Allow other node type for tolerant parsing. 900 pass 901 902 def parseGroupExpression(self): 903 self.expect('(') 904 if self.match(')'): 905 self.nextToken() 906 if not self.match('=>'): 907 self.expect('=>') 908 expr = Node.ArrowParameterPlaceHolder([]) 909 else: 910 startToken = self.lookahead 911 params = [] 912 if self.match('...'): 913 expr = self.parseRestElement(params) 914 self.expect(')') 915 if not self.match('=>'): 916 self.expect('=>') 917 expr = Node.ArrowParameterPlaceHolder([expr]) 918 else: 919 arrow = False 920 self.context.isBindingElement = True 921 expr = self.inheritCoverGrammar(self.parseAssignmentExpression) 922 923 if self.match(','): 924 expressions = [] 925 926 self.context.isAssignmentTarget = False 927 expressions.append(expr) 928 while self.lookahead.type is not Token.EOF: 929 if not self.match(','): 930 break 931 self.nextToken() 932 if self.match(')'): 933 self.nextToken() 934 for expression in expressions: 935 self.reinterpretExpressionAsPattern(expression) 936 arrow = True 937 expr = Node.ArrowParameterPlaceHolder(expressions) 938 elif self.match('...'): 939 if not self.context.isBindingElement: 940 self.throwUnexpectedToken(self.lookahead) 941 expressions.append(self.parseRestElement(params)) 942 self.expect(')') 943 if not self.match('=>'): 944 self.expect('=>') 945 self.context.isBindingElement = False 946 for expression in expressions: 947 self.reinterpretExpressionAsPattern(expression) 948 arrow = True 949 expr = Node.ArrowParameterPlaceHolder(expressions) 950 else: 951 expressions.append(self.inheritCoverGrammar(self.parseAssignmentExpression)) 952 if arrow: 953 break 954 if not arrow: 955 expr = self.finalize(self.startNode(startToken), Node.SequenceExpression(expressions)) 956 957 if not arrow: 958 self.expect(')') 959 if self.match('=>'): 960 if expr.type is Syntax.Identifier and expr.name == 'yield': 961 arrow = True 962 expr = Node.ArrowParameterPlaceHolder([expr]) 963 if not arrow: 964 if not self.context.isBindingElement: 965 self.throwUnexpectedToken(self.lookahead) 966 967 if expr.type is Syntax.SequenceExpression: 968 for expression in expr.expressions: 969 self.reinterpretExpressionAsPattern(expression) 970 else: 971 self.reinterpretExpressionAsPattern(expr) 972 973 if expr.type is Syntax.SequenceExpression: 974 parameters = expr.expressions 975 else: 976 parameters = [expr] 977 expr = Node.ArrowParameterPlaceHolder(parameters) 978 self.context.isBindingElement = False 979 980 return expr 981 982 # https://tc39.github.io/ecma262/#sec-left-hand-side-expressions 983 984 def parseArguments(self): 985 self.expect('(') 986 args = [] 987 if not self.match(')'): 988 while True: 989 if self.match('...'): 990 expr = self.parseSpreadElement() 991 else: 992 expr = self.isolateCoverGrammar(self.parseAssignmentExpression) 993 args.append(expr) 994 if self.match(')'): 995 break 996 self.expectCommaSeparator() 997 if self.match(')'): 998 break 999 self.expect(')') 1000 1001 return args 1002 1003 def isIdentifierName(self, token): 1004 return ( 1005 token.type is Token.Identifier or 1006 token.type is Token.Keyword or 1007 token.type is Token.BooleanLiteral or 1008 token.type is Token.NullLiteral 1009 ) 1010 1011 def parseIdentifierName(self): 1012 node = self.createNode() 1013 token = self.nextToken() 1014 if not self.isIdentifierName(token): 1015 self.throwUnexpectedToken(token) 1016 return self.finalize(node, Node.Identifier(token.value)) 1017 1018 def parseNewExpression(self): 1019 node = self.createNode() 1020 1021 id = self.parseIdentifierName() 1022 assert id.name == 'new', 'New expression must start with `new`' 1023 1024 if self.match('.'): 1025 self.nextToken() 1026 if self.lookahead.type is Token.Identifier and self.context.inFunctionBody and self.lookahead.value == 'target': 1027 property = self.parseIdentifierName() 1028 expr = Node.MetaProperty(id, property) 1029 else: 1030 self.throwUnexpectedToken(self.lookahead) 1031 elif self.matchKeyword('import'): 1032 self.throwUnexpectedToken(self.lookahead) 1033 else: 1034 callee = self.isolateCoverGrammar(self.parseLeftHandSideExpression) 1035 args = self.parseArguments() if self.match('(') else [] 1036 expr = Node.NewExpression(callee, args) 1037 self.context.isAssignmentTarget = False 1038 self.context.isBindingElement = False 1039 1040 return self.finalize(node, expr) 1041 1042 def parseAsyncArgument(self): 1043 arg = self.parseAssignmentExpression() 1044 self.context.firstCoverInitializedNameError = None 1045 return arg 1046 1047 def parseAsyncArguments(self): 1048 self.expect('(') 1049 args = [] 1050 if not self.match(')'): 1051 while True: 1052 if self.match('...'): 1053 expr = self.parseSpreadElement() 1054 else: 1055 expr = self.isolateCoverGrammar(self.parseAsyncArgument) 1056 args.append(expr) 1057 if self.match(')'): 1058 break 1059 self.expectCommaSeparator() 1060 if self.match(')'): 1061 break 1062 self.expect(')') 1063 1064 return args 1065 1066 def matchImportCall(self): 1067 match = self.matchKeyword('import') 1068 if match: 1069 state = self.scanner.saveState() 1070 self.scanner.scanComments() 1071 next = self.scanner.lex() 1072 self.scanner.restoreState(state) 1073 match = (next.type is Token.Punctuator) and (next.value == '(') 1074 1075 return match 1076 1077 def parseImportCall(self): 1078 node = self.createNode() 1079 self.expectKeyword('import') 1080 return self.finalize(node, Node.Import()) 1081 1082 def parseLeftHandSideExpressionAllowCall(self): 1083 startToken = self.lookahead 1084 maybeAsync = self.matchContextualKeyword('async') 1085 1086 previousAllowIn = self.context.allowIn 1087 self.context.allowIn = True 1088 1089 if self.matchKeyword('super') and self.context.inFunctionBody: 1090 expr = self.createNode() 1091 self.nextToken() 1092 expr = self.finalize(expr, Node.Super()) 1093 if not self.match('(') and not self.match('.') and not self.match('['): 1094 self.throwUnexpectedToken(self.lookahead) 1095 else: 1096 expr = self.inheritCoverGrammar(self.parseNewExpression if self.matchKeyword('new') else self.parsePrimaryExpression) 1097 1098 while True: 1099 if self.match('.'): 1100 self.context.isBindingElement = False 1101 self.context.isAssignmentTarget = True 1102 self.expect('.') 1103 property = self.parseIdentifierName() 1104 expr = self.finalize(self.startNode(startToken), Node.StaticMemberExpression(expr, property)) 1105 1106 elif self.match('('): 1107 asyncArrow = maybeAsync and (startToken.lineNumber == self.lookahead.lineNumber) 1108 self.context.isBindingElement = False 1109 self.context.isAssignmentTarget = False 1110 if asyncArrow: 1111 args = self.parseAsyncArguments() 1112 else: 1113 args = self.parseArguments() 1114 if expr.type is Syntax.Import and len(args) != 1: 1115 self.tolerateError(Messages.BadImportCallArity) 1116 expr = self.finalize(self.startNode(startToken), Node.CallExpression(expr, args)) 1117 if asyncArrow and self.match('=>'): 1118 for arg in args: 1119 self.reinterpretExpressionAsPattern(arg) 1120 expr = Node.AsyncArrowParameterPlaceHolder(args) 1121 elif self.match('['): 1122 self.context.isBindingElement = False 1123 self.context.isAssignmentTarget = True 1124 self.expect('[') 1125 property = self.isolateCoverGrammar(self.parseExpression) 1126 self.expect(']') 1127 expr = self.finalize(self.startNode(startToken), Node.ComputedMemberExpression(expr, property)) 1128 1129 elif self.lookahead.type is Token.Template and self.lookahead.head: 1130 quasi = self.parseTemplateLiteral() 1131 expr = self.finalize(self.startNode(startToken), Node.TaggedTemplateExpression(expr, quasi)) 1132 1133 else: 1134 break 1135 1136 self.context.allowIn = previousAllowIn 1137 1138 return expr 1139 1140 def parseSuper(self): 1141 node = self.createNode() 1142 1143 self.expectKeyword('super') 1144 if not self.match('[') and not self.match('.'): 1145 self.throwUnexpectedToken(self.lookahead) 1146 1147 return self.finalize(node, Node.Super()) 1148 1149 def parseLeftHandSideExpression(self): 1150 assert self.context.allowIn, 'callee of new expression always allow in keyword.' 1151 1152 node = self.startNode(self.lookahead) 1153 if self.matchKeyword('super') and self.context.inFunctionBody: 1154 expr = self.parseSuper() 1155 else: 1156 expr = self.inheritCoverGrammar(self.parseNewExpression if self.matchKeyword('new') else self.parsePrimaryExpression) 1157 1158 while True: 1159 if self.match('['): 1160 self.context.isBindingElement = False 1161 self.context.isAssignmentTarget = True 1162 self.expect('[') 1163 property = self.isolateCoverGrammar(self.parseExpression) 1164 self.expect(']') 1165 expr = self.finalize(node, Node.ComputedMemberExpression(expr, property)) 1166 1167 elif self.match('.'): 1168 self.context.isBindingElement = False 1169 self.context.isAssignmentTarget = True 1170 self.expect('.') 1171 property = self.parseIdentifierName() 1172 expr = self.finalize(node, Node.StaticMemberExpression(expr, property)) 1173 1174 elif self.lookahead.type is Token.Template and self.lookahead.head: 1175 quasi = self.parseTemplateLiteral() 1176 expr = self.finalize(node, Node.TaggedTemplateExpression(expr, quasi)) 1177 1178 else: 1179 break 1180 1181 return expr 1182 1183 # https://tc39.github.io/ecma262/#sec-update-expressions 1184 1185 def parseUpdateExpression(self): 1186 startToken = self.lookahead 1187 1188 if self.match('++', '--'): 1189 node = self.startNode(startToken) 1190 token = self.nextToken() 1191 expr = self.inheritCoverGrammar(self.parseUnaryExpression) 1192 if self.context.strict and expr.type is Syntax.Identifier and self.scanner.isRestrictedWord(expr.name): 1193 self.tolerateError(Messages.StrictLHSPrefix) 1194 if not self.context.isAssignmentTarget: 1195 self.tolerateError(Messages.InvalidLHSInAssignment) 1196 prefix = True 1197 expr = self.finalize(node, Node.UpdateExpression(token.value, expr, prefix)) 1198 self.context.isAssignmentTarget = False 1199 self.context.isBindingElement = False 1200 else: 1201 expr = self.inheritCoverGrammar(self.parseLeftHandSideExpressionAllowCall) 1202 if not self.hasLineTerminator and self.lookahead.type is Token.Punctuator: 1203 if self.match('++', '--'): 1204 if self.context.strict and expr.type is Syntax.Identifier and self.scanner.isRestrictedWord(expr.name): 1205 self.tolerateError(Messages.StrictLHSPostfix) 1206 if not self.context.isAssignmentTarget: 1207 self.tolerateError(Messages.InvalidLHSInAssignment) 1208 self.context.isAssignmentTarget = False 1209 self.context.isBindingElement = False 1210 operator = self.nextToken().value 1211 prefix = False 1212 expr = self.finalize(self.startNode(startToken), Node.UpdateExpression(operator, expr, prefix)) 1213 1214 return expr 1215 1216 # https://tc39.github.io/ecma262/#sec-unary-operators 1217 1218 def parseAwaitExpression(self): 1219 node = self.createNode() 1220 self.nextToken() 1221 argument = self.parseUnaryExpression() 1222 return self.finalize(node, Node.AwaitExpression(argument)) 1223 1224 def parseUnaryExpression(self): 1225 if ( 1226 self.match('+', '-', '~', '!') or 1227 self.matchKeyword('delete', 'void', 'typeof') 1228 ): 1229 node = self.startNode(self.lookahead) 1230 token = self.nextToken() 1231 expr = self.inheritCoverGrammar(self.parseUnaryExpression) 1232 expr = self.finalize(node, Node.UnaryExpression(token.value, expr)) 1233 if self.context.strict and expr.operator == 'delete' and expr.argument.type is Syntax.Identifier: 1234 self.tolerateError(Messages.StrictDelete) 1235 self.context.isAssignmentTarget = False 1236 self.context.isBindingElement = False 1237 elif self.context.allowAwait and self.matchContextualKeyword('await'): 1238 expr = self.parseAwaitExpression() 1239 else: 1240 expr = self.parseUpdateExpression() 1241 1242 return expr 1243 1244 def parseExponentiationExpression(self): 1245 startToken = self.lookahead 1246 1247 expr = self.inheritCoverGrammar(self.parseUnaryExpression) 1248 if expr.type is not Syntax.UnaryExpression and self.match('**'): 1249 self.nextToken() 1250 self.context.isAssignmentTarget = False 1251 self.context.isBindingElement = False 1252 left = expr 1253 right = self.isolateCoverGrammar(self.parseExponentiationExpression) 1254 expr = self.finalize(self.startNode(startToken), Node.BinaryExpression('**', left, right)) 1255 1256 return expr 1257 1258 # https://tc39.github.io/ecma262/#sec-exp-operator 1259 # https://tc39.github.io/ecma262/#sec-multiplicative-operators 1260 # https://tc39.github.io/ecma262/#sec-additive-operators 1261 # https://tc39.github.io/ecma262/#sec-bitwise-shift-operators 1262 # https://tc39.github.io/ecma262/#sec-relational-operators 1263 # https://tc39.github.io/ecma262/#sec-equality-operators 1264 # https://tc39.github.io/ecma262/#sec-binary-bitwise-operators 1265 # https://tc39.github.io/ecma262/#sec-binary-logical-operators 1266 1267 def binaryPrecedence(self, token): 1268 op = token.value 1269 if token.type is Token.Punctuator: 1270 precedence = self.operatorPrecedence.get(op, 0) 1271 elif token.type is Token.Keyword: 1272 precedence = 7 if (op == 'instanceof' or (self.context.allowIn and op == 'in')) else 0 1273 else: 1274 precedence = 0 1275 return precedence 1276 1277 def parseBinaryExpression(self): 1278 startToken = self.lookahead 1279 1280 expr = self.inheritCoverGrammar(self.parseExponentiationExpression) 1281 1282 token = self.lookahead 1283 prec = self.binaryPrecedence(token) 1284 if prec > 0: 1285 self.nextToken() 1286 1287 self.context.isAssignmentTarget = False 1288 self.context.isBindingElement = False 1289 1290 markers = [startToken, self.lookahead] 1291 left = expr 1292 right = self.isolateCoverGrammar(self.parseExponentiationExpression) 1293 1294 stack = [left, token.value, right] 1295 precedences = [prec] 1296 while True: 1297 prec = self.binaryPrecedence(self.lookahead) 1298 if prec <= 0: 1299 break 1300 1301 # Reduce: make a binary expression from the three topmost entries. 1302 while len(stack) > 2 and prec <= precedences[-1]: 1303 right = stack.pop() 1304 operator = stack.pop() 1305 precedences.pop() 1306 left = stack.pop() 1307 markers.pop() 1308 node = self.startNode(markers[-1]) 1309 stack.append(self.finalize(node, Node.BinaryExpression(operator, left, right))) 1310 1311 # Shift. 1312 stack.append(self.nextToken().value) 1313 precedences.append(prec) 1314 markers.append(self.lookahead) 1315 stack.append(self.isolateCoverGrammar(self.parseExponentiationExpression)) 1316 1317 # Final reduce to clean-up the stack. 1318 i = len(stack) - 1 1319 expr = stack[i] 1320 1321 lastMarker = markers.pop() 1322 while i > 1: 1323 marker = markers.pop() 1324 lastLineStart = lastMarker.lineStart if lastMarker else 0 1325 node = self.startNode(marker, lastLineStart) 1326 operator = stack[i - 1] 1327 expr = self.finalize(node, Node.BinaryExpression(operator, stack[i - 2], expr)) 1328 i -= 2 1329 lastMarker = marker 1330 1331 return expr 1332 1333 # https://tc39.github.io/ecma262/#sec-conditional-operator 1334 1335 def parseConditionalExpression(self): 1336 startToken = self.lookahead 1337 1338 expr = self.inheritCoverGrammar(self.parseBinaryExpression) 1339 if self.match('?'): 1340 self.nextToken() 1341 1342 previousAllowIn = self.context.allowIn 1343 self.context.allowIn = True 1344 consequent = self.isolateCoverGrammar(self.parseAssignmentExpression) 1345 self.context.allowIn = previousAllowIn 1346 1347 self.expect(':') 1348 alternate = self.isolateCoverGrammar(self.parseAssignmentExpression) 1349 1350 expr = self.finalize(self.startNode(startToken), Node.ConditionalExpression(expr, consequent, alternate)) 1351 self.context.isAssignmentTarget = False 1352 self.context.isBindingElement = False 1353 1354 return expr 1355 1356 # https://tc39.github.io/ecma262/#sec-assignment-operators 1357 1358 def checkPatternParam(self, options, param): 1359 typ = param.type 1360 if typ is Syntax.Identifier: 1361 self.validateParam(options, param, param.name) 1362 elif typ is Syntax.RestElement: 1363 self.checkPatternParam(options, param.argument) 1364 elif typ is Syntax.AssignmentPattern: 1365 self.checkPatternParam(options, param.left) 1366 elif typ is Syntax.ArrayPattern: 1367 for element in param.elements: 1368 if element is not None: 1369 self.checkPatternParam(options, element) 1370 elif typ is Syntax.ObjectPattern: 1371 for prop in param.properties: 1372 self.checkPatternParam(options, prop if prop.type is Syntax.RestElement else prop.value) 1373 1374 options.simple = options.simple and isinstance(param, Node.Identifier) 1375 1376 def reinterpretAsCoverFormalsList(self, expr): 1377 params = [expr] 1378 1379 asyncArrow = False 1380 typ = expr.type 1381 if typ is Syntax.Identifier: 1382 pass 1383 elif typ is Syntax.ArrowParameterPlaceHolder: 1384 params = expr.params 1385 asyncArrow = expr.isAsync 1386 else: 1387 return None 1388 1389 options = Params( 1390 simple=True, 1391 paramSet={}, 1392 ) 1393 1394 for param in params: 1395 if param.type is Syntax.AssignmentPattern: 1396 if param.right.type is Syntax.YieldExpression: 1397 if param.right.argument: 1398 self.throwUnexpectedToken(self.lookahead) 1399 param.right.type = Syntax.Identifier 1400 param.right.name = 'yield' 1401 del param.right.argument 1402 del param.right.delegate 1403 elif asyncArrow and param.type is Syntax.Identifier and param.name == 'await': 1404 self.throwUnexpectedToken(self.lookahead) 1405 self.checkPatternParam(options, param) 1406 1407 if self.context.strict or not self.context.allowYield: 1408 for param in params: 1409 if param.type is Syntax.YieldExpression: 1410 self.throwUnexpectedToken(self.lookahead) 1411 1412 if options.message is Messages.StrictParamDupe: 1413 token = options.stricted if self.context.strict else options.firstRestricted 1414 self.throwUnexpectedToken(token, options.message) 1415 1416 return Params( 1417 simple=options.simple, 1418 params=params, 1419 stricted=options.stricted, 1420 firstRestricted=options.firstRestricted, 1421 message=options.message 1422 ) 1423 1424 def parseAssignmentExpression(self): 1425 if not self.context.allowYield and self.matchKeyword('yield'): 1426 expr = self.parseYieldExpression() 1427 else: 1428 startToken = self.lookahead 1429 token = startToken 1430 expr = self.parseConditionalExpression() 1431 1432 if token.type is Token.Identifier and (token.lineNumber == self.lookahead.lineNumber) and token.value == 'async': 1433 if self.lookahead.type is Token.Identifier or self.matchKeyword('yield'): 1434 arg = self.parsePrimaryExpression() 1435 self.reinterpretExpressionAsPattern(arg) 1436 expr = Node.AsyncArrowParameterPlaceHolder([arg]) 1437 1438 if expr.type is Syntax.ArrowParameterPlaceHolder or self.match('=>'): 1439 1440 # https://tc39.github.io/ecma262/#sec-arrow-function-definitions 1441 self.context.isAssignmentTarget = False 1442 self.context.isBindingElement = False 1443 isAsync = expr.isAsync 1444 list = self.reinterpretAsCoverFormalsList(expr) 1445 1446 if list: 1447 if self.hasLineTerminator: 1448 self.tolerateUnexpectedToken(self.lookahead) 1449 self.context.firstCoverInitializedNameError = None 1450 1451 previousStrict = self.context.strict 1452 previousAllowStrictDirective = self.context.allowStrictDirective 1453 self.context.allowStrictDirective = list.simple 1454 1455 previousAllowYield = self.context.allowYield 1456 previousAwait = self.context.allowAwait 1457 self.context.allowYield = True 1458 self.context.allowAwait = isAsync 1459 1460 node = self.startNode(startToken) 1461 self.expect('=>') 1462 if self.match('{'): 1463 previousAllowIn = self.context.allowIn 1464 self.context.allowIn = True 1465 body = self.parseFunctionSourceElements() 1466 self.context.allowIn = previousAllowIn 1467 else: 1468 body = self.isolateCoverGrammar(self.parseAssignmentExpression) 1469 expression = body.type is not Syntax.BlockStatement 1470 1471 if self.context.strict and list.firstRestricted: 1472 self.throwUnexpectedToken(list.firstRestricted, list.message) 1473 if self.context.strict and list.stricted: 1474 self.tolerateUnexpectedToken(list.stricted, list.message) 1475 if isAsync: 1476 expr = self.finalize(node, Node.AsyncArrowFunctionExpression(list.params, body, expression)) 1477 else: 1478 expr = self.finalize(node, Node.ArrowFunctionExpression(list.params, body, expression)) 1479 1480 self.context.strict = previousStrict 1481 self.context.allowStrictDirective = previousAllowStrictDirective 1482 self.context.allowYield = previousAllowYield 1483 self.context.allowAwait = previousAwait 1484 else: 1485 if self.matchAssign(): 1486 if not self.context.isAssignmentTarget: 1487 self.tolerateError(Messages.InvalidLHSInAssignment) 1488 1489 if self.context.strict and expr.type is Syntax.Identifier: 1490 id = expr 1491 if self.scanner.isRestrictedWord(id.name): 1492 self.tolerateUnexpectedToken(token, Messages.StrictLHSAssignment) 1493 if self.scanner.isStrictModeReservedWord(id.name): 1494 self.tolerateUnexpectedToken(token, Messages.StrictReservedWord) 1495 1496 if not self.match('='): 1497 self.context.isAssignmentTarget = False 1498 self.context.isBindingElement = False 1499 else: 1500 self.reinterpretExpressionAsPattern(expr) 1501 1502 token = self.nextToken() 1503 operator = token.value 1504 right = self.isolateCoverGrammar(self.parseAssignmentExpression) 1505 expr = self.finalize(self.startNode(startToken), Node.AssignmentExpression(operator, expr, right)) 1506 self.context.firstCoverInitializedNameError = None 1507 1508 return expr 1509 1510 # https://tc39.github.io/ecma262/#sec-comma-operator 1511 1512 def parseExpression(self): 1513 startToken = self.lookahead 1514 expr = self.isolateCoverGrammar(self.parseAssignmentExpression) 1515 1516 if self.match(','): 1517 expressions = [] 1518 expressions.append(expr) 1519 while self.lookahead.type is not Token.EOF: 1520 if not self.match(','): 1521 break 1522 self.nextToken() 1523 expressions.append(self.isolateCoverGrammar(self.parseAssignmentExpression)) 1524 1525 expr = self.finalize(self.startNode(startToken), Node.SequenceExpression(expressions)) 1526 1527 return expr 1528 1529 # https://tc39.github.io/ecma262/#sec-block 1530 1531 def parseStatementListItem(self): 1532 self.context.isAssignmentTarget = True 1533 self.context.isBindingElement = True 1534 if self.lookahead.type is Token.Keyword: 1535 value = self.lookahead.value 1536 if value == 'export': 1537 if not self.context.isModule: 1538 self.tolerateUnexpectedToken(self.lookahead, Messages.IllegalExportDeclaration) 1539 statement = self.parseExportDeclaration() 1540 elif value == 'import': 1541 if self.matchImportCall(): 1542 statement = self.parseExpressionStatement() 1543 else: 1544 if not self.context.isModule: 1545 self.tolerateUnexpectedToken(self.lookahead, Messages.IllegalImportDeclaration) 1546 statement = self.parseImportDeclaration() 1547 elif value == 'const': 1548 statement = self.parseLexicalDeclaration(Params(inFor=False)) 1549 elif value == 'function': 1550 statement = self.parseFunctionDeclaration() 1551 elif value == 'class': 1552 statement = self.parseClassDeclaration() 1553 elif value == 'let': 1554 statement = self.parseLexicalDeclaration(Params(inFor=False)) if self.isLexicalDeclaration() else self.parseStatement() 1555 else: 1556 statement = self.parseStatement() 1557 else: 1558 statement = self.parseStatement() 1559 1560 return statement 1561 1562 def parseBlock(self): 1563 node = self.createNode() 1564 1565 self.expect('{') 1566 block = [] 1567 while True: 1568 if self.match('}'): 1569 break 1570 block.append(self.parseStatementListItem()) 1571 self.expect('}') 1572 1573 return self.finalize(node, Node.BlockStatement(block)) 1574 1575 # https://tc39.github.io/ecma262/#sec-let-and-const-declarations 1576 1577 def parseLexicalBinding(self, kind, options): 1578 node = self.createNode() 1579 params = [] 1580 id = self.parsePattern(params, kind) 1581 1582 if self.context.strict and id.type is Syntax.Identifier: 1583 if self.scanner.isRestrictedWord(id.name): 1584 self.tolerateError(Messages.StrictVarName) 1585 1586 init = None 1587 if kind == 'const': 1588 if not self.matchKeyword('in') and not self.matchContextualKeyword('of'): 1589 if self.match('='): 1590 self.nextToken() 1591 init = self.isolateCoverGrammar(self.parseAssignmentExpression) 1592 else: 1593 self.throwError(Messages.DeclarationMissingInitializer, 'const') 1594 elif (not options.inFor and id.type is not Syntax.Identifier) or self.match('='): 1595 self.expect('=') 1596 init = self.isolateCoverGrammar(self.parseAssignmentExpression) 1597 1598 return self.finalize(node, Node.VariableDeclarator(id, init)) 1599 1600 def parseBindingList(self, kind, options): 1601 lst = [self.parseLexicalBinding(kind, options)] 1602 1603 while self.match(','): 1604 self.nextToken() 1605 lst.append(self.parseLexicalBinding(kind, options)) 1606 1607 return lst 1608 1609 def isLexicalDeclaration(self): 1610 state = self.scanner.saveState() 1611 self.scanner.scanComments() 1612 next = self.scanner.lex() 1613 self.scanner.restoreState(state) 1614 1615 return ( 1616 (next.type is Token.Identifier) or 1617 (next.type is Token.Punctuator and next.value == '[') or 1618 (next.type is Token.Punctuator and next.value == '{') or 1619 (next.type is Token.Keyword and next.value == 'let') or 1620 (next.type is Token.Keyword and next.value == 'yield') 1621 ) 1622 1623 def parseLexicalDeclaration(self, options): 1624 node = self.createNode() 1625 kind = self.nextToken().value 1626 assert kind == 'let' or kind == 'const', 'Lexical declaration must be either or const' 1627 1628 declarations = self.parseBindingList(kind, options) 1629 self.consumeSemicolon() 1630 1631 return self.finalize(node, Node.VariableDeclaration(declarations, kind)) 1632 1633 # https://tc39.github.io/ecma262/#sec-destructuring-binding-patterns 1634 1635 def parseBindingRestElement(self, params, kind=None): 1636 node = self.createNode() 1637 1638 self.expect('...') 1639 arg = self.parsePattern(params, kind) 1640 1641 return self.finalize(node, Node.RestElement(arg)) 1642 1643 def parseArrayPattern(self, params, kind=None): 1644 node = self.createNode() 1645 1646 self.expect('[') 1647 elements = [] 1648 while not self.match(']'): 1649 if self.match(','): 1650 self.nextToken() 1651 elements.append(None) 1652 else: 1653 if self.match('...'): 1654 elements.append(self.parseBindingRestElement(params, kind)) 1655 break 1656 else: 1657 elements.append(self.parsePatternWithDefault(params, kind)) 1658 if not self.match(']'): 1659 self.expect(',') 1660 self.expect(']') 1661 1662 return self.finalize(node, Node.ArrayPattern(elements)) 1663 1664 def parsePropertyPattern(self, params, kind=None): 1665 node = self.createNode() 1666 1667 computed = False 1668 shorthand = False 1669 method = False 1670 1671 key = None 1672 1673 if self.lookahead.type is Token.Identifier: 1674 keyToken = self.lookahead 1675 key = self.parseVariableIdentifier() 1676 init = self.finalize(node, Node.Identifier(keyToken.value)) 1677 if self.match('='): 1678 params.append(keyToken) 1679 shorthand = True 1680 self.nextToken() 1681 expr = self.parseAssignmentExpression() 1682 value = self.finalize(self.startNode(keyToken), Node.AssignmentPattern(init, expr)) 1683 elif not self.match(':'): 1684 params.append(keyToken) 1685 shorthand = True 1686 value = init 1687 else: 1688 self.expect(':') 1689 value = self.parsePatternWithDefault(params, kind) 1690 else: 1691 computed = self.match('[') 1692 key = self.parseObjectPropertyKey() 1693 self.expect(':') 1694 value = self.parsePatternWithDefault(params, kind) 1695 1696 return self.finalize(node, Node.Property('init', key, computed, value, method, shorthand)) 1697 1698 def parseRestProperty(self, params, kind): 1699 node = self.createNode() 1700 self.expect('...') 1701 arg = self.parsePattern(params) 1702 if self.match('='): 1703 self.throwError(Messages.DefaultRestProperty) 1704 if not self.match('}'): 1705 self.throwError(Messages.PropertyAfterRestProperty) 1706 return self.finalize(node, Node.RestElement(arg)) 1707 1708 def parseObjectPattern(self, params, kind=None): 1709 node = self.createNode() 1710 properties = [] 1711 1712 self.expect('{') 1713 while not self.match('}'): 1714 properties.append(self.parseRestProperty(params, kind) if self.match('...') else self.parsePropertyPattern(params, kind)) 1715 if not self.match('}'): 1716 self.expect(',') 1717 self.expect('}') 1718 1719 return self.finalize(node, Node.ObjectPattern(properties)) 1720 1721 def parsePattern(self, params, kind=None): 1722 if self.match('['): 1723 pattern = self.parseArrayPattern(params, kind) 1724 elif self.match('{'): 1725 pattern = self.parseObjectPattern(params, kind) 1726 else: 1727 if self.matchKeyword('let') and (kind in ('const', 'let')): 1728 self.tolerateUnexpectedToken(self.lookahead, Messages.LetInLexicalBinding) 1729 params.append(self.lookahead) 1730 pattern = self.parseVariableIdentifier(kind) 1731 1732 return pattern 1733 1734 def parsePatternWithDefault(self, params, kind=None): 1735 startToken = self.lookahead 1736 1737 pattern = self.parsePattern(params, kind) 1738 if self.match('='): 1739 self.nextToken() 1740 previousAllowYield = self.context.allowYield 1741 self.context.allowYield = True 1742 right = self.isolateCoverGrammar(self.parseAssignmentExpression) 1743 self.context.allowYield = previousAllowYield 1744 pattern = self.finalize(self.startNode(startToken), Node.AssignmentPattern(pattern, right)) 1745 1746 return pattern 1747 1748 # https://tc39.github.io/ecma262/#sec-variable-statement 1749 1750 def parseVariableIdentifier(self, kind=None): 1751 node = self.createNode() 1752 1753 token = self.nextToken() 1754 if token.type is Token.Keyword and token.value == 'yield': 1755 if self.context.strict: 1756 self.tolerateUnexpectedToken(token, Messages.StrictReservedWord) 1757 elif not self.context.allowYield: 1758 self.throwUnexpectedToken(token) 1759 elif token.type is not Token.Identifier: 1760 if self.context.strict and token.type is Token.Keyword and self.scanner.isStrictModeReservedWord(token.value): 1761 self.tolerateUnexpectedToken(token, Messages.StrictReservedWord) 1762 else: 1763 if self.context.strict or token.value != 'let' or kind != 'var': 1764 self.throwUnexpectedToken(token) 1765 elif (self.context.isModule or self.context.allowAwait) and token.type is Token.Identifier and token.value == 'await': 1766 self.tolerateUnexpectedToken(token) 1767 1768 return self.finalize(node, Node.Identifier(token.value)) 1769 1770 def parseVariableDeclaration(self, options): 1771 node = self.createNode() 1772 1773 params = [] 1774 id = self.parsePattern(params, 'var') 1775 1776 if self.context.strict and id.type is Syntax.Identifier: 1777 if self.scanner.isRestrictedWord(id.name): 1778 self.tolerateError(Messages.StrictVarName) 1779 1780 init = None 1781 if self.match('='): 1782 self.nextToken() 1783 init = self.isolateCoverGrammar(self.parseAssignmentExpression) 1784 elif id.type is not Syntax.Identifier and not options.inFor: 1785 self.expect('=') 1786 1787 return self.finalize(node, Node.VariableDeclarator(id, init)) 1788 1789 def parseVariableDeclarationList(self, options): 1790 opt = Params(inFor=options.inFor) 1791 1792 lst = [] 1793 lst.append(self.parseVariableDeclaration(opt)) 1794 while self.match(','): 1795 self.nextToken() 1796 lst.append(self.parseVariableDeclaration(opt)) 1797 1798 return lst 1799 1800 def parseVariableStatement(self): 1801 node = self.createNode() 1802 self.expectKeyword('var') 1803 declarations = self.parseVariableDeclarationList(Params(inFor=False)) 1804 self.consumeSemicolon() 1805 1806 return self.finalize(node, Node.VariableDeclaration(declarations, 'var')) 1807 1808 # https://tc39.github.io/ecma262/#sec-empty-statement 1809 1810 def parseEmptyStatement(self): 1811 node = self.createNode() 1812 self.expect(';') 1813 return self.finalize(node, Node.EmptyStatement()) 1814 1815 # https://tc39.github.io/ecma262/#sec-expression-statement 1816 1817 def parseExpressionStatement(self): 1818 node = self.createNode() 1819 expr = self.parseExpression() 1820 self.consumeSemicolon() 1821 return self.finalize(node, Node.ExpressionStatement(expr)) 1822 1823 # https://tc39.github.io/ecma262/#sec-if-statement 1824 1825 def parseIfClause(self): 1826 if self.context.strict and self.matchKeyword('function'): 1827 self.tolerateError(Messages.StrictFunction) 1828 return self.parseStatement() 1829 1830 def parseIfStatement(self): 1831 node = self.createNode() 1832 alternate = None 1833 1834 self.expectKeyword('if') 1835 self.expect('(') 1836 test = self.parseExpression() 1837 1838 if not self.match(')') and self.config.tolerant: 1839 self.tolerateUnexpectedToken(self.nextToken()) 1840 consequent = self.finalize(self.createNode(), Node.EmptyStatement()) 1841 else: 1842 self.expect(')') 1843 consequent = self.parseIfClause() 1844 if self.matchKeyword('else'): 1845 self.nextToken() 1846 alternate = self.parseIfClause() 1847 1848 return self.finalize(node, Node.IfStatement(test, consequent, alternate)) 1849 1850 # https://tc39.github.io/ecma262/#sec-do-while-statement 1851 1852 def parseDoWhileStatement(self): 1853 node = self.createNode() 1854 self.expectKeyword('do') 1855 1856 previousInIteration = self.context.inIteration 1857 self.context.inIteration = True 1858 body = self.parseStatement() 1859 self.context.inIteration = previousInIteration 1860 1861 self.expectKeyword('while') 1862 self.expect('(') 1863 test = self.parseExpression() 1864 1865 if not self.match(')') and self.config.tolerant: 1866 self.tolerateUnexpectedToken(self.nextToken()) 1867 else: 1868 self.expect(')') 1869 if self.match(';'): 1870 self.nextToken() 1871 1872 return self.finalize(node, Node.DoWhileStatement(body, test)) 1873 1874 # https://tc39.github.io/ecma262/#sec-while-statement 1875 1876 def parseWhileStatement(self): 1877 node = self.createNode() 1878 1879 self.expectKeyword('while') 1880 self.expect('(') 1881 test = self.parseExpression() 1882 1883 if not self.match(')') and self.config.tolerant: 1884 self.tolerateUnexpectedToken(self.nextToken()) 1885 body = self.finalize(self.createNode(), Node.EmptyStatement()) 1886 else: 1887 self.expect(')') 1888 1889 previousInIteration = self.context.inIteration 1890 self.context.inIteration = True 1891 body = self.parseStatement() 1892 self.context.inIteration = previousInIteration 1893 1894 return self.finalize(node, Node.WhileStatement(test, body)) 1895 1896 # https://tc39.github.io/ecma262/#sec-for-statement 1897 # https://tc39.github.io/ecma262/#sec-for-in-and-for-of-statements 1898 1899 def parseForStatement(self): 1900 init = None 1901 test = None 1902 update = None 1903 forIn = True 1904 left = None 1905 right = None 1906 1907 node = self.createNode() 1908 self.expectKeyword('for') 1909 self.expect('(') 1910 1911 if self.match(';'): 1912 self.nextToken() 1913 else: 1914 if self.matchKeyword('var'): 1915 init = self.createNode() 1916 self.nextToken() 1917 1918 previousAllowIn = self.context.allowIn 1919 self.context.allowIn = False 1920 declarations = self.parseVariableDeclarationList(Params(inFor=True)) 1921 self.context.allowIn = previousAllowIn 1922 1923 if len(declarations) == 1 and self.matchKeyword('in'): 1924 decl = declarations[0] 1925 if decl.init and (decl.id.type is Syntax.ArrayPattern or decl.id.type is Syntax.ObjectPattern or self.context.strict): 1926 self.tolerateError(Messages.ForInOfLoopInitializer, 'for-in') 1927 init = self.finalize(init, Node.VariableDeclaration(declarations, 'var')) 1928 self.nextToken() 1929 left = init 1930 right = self.parseExpression() 1931 init = None 1932 elif len(declarations) == 1 and declarations[0].init is None and self.matchContextualKeyword('of'): 1933 init = self.finalize(init, Node.VariableDeclaration(declarations, 'var')) 1934 self.nextToken() 1935 left = init 1936 right = self.parseAssignmentExpression() 1937 init = None 1938 forIn = False 1939 else: 1940 init = self.finalize(init, Node.VariableDeclaration(declarations, 'var')) 1941 self.expect(';') 1942 elif self.matchKeyword('const', 'let'): 1943 init = self.createNode() 1944 kind = self.nextToken().value 1945 1946 if not self.context.strict and self.lookahead.value == 'in': 1947 init = self.finalize(init, Node.Identifier(kind)) 1948 self.nextToken() 1949 left = init 1950 right = self.parseExpression() 1951 init = None 1952 else: 1953 previousAllowIn = self.context.allowIn 1954 self.context.allowIn = False 1955 declarations = self.parseBindingList(kind, Params(inFor=True)) 1956 self.context.allowIn = previousAllowIn 1957 1958 if len(declarations) == 1 and declarations[0].init is None and self.matchKeyword('in'): 1959 init = self.finalize(init, Node.VariableDeclaration(declarations, kind)) 1960 self.nextToken() 1961 left = init 1962 right = self.parseExpression() 1963 init = None 1964 elif len(declarations) == 1 and declarations[0].init is None and self.matchContextualKeyword('of'): 1965 init = self.finalize(init, Node.VariableDeclaration(declarations, kind)) 1966 self.nextToken() 1967 left = init 1968 right = self.parseAssignmentExpression() 1969 init = None 1970 forIn = False 1971 else: 1972 self.consumeSemicolon() 1973 init = self.finalize(init, Node.VariableDeclaration(declarations, kind)) 1974 else: 1975 initStartToken = self.lookahead 1976 previousAllowIn = self.context.allowIn 1977 self.context.allowIn = False 1978 init = self.inheritCoverGrammar(self.parseAssignmentExpression) 1979 self.context.allowIn = previousAllowIn 1980 1981 if self.matchKeyword('in'): 1982 if not self.context.isAssignmentTarget or init.type is Syntax.AssignmentExpression: 1983 self.tolerateError(Messages.InvalidLHSInForIn) 1984 1985 self.nextToken() 1986 self.reinterpretExpressionAsPattern(init) 1987 left = init 1988 right = self.parseExpression() 1989 init = None 1990 elif self.matchContextualKeyword('of'): 1991 if not self.context.isAssignmentTarget or init.type is Syntax.AssignmentExpression: 1992 self.tolerateError(Messages.InvalidLHSInForLoop) 1993 1994 self.nextToken() 1995 self.reinterpretExpressionAsPattern(init) 1996 left = init 1997 right = self.parseAssignmentExpression() 1998 init = None 1999 forIn = False 2000 else: 2001 if self.match(','): 2002 initSeq = [init] 2003 while self.match(','): 2004 self.nextToken() 2005 initSeq.append(self.isolateCoverGrammar(self.parseAssignmentExpression)) 2006 init = self.finalize(self.startNode(initStartToken), Node.SequenceExpression(initSeq)) 2007 self.expect(';') 2008 2009 if left is None: 2010 if not self.match(';'): 2011 test = self.parseExpression() 2012 self.expect(';') 2013 if not self.match(')'): 2014 update = self.parseExpression() 2015 2016 if not self.match(')') and self.config.tolerant: 2017 self.tolerateUnexpectedToken(self.nextToken()) 2018 body = self.finalize(self.createNode(), Node.EmptyStatement()) 2019 else: 2020 self.expect(')') 2021 2022 previousInIteration = self.context.inIteration 2023 self.context.inIteration = True 2024 body = self.isolateCoverGrammar(self.parseStatement) 2025 self.context.inIteration = previousInIteration 2026 2027 if left is None: 2028 return self.finalize(node, Node.ForStatement(init, test, update, body)) 2029 2030 if forIn: 2031 return self.finalize(node, Node.ForInStatement(left, right, body)) 2032 2033 return self.finalize(node, Node.ForOfStatement(left, right, body)) 2034 2035 # https://tc39.github.io/ecma262/#sec-continue-statement 2036 2037 def parseContinueStatement(self): 2038 node = self.createNode() 2039 self.expectKeyword('continue') 2040 2041 label = None 2042 if self.lookahead.type is Token.Identifier and not self.hasLineTerminator: 2043 id = self.parseVariableIdentifier() 2044 label = id 2045 2046 key = '$' + id.name 2047 if key not in self.context.labelSet: 2048 self.throwError(Messages.UnknownLabel, id.name) 2049 2050 self.consumeSemicolon() 2051 if label is None and not self.context.inIteration: 2052 self.throwError(Messages.IllegalContinue) 2053 2054 return self.finalize(node, Node.ContinueStatement(label)) 2055 2056 # https://tc39.github.io/ecma262/#sec-break-statement 2057 2058 def parseBreakStatement(self): 2059 node = self.createNode() 2060 self.expectKeyword('break') 2061 2062 label = None 2063 if self.lookahead.type is Token.Identifier and not self.hasLineTerminator: 2064 id = self.parseVariableIdentifier() 2065 2066 key = '$' + id.name 2067 if key not in self.context.labelSet: 2068 self.throwError(Messages.UnknownLabel, id.name) 2069 label = id 2070 2071 self.consumeSemicolon() 2072 if label is None and not self.context.inIteration and not self.context.inSwitch: 2073 self.throwError(Messages.IllegalBreak) 2074 2075 return self.finalize(node, Node.BreakStatement(label)) 2076 2077 # https://tc39.github.io/ecma262/#sec-return-statement 2078 2079 def parseReturnStatement(self): 2080 if not self.context.inFunctionBody: 2081 self.tolerateError(Messages.IllegalReturn) 2082 2083 node = self.createNode() 2084 self.expectKeyword('return') 2085 2086 hasArgument = ( 2087 ( 2088 not self.match(';') and not self.match('}') and 2089 not self.hasLineTerminator and self.lookahead.type is not Token.EOF 2090 ) or 2091 self.lookahead.type is Token.StringLiteral or 2092 self.lookahead.type is Token.Template 2093 ) 2094 argument = self.parseExpression() if hasArgument else None 2095 self.consumeSemicolon() 2096 2097 return self.finalize(node, Node.ReturnStatement(argument)) 2098 2099 # https://tc39.github.io/ecma262/#sec-with-statement 2100 2101 def parseWithStatement(self): 2102 if self.context.strict: 2103 self.tolerateError(Messages.StrictModeWith) 2104 2105 node = self.createNode() 2106 2107 self.expectKeyword('with') 2108 self.expect('(') 2109 object = self.parseExpression() 2110 2111 if not self.match(')') and self.config.tolerant: 2112 self.tolerateUnexpectedToken(self.nextToken()) 2113 body = self.finalize(self.createNode(), Node.EmptyStatement()) 2114 else: 2115 self.expect(')') 2116 body = self.parseStatement() 2117 2118 return self.finalize(node, Node.WithStatement(object, body)) 2119 2120 # https://tc39.github.io/ecma262/#sec-switch-statement 2121 2122 def parseSwitchCase(self): 2123 node = self.createNode() 2124 2125 if self.matchKeyword('default'): 2126 self.nextToken() 2127 test = None 2128 else: 2129 self.expectKeyword('case') 2130 test = self.parseExpression() 2131 self.expect(':') 2132 2133 consequent = [] 2134 while True: 2135 if self.match('}') or self.matchKeyword('default', 'case'): 2136 break 2137 consequent.append(self.parseStatementListItem()) 2138 2139 return self.finalize(node, Node.SwitchCase(test, consequent)) 2140 2141 def parseSwitchStatement(self): 2142 node = self.createNode() 2143 self.expectKeyword('switch') 2144 2145 self.expect('(') 2146 discriminant = self.parseExpression() 2147 self.expect(')') 2148 2149 previousInSwitch = self.context.inSwitch 2150 self.context.inSwitch = True 2151 2152 cases = [] 2153 defaultFound = False 2154 self.expect('{') 2155 while True: 2156 if self.match('}'): 2157 break 2158 clause = self.parseSwitchCase() 2159 if clause.test is None: 2160 if defaultFound: 2161 self.throwError(Messages.MultipleDefaultsInSwitch) 2162 defaultFound = True 2163 cases.append(clause) 2164 self.expect('}') 2165 2166 self.context.inSwitch = previousInSwitch 2167 2168 return self.finalize(node, Node.SwitchStatement(discriminant, cases)) 2169 2170 # https://tc39.github.io/ecma262/#sec-labelled-statements 2171 2172 def parseLabelledStatement(self): 2173 node = self.createNode() 2174 expr = self.parseExpression() 2175 2176 if expr.type is Syntax.Identifier and self.match(':'): 2177 self.nextToken() 2178 2179 id = expr 2180 key = '$' + id.name 2181 if key in self.context.labelSet: 2182 self.throwError(Messages.Redeclaration, 'Label', id.name) 2183 2184 self.context.labelSet[key] = True 2185 if self.matchKeyword('class'): 2186 self.tolerateUnexpectedToken(self.lookahead) 2187 body = self.parseClassDeclaration() 2188 elif self.matchKeyword('function'): 2189 token = self.lookahead 2190 declaration = self.parseFunctionDeclaration() 2191 if self.context.strict: 2192 self.tolerateUnexpectedToken(token, Messages.StrictFunction) 2193 elif declaration.generator: 2194 self.tolerateUnexpectedToken(token, Messages.GeneratorInLegacyContext) 2195 body = declaration 2196 else: 2197 body = self.parseStatement() 2198 del self.context.labelSet[key] 2199 2200 statement = Node.LabeledStatement(id, body) 2201 else: 2202 self.consumeSemicolon() 2203 statement = Node.ExpressionStatement(expr) 2204 2205 return self.finalize(node, statement) 2206 2207 # https://tc39.github.io/ecma262/#sec-throw-statement 2208 2209 def parseThrowStatement(self): 2210 node = self.createNode() 2211 self.expectKeyword('throw') 2212 2213 if self.hasLineTerminator: 2214 self.throwError(Messages.NewlineAfterThrow) 2215 2216 argument = self.parseExpression() 2217 self.consumeSemicolon() 2218 2219 return self.finalize(node, Node.ThrowStatement(argument)) 2220 2221 # https://tc39.github.io/ecma262/#sec-try-statement 2222 2223 def parseCatchClause(self): 2224 node = self.createNode() 2225 2226 self.expectKeyword('catch') 2227 2228 self.expect('(') 2229 if self.match(')'): 2230 self.throwUnexpectedToken(self.lookahead) 2231 2232 params = [] 2233 param = self.parsePattern(params) 2234 paramMap = {} 2235 for p in params: 2236 key = '$' + p.value 2237 if key in paramMap: 2238 self.tolerateError(Messages.DuplicateBinding, p.value) 2239 paramMap[key] = True 2240 2241 if self.context.strict and param.type is Syntax.Identifier: 2242 if self.scanner.isRestrictedWord(param.name): 2243 self.tolerateError(Messages.StrictCatchVariable) 2244 2245 self.expect(')') 2246 body = self.parseBlock() 2247 2248 return self.finalize(node, Node.CatchClause(param, body)) 2249 2250 def parseFinallyClause(self): 2251 self.expectKeyword('finally') 2252 return self.parseBlock() 2253 2254 def parseTryStatement(self): 2255 node = self.createNode() 2256 self.expectKeyword('try') 2257 2258 block = self.parseBlock() 2259 handler = self.parseCatchClause() if self.matchKeyword('catch') else None 2260 finalizer = self.parseFinallyClause() if self.matchKeyword('finally') else None 2261 2262 if not handler and not finalizer: 2263 self.throwError(Messages.NoCatchOrFinally) 2264 2265 return self.finalize(node, Node.TryStatement(block, handler, finalizer)) 2266 2267 # https://tc39.github.io/ecma262/#sec-debugger-statement 2268 2269 def parseDebuggerStatement(self): 2270 node = self.createNode() 2271 self.expectKeyword('debugger') 2272 self.consumeSemicolon() 2273 return self.finalize(node, Node.DebuggerStatement()) 2274 2275 # https://tc39.github.io/ecma262/#sec-ecmascript-language-statements-and-declarations 2276 2277 def parseStatement(self): 2278 typ = self.lookahead.type 2279 if typ in ( 2280 Token.BooleanLiteral, 2281 Token.NullLiteral, 2282 Token.NumericLiteral, 2283 Token.StringLiteral, 2284 Token.Template, 2285 Token.RegularExpression, 2286 ): 2287 statement = self.parseExpressionStatement() 2288 2289 elif typ is Token.Punctuator: 2290 value = self.lookahead.value 2291 if value == '{': 2292 statement = self.parseBlock() 2293 elif value == '(': 2294 statement = self.parseExpressionStatement() 2295 elif value == ';': 2296 statement = self.parseEmptyStatement() 2297 else: 2298 statement = self.parseExpressionStatement() 2299 2300 elif typ is Token.Identifier: 2301 statement = self.parseFunctionDeclaration() if self.matchAsyncFunction() else self.parseLabelledStatement() 2302 2303 elif typ is Token.Keyword: 2304 value = self.lookahead.value 2305 if value == 'break': 2306 statement = self.parseBreakStatement() 2307 elif value == 'continue': 2308 statement = self.parseContinueStatement() 2309 elif value == 'debugger': 2310 statement = self.parseDebuggerStatement() 2311 elif value == 'do': 2312 statement = self.parseDoWhileStatement() 2313 elif value == 'for': 2314 statement = self.parseForStatement() 2315 elif value == 'function': 2316 statement = self.parseFunctionDeclaration() 2317 elif value == 'if': 2318 statement = self.parseIfStatement() 2319 elif value == 'return': 2320 statement = self.parseReturnStatement() 2321 elif value == 'switch': 2322 statement = self.parseSwitchStatement() 2323 elif value == 'throw': 2324 statement = self.parseThrowStatement() 2325 elif value == 'try': 2326 statement = self.parseTryStatement() 2327 elif value == 'var': 2328 statement = self.parseVariableStatement() 2329 elif value == 'while': 2330 statement = self.parseWhileStatement() 2331 elif value == 'with': 2332 statement = self.parseWithStatement() 2333 else: 2334 statement = self.parseExpressionStatement() 2335 2336 else: 2337 statement = self.throwUnexpectedToken(self.lookahead) 2338 2339 return statement 2340 2341 # https://tc39.github.io/ecma262/#sec-function-definitions 2342 2343 def parseFunctionSourceElements(self): 2344 node = self.createNode() 2345 2346 self.expect('{') 2347 body = self.parseDirectivePrologues() 2348 2349 previousLabelSet = self.context.labelSet 2350 previousInIteration = self.context.inIteration 2351 previousInSwitch = self.context.inSwitch 2352 previousInFunctionBody = self.context.inFunctionBody 2353 2354 self.context.labelSet = {} 2355 self.context.inIteration = False 2356 self.context.inSwitch = False 2357 self.context.inFunctionBody = True 2358 2359 while self.lookahead.type is not Token.EOF: 2360 if self.match('}'): 2361 break 2362 body.append(self.parseStatementListItem()) 2363 2364 self.expect('}') 2365 2366 self.context.labelSet = previousLabelSet 2367 self.context.inIteration = previousInIteration 2368 self.context.inSwitch = previousInSwitch 2369 self.context.inFunctionBody = previousInFunctionBody 2370 2371 return self.finalize(node, Node.BlockStatement(body)) 2372 2373 def validateParam(self, options, param, name): 2374 key = '$' + name 2375 if self.context.strict: 2376 if self.scanner.isRestrictedWord(name): 2377 options.stricted = param 2378 options.message = Messages.StrictParamName 2379 if key in options.paramSet: 2380 options.stricted = param 2381 options.message = Messages.StrictParamDupe 2382 elif not options.firstRestricted: 2383 if self.scanner.isRestrictedWord(name): 2384 options.firstRestricted = param 2385 options.message = Messages.StrictParamName 2386 elif self.scanner.isStrictModeReservedWord(name): 2387 options.firstRestricted = param 2388 options.message = Messages.StrictReservedWord 2389 elif key in options.paramSet: 2390 options.stricted = param 2391 options.message = Messages.StrictParamDupe 2392 2393 options.paramSet[key] = True 2394 2395 def parseRestElement(self, params): 2396 node = self.createNode() 2397 2398 self.expect('...') 2399 arg = self.parsePattern(params) 2400 if self.match('='): 2401 self.throwError(Messages.DefaultRestParameter) 2402 if not self.match(')'): 2403 self.throwError(Messages.ParameterAfterRestParameter) 2404 2405 return self.finalize(node, Node.RestElement(arg)) 2406 2407 def parseFormalParameter(self, options): 2408 params = [] 2409 param = self.parseRestElement(params) if self.match('...') else self.parsePatternWithDefault(params) 2410 for p in params: 2411 self.validateParam(options, p, p.value) 2412 options.simple = options.simple and isinstance(param, Node.Identifier) 2413 options.params.append(param) 2414 2415 def parseFormalParameters(self, firstRestricted=None): 2416 options = Params( 2417 simple=True, 2418 params=[], 2419 firstRestricted=firstRestricted 2420 ) 2421 2422 self.expect('(') 2423 if not self.match(')'): 2424 options.paramSet = {} 2425 while self.lookahead.type is not Token.EOF: 2426 self.parseFormalParameter(options) 2427 if self.match(')'): 2428 break 2429 self.expect(',') 2430 if self.match(')'): 2431 break 2432 self.expect(')') 2433 2434 return Params( 2435 simple=options.simple, 2436 params=options.params, 2437 stricted=options.stricted, 2438 firstRestricted=options.firstRestricted, 2439 message=options.message 2440 ) 2441 2442 def matchAsyncFunction(self): 2443 match = self.matchContextualKeyword('async') 2444 if match: 2445 state = self.scanner.saveState() 2446 self.scanner.scanComments() 2447 next = self.scanner.lex() 2448 self.scanner.restoreState(state) 2449 2450 match = (state.lineNumber == next.lineNumber) and (next.type is Token.Keyword) and (next.value == 'function') 2451 2452 return match 2453 2454 def parseFunctionDeclaration(self, identifierIsOptional=False): 2455 node = self.createNode() 2456 2457 isAsync = self.matchContextualKeyword('async') 2458 if isAsync: 2459 self.nextToken() 2460 2461 self.expectKeyword('function') 2462 2463 isGenerator = False if isAsync else self.match('*') 2464 if isGenerator: 2465 self.nextToken() 2466 2467 id = None 2468 firstRestricted = None 2469 2470 if not identifierIsOptional or not self.match('('): 2471 token = self.lookahead 2472 id = self.parseVariableIdentifier() 2473 if self.context.strict: 2474 if self.scanner.isRestrictedWord(token.value): 2475 self.tolerateUnexpectedToken(token, Messages.StrictFunctionName) 2476 else: 2477 if self.scanner.isRestrictedWord(token.value): 2478 firstRestricted = token 2479 message = Messages.StrictFunctionName 2480 elif self.scanner.isStrictModeReservedWord(token.value): 2481 firstRestricted = token 2482 message = Messages.StrictReservedWord 2483 2484 previousAllowAwait = self.context.allowAwait 2485 previousAllowYield = self.context.allowYield 2486 self.context.allowAwait = isAsync 2487 self.context.allowYield = not isGenerator 2488 2489 formalParameters = self.parseFormalParameters(firstRestricted) 2490 params = formalParameters.params 2491 stricted = formalParameters.stricted 2492 firstRestricted = formalParameters.firstRestricted 2493 if formalParameters.message: 2494 message = formalParameters.message 2495 2496 previousStrict = self.context.strict 2497 previousAllowStrictDirective = self.context.allowStrictDirective 2498 self.context.allowStrictDirective = formalParameters.simple 2499 body = self.parseFunctionSourceElements() 2500 if self.context.strict and firstRestricted: 2501 self.throwUnexpectedToken(firstRestricted, message) 2502 if self.context.strict and stricted: 2503 self.tolerateUnexpectedToken(stricted, message) 2504 2505 self.context.strict = previousStrict 2506 self.context.allowStrictDirective = previousAllowStrictDirective 2507 self.context.allowAwait = previousAllowAwait 2508 self.context.allowYield = previousAllowYield 2509 2510 if isAsync: 2511 return self.finalize(node, Node.AsyncFunctionDeclaration(id, params, body)) 2512 2513 return self.finalize(node, Node.FunctionDeclaration(id, params, body, isGenerator)) 2514 2515 def parseFunctionExpression(self): 2516 node = self.createNode() 2517 2518 isAsync = self.matchContextualKeyword('async') 2519 if isAsync: 2520 self.nextToken() 2521 2522 self.expectKeyword('function') 2523 2524 isGenerator = False if isAsync else self.match('*') 2525 if isGenerator: 2526 self.nextToken() 2527 2528 id = None 2529 firstRestricted = None 2530 2531 previousAllowAwait = self.context.allowAwait 2532 previousAllowYield = self.context.allowYield 2533 self.context.allowAwait = isAsync 2534 self.context.allowYield = not isGenerator 2535 2536 if not self.match('('): 2537 token = self.lookahead 2538 id = self.parseIdentifierName() if not self.context.strict and not isGenerator and self.matchKeyword('yield') else self.parseVariableIdentifier() 2539 if self.context.strict: 2540 if self.scanner.isRestrictedWord(token.value): 2541 self.tolerateUnexpectedToken(token, Messages.StrictFunctionName) 2542 else: 2543 if self.scanner.isRestrictedWord(token.value): 2544 firstRestricted = token 2545 message = Messages.StrictFunctionName 2546 elif self.scanner.isStrictModeReservedWord(token.value): 2547 firstRestricted = token 2548 message = Messages.StrictReservedWord 2549 2550 formalParameters = self.parseFormalParameters(firstRestricted) 2551 params = formalParameters.params 2552 stricted = formalParameters.stricted 2553 firstRestricted = formalParameters.firstRestricted 2554 if formalParameters.message: 2555 message = formalParameters.message 2556 2557 previousStrict = self.context.strict 2558 previousAllowStrictDirective = self.context.allowStrictDirective 2559 self.context.allowStrictDirective = formalParameters.simple 2560 body = self.parseFunctionSourceElements() 2561 if self.context.strict and firstRestricted: 2562 self.throwUnexpectedToken(firstRestricted, message) 2563 if self.context.strict and stricted: 2564 self.tolerateUnexpectedToken(stricted, message) 2565 self.context.strict = previousStrict 2566 self.context.allowStrictDirective = previousAllowStrictDirective 2567 self.context.allowAwait = previousAllowAwait 2568 self.context.allowYield = previousAllowYield 2569 2570 if isAsync: 2571 return self.finalize(node, Node.AsyncFunctionExpression(id, params, body)) 2572 2573 return self.finalize(node, Node.FunctionExpression(id, params, body, isGenerator)) 2574 2575 # https://tc39.github.io/ecma262/#sec-directive-prologues-and-the-use-strict-directive 2576 2577 def parseDirective(self): 2578 token = self.lookahead 2579 2580 node = self.createNode() 2581 expr = self.parseExpression() 2582 directive = self.getTokenRaw(token)[1:-1] if expr.type is Syntax.Literal else None 2583 self.consumeSemicolon() 2584 2585 return self.finalize(node, Node.Directive(expr, directive) if directive else Node.ExpressionStatement(expr)) 2586 2587 def parseDirectivePrologues(self): 2588 firstRestricted = None 2589 2590 body = [] 2591 while True: 2592 token = self.lookahead 2593 if token.type is not Token.StringLiteral: 2594 break 2595 2596 statement = self.parseDirective() 2597 body.append(statement) 2598 directive = statement.directive 2599 if not isinstance(directive, basestring): 2600 break 2601 2602 if directive == 'use strict': 2603 self.context.strict = True 2604 if firstRestricted: 2605 self.tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral) 2606 if not self.context.allowStrictDirective: 2607 self.tolerateUnexpectedToken(token, Messages.IllegalLanguageModeDirective) 2608 else: 2609 if not firstRestricted and token.octal: 2610 firstRestricted = token 2611 2612 return body 2613 2614 # https://tc39.github.io/ecma262/#sec-method-definitions 2615 2616 def qualifiedPropertyName(self, token): 2617 typ = token.type 2618 if typ in ( 2619 Token.Identifier, 2620 Token.StringLiteral, 2621 Token.BooleanLiteral, 2622 Token.NullLiteral, 2623 Token.NumericLiteral, 2624 Token.Keyword, 2625 ): 2626 return True 2627 elif typ is Token.Punctuator: 2628 return token.value == '[' 2629 return False 2630 2631 def parseGetterMethod(self): 2632 node = self.createNode() 2633 2634 isGenerator = False 2635 previousAllowYield = self.context.allowYield 2636 self.context.allowYield = not isGenerator 2637 formalParameters = self.parseFormalParameters() 2638 if len(formalParameters.params) > 0: 2639 self.tolerateError(Messages.BadGetterArity) 2640 method = self.parsePropertyMethod(formalParameters) 2641 self.context.allowYield = previousAllowYield 2642 2643 return self.finalize(node, Node.FunctionExpression(None, formalParameters.params, method, isGenerator)) 2644 2645 def parseSetterMethod(self): 2646 node = self.createNode() 2647 2648 isGenerator = False 2649 previousAllowYield = self.context.allowYield 2650 self.context.allowYield = not isGenerator 2651 formalParameters = self.parseFormalParameters() 2652 if len(formalParameters.params) != 1: 2653 self.tolerateError(Messages.BadSetterArity) 2654 elif isinstance(formalParameters.params[0], Node.RestElement): 2655 self.tolerateError(Messages.BadSetterRestParameter) 2656 method = self.parsePropertyMethod(formalParameters) 2657 self.context.allowYield = previousAllowYield 2658 2659 return self.finalize(node, Node.FunctionExpression(None, formalParameters.params, method, isGenerator)) 2660 2661 def parseGeneratorMethod(self): 2662 node = self.createNode() 2663 2664 isGenerator = True 2665 previousAllowYield = self.context.allowYield 2666 2667 self.context.allowYield = True 2668 params = self.parseFormalParameters() 2669 self.context.allowYield = False 2670 method = self.parsePropertyMethod(params) 2671 self.context.allowYield = previousAllowYield 2672 2673 return self.finalize(node, Node.FunctionExpression(None, params.params, method, isGenerator)) 2674 2675 # https://tc39.github.io/ecma262/#sec-generator-function-definitions 2676 2677 def isStartOfExpression(self): 2678 start = True 2679 2680 value = self.lookahead.value 2681 typ = self.lookahead.type 2682 if typ is Token.Punctuator: 2683 start = value in ('[', '(', '{', '+', '-', '!', '~', '++', '--', '/', '/=') # regular expression literal ) 2684 2685 elif typ is Token.Keyword: 2686 start = value in ('class', 'delete', 'function', 'let', 'new', 'super', 'this', 'typeof', 'void', 'yield') 2687 2688 return start 2689 2690 def parseYieldExpression(self): 2691 node = self.createNode() 2692 self.expectKeyword('yield') 2693 2694 argument = None 2695 delegate = False 2696 if not self.hasLineTerminator: 2697 previousAllowYield = self.context.allowYield 2698 self.context.allowYield = False 2699 delegate = self.match('*') 2700 if delegate: 2701 self.nextToken() 2702 argument = self.parseAssignmentExpression() 2703 elif self.isStartOfExpression(): 2704 argument = self.parseAssignmentExpression() 2705 self.context.allowYield = previousAllowYield 2706 2707 return self.finalize(node, Node.YieldExpression(argument, delegate)) 2708 2709 # https://tc39.github.io/ecma262/#sec-class-definitions 2710 2711 def parseClassElement(self, hasConstructor): 2712 token = self.lookahead 2713 node = self.createNode() 2714 2715 kind = '' 2716 key = None 2717 value = None 2718 computed = False 2719 isStatic = False 2720 isAsync = False 2721 2722 if self.match('*'): 2723 self.nextToken() 2724 2725 else: 2726 computed = self.match('[') 2727 key = self.parseObjectPropertyKey() 2728 id = key 2729 if id.name == 'static' and (self.qualifiedPropertyName(self.lookahead) or self.match('*')): 2730 token = self.lookahead 2731 isStatic = True 2732 computed = self.match('[') 2733 if self.match('*'): 2734 self.nextToken() 2735 else: 2736 key = self.parseObjectPropertyKey() 2737 if token.type is Token.Identifier and not self.hasLineTerminator and token.value == 'async': 2738 punctuator = self.lookahead.value 2739 if punctuator != ':' and punctuator != '(' and punctuator != '*': 2740 isAsync = True 2741 token = self.lookahead 2742 key = self.parseObjectPropertyKey() 2743 if token.type is Token.Identifier and token.value == 'constructor': 2744 self.tolerateUnexpectedToken(token, Messages.ConstructorIsAsync) 2745 2746 lookaheadPropertyKey = self.qualifiedPropertyName(self.lookahead) 2747 if token.type is Token.Identifier: 2748 if token.value == 'get' and lookaheadPropertyKey: 2749 kind = 'get' 2750 computed = self.match('[') 2751 key = self.parseObjectPropertyKey() 2752 self.context.allowYield = False 2753 value = self.parseGetterMethod() 2754 elif token.value == 'set' and lookaheadPropertyKey: 2755 kind = 'set' 2756 computed = self.match('[') 2757 key = self.parseObjectPropertyKey() 2758 value = self.parseSetterMethod() 2759 elif self.config.classProperties and not self.match('('): 2760 kind = 'init' 2761 id = self.finalize(node, Node.Identifier(token.value)) 2762 if self.match('='): 2763 self.nextToken() 2764 value = self.parseAssignmentExpression() 2765 2766 elif token.type is Token.Punctuator and token.value == '*' and lookaheadPropertyKey: 2767 kind = 'method' 2768 computed = self.match('[') 2769 key = self.parseObjectPropertyKey() 2770 value = self.parseGeneratorMethod() 2771 2772 if not kind and key and self.match('('): 2773 kind = 'method' 2774 value = self.parsePropertyMethodAsyncFunction() if isAsync else self.parsePropertyMethodFunction() 2775 2776 if not kind: 2777 self.throwUnexpectedToken(self.lookahead) 2778 2779 if not computed: 2780 if isStatic and self.isPropertyKey(key, 'prototype'): 2781 self.throwUnexpectedToken(token, Messages.StaticPrototype) 2782 if not isStatic and self.isPropertyKey(key, 'constructor'): 2783 if kind != 'method' or (value and value.generator): 2784 self.throwUnexpectedToken(token, Messages.ConstructorSpecialMethod) 2785 if hasConstructor.value: 2786 self.throwUnexpectedToken(token, Messages.DuplicateConstructor) 2787 else: 2788 hasConstructor.value = True 2789 kind = 'constructor' 2790 2791 if kind in ('constructor', 'method', 'get', 'set'): 2792 return self.finalize(node, Node.MethodDefinition(key, computed, value, kind, isStatic)) 2793 2794 else: 2795 return self.finalize(node, Node.FieldDefinition(key, computed, value, kind, isStatic)) 2796 2797 def parseClassElementList(self): 2798 body = [] 2799 hasConstructor = Value(False) 2800 2801 self.expect('{') 2802 while not self.match('}'): 2803 if self.match(';'): 2804 self.nextToken() 2805 else: 2806 body.append(self.parseClassElement(hasConstructor)) 2807 self.expect('}') 2808 2809 return body 2810 2811 def parseClassBody(self): 2812 node = self.createNode() 2813 elementList = self.parseClassElementList() 2814 2815 return self.finalize(node, Node.ClassBody(elementList)) 2816 2817 def parseClassDeclaration(self, identifierIsOptional=False): 2818 node = self.createNode() 2819 2820 previousStrict = self.context.strict 2821 self.context.strict = True 2822 self.expectKeyword('class') 2823 2824 id = None if identifierIsOptional and self.lookahead.type is not Token.Identifier else self.parseVariableIdentifier() 2825 superClass = None 2826 if self.matchKeyword('extends'): 2827 self.nextToken() 2828 superClass = self.isolateCoverGrammar(self.parseLeftHandSideExpressionAllowCall) 2829 classBody = self.parseClassBody() 2830 self.context.strict = previousStrict 2831 2832 return self.finalize(node, Node.ClassDeclaration(id, superClass, classBody)) 2833 2834 def parseClassExpression(self): 2835 node = self.createNode() 2836 2837 previousStrict = self.context.strict 2838 self.context.strict = True 2839 self.expectKeyword('class') 2840 id = self.parseVariableIdentifier() if self.lookahead.type is Token.Identifier else None 2841 superClass = None 2842 if self.matchKeyword('extends'): 2843 self.nextToken() 2844 superClass = self.isolateCoverGrammar(self.parseLeftHandSideExpressionAllowCall) 2845 classBody = self.parseClassBody() 2846 self.context.strict = previousStrict 2847 2848 return self.finalize(node, Node.ClassExpression(id, superClass, classBody)) 2849 2850 # https://tc39.github.io/ecma262/#sec-scripts 2851 # https://tc39.github.io/ecma262/#sec-modules 2852 2853 def parseModule(self): 2854 self.context.strict = True 2855 self.context.isModule = True 2856 self.scanner.isModule = True 2857 node = self.createNode() 2858 body = self.parseDirectivePrologues() 2859 while self.lookahead.type is not Token.EOF: 2860 body.append(self.parseStatementListItem()) 2861 return self.finalize(node, Node.Module(body)) 2862 2863 def parseScript(self): 2864 node = self.createNode() 2865 body = self.parseDirectivePrologues() 2866 while self.lookahead.type is not Token.EOF: 2867 body.append(self.parseStatementListItem()) 2868 return self.finalize(node, Node.Script(body)) 2869 2870 # https://tc39.github.io/ecma262/#sec-imports 2871 2872 def parseModuleSpecifier(self): 2873 node = self.createNode() 2874 2875 if self.lookahead.type is not Token.StringLiteral: 2876 self.throwError(Messages.InvalidModuleSpecifier) 2877 2878 token = self.nextToken() 2879 raw = self.getTokenRaw(token) 2880 return self.finalize(node, Node.Literal(token.value, raw)) 2881 2882 # import {<foo as bar>} ... 2883 def parseImportSpecifier(self): 2884 node = self.createNode() 2885 2886 if self.lookahead.type is Token.Identifier: 2887 imported = self.parseVariableIdentifier() 2888 local = imported 2889 if self.matchContextualKeyword('as'): 2890 self.nextToken() 2891 local = self.parseVariableIdentifier() 2892 else: 2893 imported = self.parseIdentifierName() 2894 local = imported 2895 if self.matchContextualKeyword('as'): 2896 self.nextToken() 2897 local = self.parseVariableIdentifier() 2898 else: 2899 self.throwUnexpectedToken(self.nextToken()) 2900 2901 return self.finalize(node, Node.ImportSpecifier(local, imported)) 2902 2903 # {foo, bar as bas 2904 def parseNamedImports(self): 2905 self.expect('{') 2906 specifiers = [] 2907 while not self.match('}'): 2908 specifiers.append(self.parseImportSpecifier()) 2909 if not self.match('}'): 2910 self.expect(',') 2911 self.expect('}') 2912 2913 return specifiers 2914 2915 # import <foo> ... 2916 def parseImportDefaultSpecifier(self): 2917 node = self.createNode() 2918 local = self.parseIdentifierName() 2919 return self.finalize(node, Node.ImportDefaultSpecifier(local)) 2920 2921 # import <* as foo> ... 2922 def parseImportNamespaceSpecifier(self): 2923 node = self.createNode() 2924 2925 self.expect('*') 2926 if not self.matchContextualKeyword('as'): 2927 self.throwError(Messages.NoAsAfterImportNamespace) 2928 self.nextToken() 2929 local = self.parseIdentifierName() 2930 2931 return self.finalize(node, Node.ImportNamespaceSpecifier(local)) 2932 2933 def parseImportDeclaration(self): 2934 if self.context.inFunctionBody: 2935 self.throwError(Messages.IllegalImportDeclaration) 2936 2937 node = self.createNode() 2938 self.expectKeyword('import') 2939 2940 specifiers = [] 2941 if self.lookahead.type is Token.StringLiteral: 2942 # import 'foo' 2943 src = self.parseModuleSpecifier() 2944 else: 2945 if self.match('{'): 2946 # import {bar 2947 specifiers.extend(self.parseNamedImports()) 2948 elif self.match('*'): 2949 # import * as foo 2950 specifiers.append(self.parseImportNamespaceSpecifier()) 2951 elif self.isIdentifierName(self.lookahead) and not self.matchKeyword('default'): 2952 # import foo 2953 specifiers.append(self.parseImportDefaultSpecifier()) 2954 if self.match(','): 2955 self.nextToken() 2956 if self.match('*'): 2957 # import foo, * as foo 2958 specifiers.append(self.parseImportNamespaceSpecifier()) 2959 elif self.match('{'): 2960 # import foo, {bar 2961 specifiers.extend(self.parseNamedImports()) 2962 else: 2963 self.throwUnexpectedToken(self.lookahead) 2964 else: 2965 self.throwUnexpectedToken(self.nextToken()) 2966 2967 if not self.matchContextualKeyword('from'): 2968 message = Messages.UnexpectedToken if self.lookahead.value else Messages.MissingFromClause 2969 self.throwError(message, self.lookahead.value) 2970 self.nextToken() 2971 src = self.parseModuleSpecifier() 2972 self.consumeSemicolon() 2973 2974 return self.finalize(node, Node.ImportDeclaration(specifiers, src)) 2975 2976 # https://tc39.github.io/ecma262/#sec-exports 2977 2978 def parseExportSpecifier(self): 2979 node = self.createNode() 2980 2981 local = self.parseIdentifierName() 2982 exported = local 2983 if self.matchContextualKeyword('as'): 2984 self.nextToken() 2985 exported = self.parseIdentifierName() 2986 2987 return self.finalize(node, Node.ExportSpecifier(local, exported)) 2988 2989 def parseExportDefaultSpecifier(self): 2990 node = self.createNode() 2991 local = self.parseIdentifierName() 2992 return self.finalize(node, Node.ExportDefaultSpecifier(local)) 2993 2994 def parseExportDeclaration(self): 2995 if self.context.inFunctionBody: 2996 self.throwError(Messages.IllegalExportDeclaration) 2997 2998 node = self.createNode() 2999 self.expectKeyword('export') 3000 3001 if self.matchKeyword('default'): 3002 # export default ... 3003 self.nextToken() 3004 if self.matchKeyword('function'): 3005 # export default function foo (: 3006 # export default function (: 3007 declaration = self.parseFunctionDeclaration(True) 3008 exportDeclaration = self.finalize(node, Node.ExportDefaultDeclaration(declaration)) 3009 elif self.matchKeyword('class'): 3010 # export default class foo { 3011 declaration = self.parseClassDeclaration(True) 3012 exportDeclaration = self.finalize(node, Node.ExportDefaultDeclaration(declaration)) 3013 elif self.matchContextualKeyword('async'): 3014 # export default async function f (: 3015 # export default async function (: 3016 # export default async x => x 3017 declaration = self.parseFunctionDeclaration(True) if self.matchAsyncFunction() else self.parseAssignmentExpression() 3018 exportDeclaration = self.finalize(node, Node.ExportDefaultDeclaration(declaration)) 3019 else: 3020 if self.matchContextualKeyword('from'): 3021 self.throwError(Messages.UnexpectedToken, self.lookahead.value) 3022 # export default {} 3023 # export default [] 3024 # export default (1 + 2) 3025 if self.match('{'): 3026 declaration = self.parseObjectInitializer() 3027 elif self.match('['): 3028 declaration = self.parseArrayInitializer() 3029 else: 3030 declaration = self.parseAssignmentExpression() 3031 self.consumeSemicolon() 3032 exportDeclaration = self.finalize(node, Node.ExportDefaultDeclaration(declaration)) 3033 3034 elif self.match('*'): 3035 # export * from 'foo' 3036 self.nextToken() 3037 if not self.matchContextualKeyword('from'): 3038 message = Messages.UnexpectedToken if self.lookahead.value else Messages.MissingFromClause 3039 self.throwError(message, self.lookahead.value) 3040 self.nextToken() 3041 src = self.parseModuleSpecifier() 3042 self.consumeSemicolon() 3043 exportDeclaration = self.finalize(node, Node.ExportAllDeclaration(src)) 3044 3045 elif self.lookahead.type is Token.Keyword: 3046 # export var f = 1 3047 value = self.lookahead.value 3048 if value in ( 3049 'let', 3050 'const', 3051 ): 3052 declaration = self.parseLexicalDeclaration(Params(inFor=False)) 3053 elif value in ( 3054 'var', 3055 'class', 3056 'function', 3057 ): 3058 declaration = self.parseStatementListItem() 3059 else: 3060 self.throwUnexpectedToken(self.lookahead) 3061 exportDeclaration = self.finalize(node, Node.ExportNamedDeclaration(declaration, [], None)) 3062 3063 elif self.matchAsyncFunction(): 3064 declaration = self.parseFunctionDeclaration() 3065 exportDeclaration = self.finalize(node, Node.ExportNamedDeclaration(declaration, [], None)) 3066 3067 else: 3068 specifiers = [] 3069 source = None 3070 isExportFromIdentifier = False 3071 3072 expectSpecifiers = True 3073 if self.lookahead.type is Token.Identifier: 3074 specifiers.append(self.parseExportDefaultSpecifier()) 3075 if self.match(','): 3076 self.nextToken() 3077 else: 3078 expectSpecifiers = False 3079 3080 if expectSpecifiers: 3081 self.expect('{') 3082 while not self.match('}'): 3083 isExportFromIdentifier = isExportFromIdentifier or self.matchKeyword('default') 3084 specifiers.append(self.parseExportSpecifier()) 3085 if not self.match('}'): 3086 self.expect(',') 3087 self.expect('}') 3088 3089 if self.matchContextualKeyword('from'): 3090 # export {default} from 'foo' 3091 # export {foo} from 'foo' 3092 self.nextToken() 3093 source = self.parseModuleSpecifier() 3094 self.consumeSemicolon() 3095 elif isExportFromIdentifier: 3096 # export {default}; # missing fromClause 3097 message = Messages.UnexpectedToken if self.lookahead.value else Messages.MissingFromClause 3098 self.throwError(message, self.lookahead.value) 3099 else: 3100 # export {foo} 3101 self.consumeSemicolon() 3102 exportDeclaration = self.finalize(node, Node.ExportNamedDeclaration(None, specifiers, source)) 3103 3104 return exportDeclaration 3105