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